Route.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. <?php
  2. /**
  3. * Pimf
  4. *
  5. * @copyright Copyright (c) Gjero Krsteski (http://krsteski.de)
  6. * @license http://krsteski.de/new-bsd-license New BSD License
  7. */
  8. namespace Pimf;
  9. /**
  10. * Route
  11. *
  12. * This class is a relationship of HTTP method(s), an HTTP URI to create
  13. * a Pimf application route. The Pimf application will determine
  14. * the one Route object to dispatch for the current HTTP request.
  15. *
  16. * Each route object will have a URI pattern. This pattern must match the
  17. * current HTTP request's URI for the route object to be dispatched by
  18. * the Pimf application. The route pattern may contain parameters, segments
  19. * prefixed with a colon (:). For example:
  20. *
  21. * /controller/:action/:id
  22. *
  23. * When the route is dispatched, it's parameters array will be populated
  24. * with the values of the corresponding HTTP request URI segments.
  25. *
  26. * @package Pimf
  27. * @author Gjero Krsteski <[email protected]>
  28. */
  29. class Route
  30. {
  31. /**
  32. * @var bool
  33. */
  34. private $matched = true;
  35. /**
  36. * @var array
  37. */
  38. private $params = array();
  39. /**
  40. * The route pattern (e.g. "/controller/:action/:id")
  41. *
  42. * @var string
  43. */
  44. private $rule;
  45. /**
  46. * Array of URL parameter names
  47. *
  48. * @var array
  49. */
  50. protected $names = array();
  51. /**
  52. * Array of URL parameter names with + at the end
  53. *
  54. * @var array
  55. */
  56. protected $namesPath = array();
  57. /**
  58. * Conditions for this route's URL parameters
  59. *
  60. * @var array
  61. */
  62. private $conditions;
  63. /**
  64. * @param string $rule
  65. * @param array $target
  66. * @param array $conditions
  67. */
  68. public function __construct($rule, array $target = array(), array $conditions = array())
  69. {
  70. $this->rule = $rule;
  71. $this->conditions = $conditions;
  72. //convert URL params into regex patterns, construct a regex for this route, init params
  73. $regex = preg_replace_callback(
  74. '#:([\w]+)\+?#', array($this, 'computeUrlRegex'), str_replace(')', ')?', (string)$rule)
  75. );
  76. if (substr($rule, -1) === '/') {
  77. $regex .= '?';
  78. }
  79. //cache URL params' names and values if this route matches the current HTTP request
  80. $params = array();
  81. if (!preg_match('#^' . $regex . '$#', self::computeUri(), $params)) {
  82. $this->matched = false;
  83. return;
  84. }
  85. foreach ($this->names as $name) {
  86. if (isset($params[$name])) {
  87. if (isset($this->namesPath[$name])) {
  88. $this->params[$name] = explode('/', urldecode($params[$name]));
  89. } else {
  90. $this->params[$name] = urldecode($params[$name]);
  91. }
  92. }
  93. }
  94. foreach ($target as $key => $value) {
  95. $this->params[$key] = $value;
  96. }
  97. }
  98. /**
  99. * @param array $matches
  100. *
  101. * @return string
  102. */
  103. private function computeUrlRegex(array $matches)
  104. {
  105. $this->names[] = $matches[1];
  106. if (isset($this->conditions[$matches[1]])) {
  107. return '(?P<' . $matches[1] . '>' . $this->conditions[$matches[1]] . ')';
  108. }
  109. if (substr($matches[0], -1) === '+') {
  110. $this->namesPath[$matches[1]] = 1;
  111. return '(?P<' . $matches[1] . '>.+)';
  112. }
  113. return '(?P<' . $matches[1] . '>[^/]+)';
  114. }
  115. /**
  116. * @return string
  117. */
  118. private function computeUri()
  119. {
  120. $uri = Registry::get('env')->REQUEST_URI;
  121. $pos = strpos($uri, '?');
  122. if ($pos !== false) {
  123. $uri = substr($uri, 0, $pos);
  124. }
  125. return $uri;
  126. }
  127. /**
  128. * @return boolean
  129. */
  130. public function matches()
  131. {
  132. return $this->matched;
  133. }
  134. /**
  135. * @return array
  136. */
  137. public function getParams()
  138. {
  139. return $this->params;
  140. }
  141. /**
  142. * @return string
  143. */
  144. public function getRule()
  145. {
  146. return $this->rule;
  147. }
  148. }