router.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. <?php namespace System;
  2. class Router {
  3. /**
  4. * All of the loaded routes.
  5. *
  6. * @var array
  7. */
  8. public static $routes;
  9. /**
  10. * The named routes that have been found so far.
  11. *
  12. * @var array
  13. */
  14. public static $names = array();
  15. /**
  16. * Search a set of routes for the route matching a method and URI.
  17. *
  18. * @param string $method
  19. * @param string $uri
  20. * @return Route
  21. */
  22. public static function route($method, $uri)
  23. {
  24. // --------------------------------------------------------------
  25. // Force the URI to have a forward slash.
  26. // --------------------------------------------------------------
  27. $uri = ($uri != '/') ? '/'.$uri : $uri;
  28. static::$routes = require APP_PATH.'routes'.EXT;
  29. // --------------------------------------------------------------
  30. // Is there an exact match for the request?
  31. // --------------------------------------------------------------
  32. if (isset(static::$routes[$method.' '.$uri]))
  33. {
  34. return new Route(static::$routes[$method.' '.$uri]);
  35. }
  36. // --------------------------------------------------------------
  37. // No exact match... check each route individually.
  38. // --------------------------------------------------------------
  39. foreach (static::$routes as $keys => $callback)
  40. {
  41. // --------------------------------------------------------------
  42. // Only check routes that have multiple URIs or wildcards.
  43. // All other routes would have been caught by a literal match.
  44. // --------------------------------------------------------------
  45. if (strpos($keys, '(') !== false or strpos($keys, ',') !== false )
  46. {
  47. foreach (explode(', ', $keys) as $route)
  48. {
  49. $route = str_replace(':num', '[0-9]+', str_replace(':any', '.+', $route));
  50. if (preg_match('#^'.$route.'$#', $method.' '.$uri))
  51. {
  52. return new Route($callback, static::parameters(explode('/', $uri), explode('/', $route)));
  53. }
  54. }
  55. }
  56. }
  57. }
  58. /**
  59. * Find a route by name.
  60. *
  61. * @param string $name
  62. * @return array
  63. */
  64. public static function find($name)
  65. {
  66. if (array_key_exists($name, static::$names))
  67. {
  68. return static::$names[$name];
  69. }
  70. $arrayIterator = new \RecursiveArrayIterator(static::$routes);
  71. $recursiveIterator = new \RecursiveIteratorIterator($arrayIterator);
  72. foreach ($recursiveIterator as $iterator)
  73. {
  74. $route = $recursiveIterator->getSubIterator();
  75. if ($route['name'] == $name)
  76. {
  77. return static::$names[$name] = array($arrayIterator->key() => iterator_to_array($route));
  78. }
  79. }
  80. }
  81. /**
  82. * Get the parameters that should be passed to the route callback.
  83. *
  84. * @param array $uri_segments
  85. * @param array $route_segments
  86. * @return array
  87. */
  88. private static function parameters($uri_segments, $route_segments)
  89. {
  90. $parameters = array();
  91. for ($i = 0; $i < count($route_segments); $i++)
  92. {
  93. // --------------------------------------------------------------
  94. // Any segment wrapped in parentheses is a parameter.
  95. // --------------------------------------------------------------
  96. if (strpos($route_segments[$i], '(') === 0)
  97. {
  98. $parameters[] = $uri_segments[$i];
  99. }
  100. }
  101. return $parameters;
  102. }
  103. }