PageRenderTime 63ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Route/Section/Common.php

https://github.com/visor/nano
PHP | 307 lines | 150 code | 38 blank | 119 comment | 16 complexity | 8be2756819bd5278a274348596e11b49 MD5 | raw file
  1. <?php
  2. namespace Nano\Route\Section;
  3. /**
  4. * @property \Nano\Route\Section\Common|null $parent
  5. */
  6. abstract class Common {
  7. /**
  8. * @var string
  9. */
  10. protected $location;
  11. /**
  12. * @var string
  13. */
  14. protected $module = null;
  15. /**
  16. * @var string
  17. */
  18. protected $suffix = null;
  19. /**
  20. * @var \ArrayObject|\Nano\Route\Section\Common[]
  21. */
  22. protected $sections;
  23. /**
  24. * @var \ArrayObject[]
  25. */
  26. protected $routes;
  27. /**
  28. * @var array
  29. */
  30. protected $params = array();
  31. /**
  32. * @return boolean
  33. * @param string $location
  34. */
  35. abstract public function sectionMatches($location);
  36. /**
  37. * @return string
  38. * @param string $location
  39. */
  40. abstract public function trimSectionLocation($location);
  41. /**
  42. * @param string $location
  43. */
  44. public function __construct($location) {
  45. $this->location = $location;
  46. $this->routes = new \ArrayObject;
  47. $this->sections = new \ArrayObject;
  48. }
  49. /**
  50. * @return \Nano\Route\Section\Common
  51. * @param string $location
  52. *
  53. * @throws \Nano\Exception
  54. */
  55. public static function create($location) {
  56. if ('' === $location || null === $location) {
  57. throw new \Nano\Exception('Section location should not be empty');
  58. }
  59. if (\Nano\Route\Common::PREFIX_REGEXP == $location[0]) {
  60. return new \Nano\Route\Section\RegExp(subStr($location, 1));
  61. }
  62. return new \Nano\Route\Section\StaticLocation($location);
  63. }
  64. /**
  65. * @return \Nano\Route\Section\Common
  66. * @param string $location
  67. *
  68. * @throws \Nano\Exception
  69. */
  70. public function section($location) {
  71. $result = self::create($location);
  72. $this->sections->append($result);
  73. $result->setParent($this);
  74. $result->module($this->module);
  75. $result->suffix($this->suffix);
  76. return $result;
  77. }
  78. /**
  79. * @return \Nano\Route\Section\Common
  80. * @param string $location
  81. * @param string $controller
  82. * @param string $action
  83. * @param array $params
  84. */
  85. public function get($location, $controller = 'index', $action = 'index', array $params = array()) {
  86. return $this->add(__FUNCTION__, $location, $controller, $action, $params);
  87. }
  88. /**
  89. * @return \Nano\Route\Section\Common
  90. * @param string $location
  91. * @param string $controller
  92. * @param string $action
  93. * @param array $params
  94. */
  95. public function post($location, $controller = 'index', $action = 'index', array $params = array()) {
  96. return $this->add(__FUNCTION__, $location, $controller, $action, $params);
  97. }
  98. /**
  99. * @return \Nano\Route\Section\Common
  100. * @param string $method
  101. * @param string $location
  102. * @param string $controller
  103. * @param string $action
  104. * @param array $params
  105. */
  106. public function add($method, $location, $controller = 'index', $action = 'index', array $params = array()) {
  107. $this->addRoute($method, \Nano\Route\Common::create(
  108. $this->buildLocation($location)
  109. , $controller
  110. , $action
  111. , $this->module
  112. , $params
  113. ));
  114. return $this;
  115. }
  116. /**
  117. * @return \Nano\Route\Section\Common|null
  118. */
  119. public function end() {
  120. $result = $this->parent;
  121. unSet($this->parent);
  122. return $result;
  123. }
  124. /**
  125. * @return \Nano\Route\Section\Common
  126. * @param string $value
  127. */
  128. public function module($value) {
  129. $this->module = $value;
  130. return $this;
  131. }
  132. /**
  133. * @return \Nano\Route\Section\Common
  134. * @param string $value
  135. */
  136. public function suffix($value) {
  137. $this->suffix = $value;
  138. return $this;
  139. }
  140. /**
  141. * @return \Nano\Route\Section\Common
  142. * @param string $method
  143. * @param \Nano\Route\Common $route
  144. */
  145. public function addRoute($method, \Nano\Route\Common $route) {
  146. $key = strToLower($method);
  147. if (!$this->routes->offsetExists($key)) {
  148. $this->routes->offsetSet($key, new \ArrayObject());
  149. }
  150. $this->routes->offsetGet($key)->append($route);
  151. return $this;
  152. }
  153. /**
  154. * @return \ArrayObject[]|\ArrayObject
  155. */
  156. public function getRoutes() {
  157. return $this->routes;
  158. }
  159. /**
  160. * @return \Nano\Route\Section\Common[]|\ArrayObject
  161. */
  162. public function getSections() {
  163. return $this->sections;
  164. }
  165. /**
  166. * @return string
  167. */
  168. public function getLocation() {
  169. return $this->location;
  170. }
  171. /**
  172. * @return null|string
  173. */
  174. public function getModule() {
  175. return $this->module;
  176. }
  177. /**
  178. * @return null|string
  179. */
  180. public function getSuffix() {
  181. return $this->suffix;
  182. }
  183. /**
  184. * @return \Nano\Route\Common|null
  185. * @param string $method
  186. * @param string $location
  187. */
  188. public function getFor($method, $location) {
  189. if (!$this->sectionMatches($location)) {
  190. return null;
  191. }
  192. $sectionLocation = $this->trimSectionLocation($location);
  193. if (($result = $this->findSection($method, $sectionLocation)) instanceof \Nano\Route\Common) {
  194. return $result;
  195. }
  196. return $this->findRoute($method, $sectionLocation);
  197. }
  198. public function __sleep() {
  199. return array('sections', 'routes', 'location');
  200. }
  201. /**
  202. * @param \Nano\Route\Section\Common $section
  203. */
  204. protected function setParent(\Nano\Route\Section\Common $section) {
  205. $this->parent = $section;
  206. }
  207. /**
  208. * @return \Nano\Route\Common|null
  209. * @param string $method
  210. * @param string $location
  211. */
  212. protected function findSection($method, $location) {
  213. foreach ($this->sections as $section) {
  214. $section->params = $this->params;
  215. if (($route = $section->getFor($method, $location)) instanceof \Nano\Route\Common) {
  216. return $route;
  217. }
  218. $section->params = array();
  219. }
  220. return null;
  221. }
  222. /**
  223. * @return \Nano\Route\Common|null
  224. * @param string $method
  225. * @param string $location
  226. */
  227. protected function findRoute($method, $location) {
  228. if (!$this->routes->offsetExists($method)) {
  229. return null;
  230. }
  231. foreach ($this->routes->offsetGet($method) as /** @var \Nano\Route\Common $route */ $route) {
  232. if ($route->match($location)) {
  233. $route->addParams($this->params);
  234. return $route;
  235. }
  236. }
  237. return null;
  238. }
  239. /**
  240. * @return string
  241. * @param string $location
  242. */
  243. protected function buildLocation($location) {
  244. $isRegExp = false;
  245. $tests = array($location, $this->suffix);
  246. $parts = array();
  247. foreach ($tests as $part) {
  248. if (null === $part || 0 === strLen($part)) {
  249. continue;
  250. }
  251. if (\Nano\Route\Common::PREFIX_REGEXP === $part[0]) {
  252. $isRegExp = true;
  253. }
  254. $parts[] = $part;
  255. }
  256. if (false === $isRegExp) {
  257. return $location . $this->suffix;
  258. }
  259. $result = '~';
  260. foreach ($parts as $part) {
  261. if (\Nano\Route\Common::PREFIX_REGEXP === (string)$part[0]) {
  262. $result .= str_replace('/', '\/', subStr($part, 1));
  263. } else {
  264. $result .= preg_quote($part, '/');
  265. }
  266. }
  267. return $result;
  268. }
  269. }