/class/Router.php

https://github.com/klj613/klj613micromvc · PHP · 207 lines · 127 code · 23 blank · 57 comment · 10 complexity · 9708079089e54a7b702f40eb320ce0d9 MD5 · raw file

  1. <?php
  2. /**
  3. * This file is part of klj613's micro MVC framework made out of boredom.
  4. *
  5. * (c) Kristian Lewis Jones <klj613@kristianlewisjones.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. /**
  11. * Used to render templates.
  12. *
  13. * @author Kristian Lewis Jones <klj613@kristianlewisjones.com>
  14. */
  15. class Router
  16. {
  17. private $routing;
  18. public $uri;
  19. public $routeId;
  20. /**
  21. * Constructor.
  22. *
  23. * @param array $routing The routing config.
  24. */
  25. public function __construct($routing)
  26. {
  27. $this->routing = $routing;
  28. }
  29. /**
  30. * Initiates the handling of a specific URI.
  31. *
  32. * @param string $uri The URI to handle.
  33. */
  34. public function handleRequest($uri)
  35. {
  36. $this->uri = $uri;
  37. $routeId = $this->matchRouting($uri);
  38. $this->routeId = $routeId;
  39. $params = $this->getParams($uri, $routeId);
  40. list($class, $method) = $this->routing[$routeId][1];
  41. $realClass = $class . 'Controller';
  42. $instance = DIFactory::getController($realClass);
  43. call_user_func_array(array($instance, $method), $params);
  44. }
  45. /**
  46. * Get the routing ID that belongs to a specific URI.
  47. *
  48. * @param string $uri The URI to match.
  49. *
  50. * @throws Exception
  51. */
  52. public function matchRouting($uri)
  53. {
  54. foreach ($this->routing as $rule)
  55. {
  56. $pattern = $rule[0];
  57. $regex = '#' . preg_replace('#{([^/]+)}#', '([a-zA-Z0-9-]+)', $pattern) . '#';
  58. if (preg_match($regex, $uri))
  59. {
  60. return key($this->routing);
  61. }
  62. next($this->routing);
  63. }
  64. throw new Exception("No Routing Found for `$uri`");
  65. }
  66. /**
  67. * Get the parameters off a URI.
  68. *
  69. * @param string $uri
  70. * @param string $routeId
  71. *
  72. * @throws Exception
  73. *
  74. * @return array The parameters of the URI.
  75. */
  76. public function getParams($uri, $routeId)
  77. {
  78. $pattern = $this->routing[$routeId][0];
  79. $regex = '#{([^/]+)}#';
  80. preg_match_all($regex, $pattern, $matchedKeys);
  81. $derivedRegex = preg_replace($regex, '([^/]+)', $pattern);
  82. preg_match_all('#' . $derivedRegex . '#', $uri, $matchedValues);
  83. $structure = $this->getParamsStructure($routeId);
  84. if (count($matchedKeys[0]) == 0)
  85. {
  86. $count = 0;
  87. }
  88. else
  89. {
  90. $count = count($matchedKeys[1]);
  91. }
  92. $realCouunt = count($structure);
  93. if ($count != $realCouunt)
  94. {
  95. throw new Exception("Parameter count on the Routing Pattern doesn't match the controller");
  96. }
  97. $params = array();
  98. for ($i = 0; $i < $count; $i++)
  99. {
  100. $key = $matchedKeys[1][$i];
  101. if (in_array($key, $structure) == false)
  102. {
  103. throw new Exception("Parameter `$key` doesn't exist on the controller");
  104. }
  105. $value = $matchedValues[$i + 1][0];
  106. $params[$key] = $value;
  107. }
  108. return $params;
  109. }
  110. /**
  111. * Get the parameter structure off a controller method.
  112. *
  113. * @param string $routeId
  114. *
  115. * @return array The parameter structure.
  116. */
  117. public function getParamsStructure($routeId)
  118. {
  119. list($controllerClass, $controllerMethod) = $this->routing[$routeId][1];
  120. $controllerRealClass = $controllerClass . 'Controller';
  121. $reflectionClass = new ReflectionClass($controllerRealClass);
  122. $reflectionMethod = $reflectionClass->getMethod($controllerMethod);
  123. $refParams = $reflectionMethod->getParameters();
  124. $realParams = array();
  125. foreach ($refParams as $refParam)
  126. {
  127. $realParams[] = $refParam->name;
  128. }
  129. return $realParams;
  130. }
  131. /**
  132. * Generates URI's that are absolute to the domain.
  133. *
  134. * @param string $routeId
  135. * @param array $params The parameters to insert into the URI.
  136. *
  137. * @throws Exception
  138. *
  139. * @return string The URI.
  140. */
  141. public function generate($routeId, $params = array())
  142. {
  143. if (isset($this->routing[$routeId]) == false)
  144. {
  145. throw new Exception("Route `$routeId` doesn't exist.");
  146. }
  147. $structure = $this->getParamsStructure($routeId);
  148. $count = count($params);
  149. $realCouunt = count($structure);
  150. if ($count != $realCouunt)
  151. {
  152. throw new Exception("Parameter count on the Routing Pattern doesn't match the controller");
  153. }
  154. $uri = $this->routing[$routeId][0];
  155. foreach ($params as $key => $value)
  156. {
  157. if (in_array($key, $structure) == false)
  158. {
  159. throw new Exception("Parameter `$key` doesn't exist on the controller");
  160. }
  161. $uri = str_replace('{' . $key . '}', $value, $uri);
  162. }
  163. $baseUri = dirname($_SERVER['SCRIPT_NAME']) . '/';
  164. return $baseUri . $uri;
  165. }
  166. /**
  167. * Gets the URI off the Global variables.
  168. *
  169. * @static
  170. *
  171. * @return string
  172. */
  173. public static function getUriFromGlobals()
  174. {
  175. return substr($_SERVER['REQUEST_URI'], strlen(dirname($_SERVER['SCRIPT_NAME'])) + 1);
  176. }
  177. }
  178. ?>