PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/fsn-site-central/library/Yab/Controller/Router.php

https://gitlab.com/team_fsn/fsn-php
PHP | 272 lines | 140 code | 116 blank | 16 comment | 29 complexity | be456e6e871c6cfe391014046146b71a MD5 | raw file
  1. <?php
  2. /**
  3. * Yab Framework
  4. *
  5. * @category Yab_Controller
  6. * @package Yab_Controller_Router
  7. * @author Yann BELLUZZI
  8. * @copyright (c) 2010 YBellu
  9. * @license http://www.ybellu.com/yab-framework/license.html
  10. * @link http://www.ybellu.com/yab-framework
  11. */
  12. class Yab_Controller_Router {
  13. private $_file = null;
  14. private $_default_controller = 'Index';
  15. private $_error_controller = 'Error';
  16. private $_default_action = 'index';
  17. final public function setDefaultController($default_controller) {
  18. $this->_default_controller = $default_controller;
  19. return $this;
  20. }
  21. final public function setErrorController($error_controller) {
  22. $this->_error_controller = $error_controller;
  23. return $this;
  24. }
  25. final public function setDefaultAction($default_action) {
  26. $this->_default_action = $default_action;
  27. return $this;
  28. }
  29. final public function getDefaultController() {
  30. return $this->_default_controller;
  31. }
  32. final public function getErrorController() {
  33. return $this->_error_controller;
  34. }
  35. final public function getDefaultAction() {
  36. return $this->_default_action;
  37. }
  38. final public function setFile($file) {
  39. $file = trim((string) $file);
  40. if(!Yab_Loader::getInstance()->isFile($file))
  41. throw new Yab_Exception($file.' is not an existing readable routes file');
  42. $this->_file = $file;
  43. return $this;
  44. }
  45. final public function getFile() {
  46. return $this->_file;
  47. }
  48. final public function route(Yab_Controller_Request $request) {
  49. if(!$request->isRouted() && $this->_file) {
  50. $fh = fopen($this->_file, 'rt', true);
  51. while(!feof($fh) && !$request->isRouted()) {
  52. $route = trim(fgets($fh, 1024));
  53. if(!$route)
  54. continue;
  55. if(strpos($route, '#') === 0)
  56. continue;
  57. if($this->_route($request, $route))
  58. break;
  59. }
  60. fclose($fh);
  61. }
  62. if(!$request->isRouted())
  63. $this->_route($request, $request->getUri().'=', true);
  64. return $this;
  65. }
  66. final private function _route(Yab_Controller_Request $request, $route, $last_route = false) {
  67. $equal = strrpos($route, '=');
  68. if(!is_numeric($equal))
  69. throw new Yab_Exception('"'.$route.'" is not a valid route ( no equal )');
  70. $external = trim(substr($route, 0, $equal));
  71. $internal = trim(substr($route, $equal + 1));
  72. $external_regexp = '#^'.str_replace('\*', '([a-zA-Z0-9_-]*)', preg_quote($external, '#')).'#';
  73. if($internal) {
  74. # We have an internal
  75. $first_comma = strpos($internal, '.');
  76. if(!is_numeric($first_comma))
  77. throw new Yab_Exception('"'.$route.'" is not a valid route ( no dot )');
  78. $opened_parenthesis = strpos($internal, '(');
  79. if(!is_numeric($opened_parenthesis))
  80. throw new Yab_Exception('"'.$route.'" is not a valid route ( no opened_parenthesis )');
  81. $closed_parenthesis = strpos($internal, ')');
  82. if(!is_numeric($closed_parenthesis))
  83. throw new Yab_Exception('"'.$route.'" is not a valid route ( no closed_parenthesis )');
  84. $internal_controller = trim(substr($internal, 0, $first_comma));
  85. $internal_action = trim(substr($internal, $first_comma + 1, $opened_parenthesis - $first_comma - 1));
  86. $internal_params = trim(substr($internal, $opened_parenthesis + 1, $closed_parenthesis - $opened_parenthesis - 1));
  87. if(preg_match_all('#\$[0-9]+#', $internal_params, $match) < substr_count($external, '*'))
  88. throw new Yab_Exception('Wrong paramaeters count in this route');
  89. $internal_params = $internal_params ? array_map('trim', explode(',', $internal_params)) : array();
  90. if($request->getUri()) {
  91. # We have an internal and request has an url
  92. if(!preg_match($external_regexp, $request->getUri(), $matches))
  93. return false;
  94. foreach($internal_params as $key => $value)
  95. $internal_params[$key] = urldecode(preg_match('#^\$([0-9]+)$#', $value, $match) ? $matches[$match[1]] : trim($value, '"\''));
  96. $request->setController($internal_controller);
  97. $request->setAction($internal_action);
  98. $request->setParams($internal_params);
  99. $this->_checkRequest($request);
  100. return true;
  101. }
  102. # We have an internal but request has no url
  103. if($request->getController() != $internal_controller || $request->getAction() != $internal_action || count($request->getParams()) != count($internal_params))
  104. return false;
  105. $i = 1;
  106. $pos = strpos($external, '*');
  107. while(is_numeric($pos)) {
  108. $length = 0;
  109. foreach($internal_params as $key => $internalParam) {
  110. if(!preg_match('#^\$([0-9]+)$#', $internalParam, $match))
  111. continue;
  112. if($i != $match[1])
  113. continue;
  114. $external = substr($external, 0, $pos).$request->getParam($key).substr($external, $pos + 1);
  115. $length = strlen($request->getParam($key));
  116. break;
  117. }
  118. if(!$length)
  119. break;
  120. $pos = strpos($external, '*', $pos + $length);
  121. $i++;
  122. }
  123. $request->setUri($request->getBaseUrl().$external);
  124. return true;
  125. } elseif($request->getUri()) {
  126. # We have no internal, but request has an url
  127. if(!preg_match($external_regexp, $request->getUri(), $matches))
  128. return false;
  129. $parts = trim($request->getUri(false), '/');
  130. $parts = $parts ? explode('/', $parts) : array();
  131. $parts = array_map('urldecode', $parts);
  132. $request->setController(count($parts) ? array_shift($parts) : $this->_default_controller);
  133. $request->setAction(count($parts) ? array_shift($parts) : $this->_default_action);
  134. $request->setParams($parts);
  135. $this->_checkRequest($request);
  136. return true;
  137. } elseif($last_route) {
  138. # We have no internal, and request has no url and it is the last route to route request
  139. $request->setUri($request->getBaseUrl().'/'.$request->getController().'/'.$request->getAction().'/'.implode('/', $request->getParams()));
  140. return true;
  141. }
  142. return false;
  143. }
  144. private function _checkRequest(Yab_Controller_Request $request) {
  145. try {
  146. $class = $request->getControllerClass();
  147. $method = $request->getActionMethod();
  148. if(!class_exists($class) || !method_exists($class, $method))
  149. throw new Yab_Exception('Request does not route to a valid Controller->action, redirecting on the error controller');
  150. } catch(Yab_Exception $e) {
  151. $request->setController($this->_error_controller)->setAction($this->_default_action)->setParams(array());
  152. }
  153. return $this;
  154. }
  155. }
  156. // Do not clause PHP tags unless it is really necessary