PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/controllers/core/Route.php

https://bitbucket.org/taras_bodnar/hw
PHP | 294 lines | 219 code | 24 blank | 51 comment | 15 complexity | e617c2a621382cfef534491e61cf7c50 MD5 | raw file
  1. <?php
  2. /**
  3. * OYiEngine 6.x
  4. * Company Otakoyi.com
  5. * Author wmgodyak mailto:wmgodyak@gmail.com
  6. * Date: 07.05.14 21:56
  7. */
  8. namespace controllers\core;
  9. if ( !defined('SYSPATH') ) die();
  10. class Route {
  11. const HEADER_404 = 'HTTP/1.0 404 Not Found';
  12. const HEADER_301 = 'HTTP/1.1 301 Moved Permanently';
  13. /**
  14. * Local storage
  15. * */
  16. private $storage;
  17. /**
  18. * The URI pattern the route responds to.
  19. *
  20. * @var string
  21. */
  22. protected $uri;
  23. protected $placeholder=array(
  24. '/:module' =>'/([a-zA-Z]+)',
  25. '/:controller' => '/([a-zA-Z]+)',
  26. '/:action' =>'/([a-zA-Z]+)',
  27. ':params' =>'(.*)',
  28. '/:namespace' =>'([a-zA-Z]+)',
  29. '/:int' =>'/([0-9]+)',
  30. // '(' => '(?:',
  31. // '/)' => '/)?',
  32. '~|' => '(?:',
  33. '|~' => '/)?'
  34. );
  35. /**
  36. * тут будуть записуватись правила маршрутизації
  37. * @var array
  38. * */
  39. private $rules;
  40. public function __construct($uri)
  41. {
  42. // clear globals
  43. $this->uri = self::protect($uri);
  44. }
  45. public function add($pattern,$rule)
  46. {
  47. if (strpos($pattern, '(') !== FALSE) {
  48. $pattern = strtr($pattern,$this->placeholder);
  49. }
  50. $this->rules[] = array($pattern,$rule);
  51. }
  52. /**
  53. * Додає роутер
  54. * @param string $regex
  55. * @param string $namespace
  56. * @param string $params
  57. * @return $this
  58. */
  59. public function set($regex, $namespace , $params ='')
  60. {
  61. $this->rules[] = array(
  62. 'params' => $params,
  63. 'regex' => $regex,
  64. 'namespace' => $namespace
  65. );
  66. return $this;
  67. }
  68. public function get(){
  69. return $this->rules;
  70. }
  71. /**
  72. * Setter method
  73. * @param string $index
  74. * @param mixed $value
  75. */
  76. public function __set($index, $value)
  77. {
  78. $this->storage[$index] = $value;
  79. }
  80. /**
  81. * Getter method
  82. * @param string $index
  83. * @return array
  84. */
  85. public function __get($index)
  86. {
  87. return isset($this->storage[$index]) ? $this->storage[$index] : null;
  88. }
  89. public function run()
  90. {
  91. $request = Request::instance();
  92. $routes = $this->get();
  93. // echo '<pre>';
  94. // print_r($routes);
  95. // echo '<pre>';
  96. // die;
  97. // echo '<pre>URI: '; echo $this->uri, '<br>';
  98. if(strpos($this->uri, '?')){
  99. $a = explode('?', $this->uri);
  100. $this->uri=$a[0];
  101. foreach ($_GET as $k=>$v) {
  102. $request->param($k,$v);
  103. }
  104. }
  105. foreach ($routes as $route) {
  106. if(preg_match("@^" . $route['regex'] . "$@u",$this->uri,$matches)){
  107. // echo '<pre>FOUND:'; print_r($route);die;
  108. // echo 'Matches: '; print_r($matches);
  109. if(empty($route['params'])) {
  110. // вирізаю з неймспейсу :controller :action
  111. if(strpos($route['namespace'], ':controller') !== false) {
  112. $s = explode(':', $route['namespace']);
  113. // echo '<b>NS String:</b> ';
  114. // print_r($s);
  115. $this->namespace = $s[0];
  116. if(isset($s[1]) && $s[1] == 'controller') {
  117. $this->controller = $matches[1];
  118. }
  119. if(isset($s[2]) && $s[2] == 'action') {
  120. $this->action = $matches[2];
  121. }
  122. if(isset($matches[3]) && !empty($matches[3])) {
  123. // echo '----------';
  124. $this->params = explode('/', trim($matches[3],'/'));
  125. }
  126. // var_dump($this->params);
  127. } else {
  128. // задано виклик конкретного контрола
  129. $this->controller = substr(strrchr($route['namespace'], '\\'), 1);
  130. $this->namespace = str_replace($this->controller, '', $route['namespace']);
  131. }
  132. } else {
  133. // echo '---<br>Чітко задана назва і послідовнсть параметрів: ';
  134. // чітко задана послідовність параметрів і назви
  135. $this->namespace = $route['namespace'];
  136. $request = Request::instance();
  137. $s = explode('/', $route['params']);
  138. // echo 'Params: '; print_r($s);
  139. foreach ($s as $k=>$param) {
  140. // echo $k, ':', $param,'<br>';
  141. $k++;
  142. if(!isset($matches[$k])) continue;
  143. $request->param($param, $matches[$k]);
  144. }
  145. }
  146. // echo '<br><b>Storage</b>: ';
  147. // print_r($this->storage);
  148. break;
  149. }
  150. }
  151. // save data to request storage
  152. $request->setStorage($this->storage);
  153. $this->route();
  154. }
  155. private final function route()
  156. {
  157. try{
  158. if(empty($this->storage)) return;
  159. $namespace = $this->namespace;
  160. $controller = ucfirst($this->controller);
  161. $action = $this->action == '' ? 'index' : $this->action;
  162. $action = rtrim($action,'/');
  163. $params = $this->params;
  164. // echo '<pre>'; print_r($this->storage); echo '<br>';
  165. $c = $namespace . $controller;
  166. $path= str_replace("\\", "/", $c);
  167. if(!file_exists(DOCROOT . $path . '.php')) {
  168. die('file not exist:' . DOCROOT . $path . '.php');
  169. }
  170. $controller = new $c;
  171. if(!is_callable(array($controller,$action))){
  172. die('File not is_callable: ' . DOCROOT . $path . '.php');
  173. }
  174. // $action = (is_callable(array($controller,$action))) ? $action : 'index';
  175. if(!empty($params)){
  176. $res = call_user_func_array(array($controller,$action),$params);
  177. } else{
  178. $res = call_user_func(array($controller,$action));
  179. }
  180. // save data to request storage
  181. $request = Request::instance();
  182. if($res) $request->body = $res;
  183. } catch (Exceptions $e){
  184. echo $e->showError();
  185. }
  186. }
  187. private static function protect($uri)
  188. {
  189. // '@<script[^>]*\?\>.*?</script>@si',
  190. $tags = array (
  191. '@\'@si',
  192. '@\[\[(.*?)\]\]@si',
  193. '@\[!(.*?)!\]@si',
  194. '@\[\~(.*?)\~\]@si',
  195. '@\[\((.*?)\)\]@si',
  196. '@{{(.*?)}}@si',
  197. '@\[\+(.*?)\+\]@si',
  198. '@\[\*(.*?)\*\]@si'
  199. );
  200. // Null is eval
  201. if (isset($_SERVER['QUERY_STRING']) && strpos(urldecode($_SERVER['QUERY_STRING']), chr(0)) !== false)
  202. die();
  203. // Unregister globals
  204. if (@ ini_get('register_globals')) {
  205. foreach ($_REQUEST as $key => $value) {
  206. $$key = null; // This is NOT paranoid because
  207. unset ($$key); // unset may not work.
  208. }
  209. }
  210. $uri = preg_replace($tags, "", $uri);
  211. $_GET = self::sanitize_gpc($_GET, $tags);
  212. $_POST = self::sanitize_gpc($_POST, $tags);
  213. $_COOKIE = self::sanitize_gpc($_COOKIE, $tags);
  214. $_REQUEST = self::sanitize_gpc($_REQUEST, $tags);
  215. unset($tags,$key,$value);
  216. return $uri;
  217. }
  218. private static function sanitize_gpc($target, $tags, $limit = 4)
  219. {
  220. foreach ($target as $key => $value) {
  221. if (is_array($value) && $limit > 0) {
  222. self::sanitize_gpc($value, $tags, $limit - 1);
  223. } else {
  224. $target[$key] = preg_replace($tags, "", $value);
  225. }
  226. }
  227. return $target;
  228. }
  229. /**
  230. * redirect to url vs headers
  231. * @param $url
  232. * @param string $header
  233. */
  234. public static function redirect($url, $header = '')
  235. {
  236. if(!empty($header)) {
  237. header ($header);
  238. }
  239. header("Location: {$url}"); die;
  240. }
  241. }