Router.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.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. namespace Symfony\Component\Routing;
  11. use Symfony\Component\Config\Loader\LoaderInterface;
  12. use Symfony\Component\Config\ConfigCache;
  13. /**
  14. * The Router class is an example of the integration of all pieces of the
  15. * routing system for easier use.
  16. *
  17. * @author Fabien Potencier <fabien@symfony.com>
  18. */
  19. class Router implements RouterInterface
  20. {
  21. private $matcher;
  22. private $generator;
  23. private $defaults;
  24. private $context;
  25. private $loader;
  26. private $collection;
  27. private $resource;
  28. protected $options;
  29. /**
  30. * Constructor.
  31. *
  32. * Available options:
  33. *
  34. * * cache_dir: The cache directory (or null to disable caching)
  35. * * debug: Whether to enable debugging or not (false by default)
  36. * * resource_type: Type hint for the main resource (optional)
  37. *
  38. * @param LoaderInterface $loader A LoaderInterface instance
  39. * @param mixed $resource The main resource to load
  40. * @param array $options An array of options
  41. * @param RequestContext $context The context
  42. * @param array $defaults The default values
  43. *
  44. * @throws \InvalidArgumentException When unsupported option is provided
  45. */
  46. public function __construct(LoaderInterface $loader, $resource, array $options = array(), RequestContext $context = null, array $defaults = array())
  47. {
  48. $this->loader = $loader;
  49. $this->resource = $resource;
  50. $this->context = null === $context ? new RequestContext() : $context;
  51. $this->defaults = $defaults;
  52. $this->options = array(
  53. 'cache_dir' => null,
  54. 'debug' => false,
  55. 'generator_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator',
  56. 'generator_base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator',
  57. 'generator_dumper_class' => 'Symfony\\Component\\Routing\\Generator\\Dumper\\PhpGeneratorDumper',
  58. 'generator_cache_class' => 'ProjectUrlGenerator',
  59. 'matcher_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher',
  60. 'matcher_base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher',
  61. 'matcher_dumper_class' => 'Symfony\\Component\\Routing\\Matcher\\Dumper\\PhpMatcherDumper',
  62. 'matcher_cache_class' => 'ProjectUrlMatcher',
  63. 'resource_type' => null,
  64. );
  65. // check option names and live merge, if errors are encountered Exception will be thrown
  66. $invalid = array();
  67. $isInvalid = false;
  68. foreach ($options as $key => $value) {
  69. if (array_key_exists($key, $this->options)) {
  70. $this->options[$key] = $value;
  71. } else {
  72. $isInvalid = true;
  73. $invalid[] = $key;
  74. }
  75. }
  76. if ($isInvalid) {
  77. throw new \InvalidArgumentException(sprintf('The Router does not support the following options: \'%s\'.', implode('\', \'', $invalid)));
  78. }
  79. }
  80. /**
  81. * Gets the RouteCollection instance associated with this Router.
  82. *
  83. * @return RouteCollection A RouteCollection instance
  84. */
  85. public function getRouteCollection()
  86. {
  87. if (null === $this->collection) {
  88. $this->collection = $this->loader->load($this->resource, $this->options['resource_type']);
  89. }
  90. return $this->collection;
  91. }
  92. /**
  93. * Sets the request context.
  94. *
  95. * @param RequestContext $context The context
  96. */
  97. public function setContext(RequestContext $context)
  98. {
  99. $this->context = $context;
  100. $this->getMatcher()->setContext($context);
  101. $this->getGenerator()->setContext($context);
  102. }
  103. /**
  104. * Gets the request context.
  105. *
  106. * @return RequestContext The context
  107. */
  108. public function getContext()
  109. {
  110. return $this->context;
  111. }
  112. /**
  113. * Generates a URL from the given parameters.
  114. *
  115. * @param string $name The name of the route
  116. * @param array $parameters An array of parameters
  117. * @param Boolean $absolute Whether to generate an absolute URL
  118. *
  119. * @return string The generated URL
  120. */
  121. public function generate($name, array $parameters = array(), $absolute = false)
  122. {
  123. return $this->getGenerator()->generate($name, $parameters, $absolute);
  124. }
  125. /**
  126. * Tries to match a URL with a set of routes.
  127. *
  128. * Returns false if no route matches the URL.
  129. *
  130. * @param string $url URL to be parsed
  131. *
  132. * @return array|false An array of parameters or false if no route matches
  133. */
  134. public function match($url)
  135. {
  136. return $this->getMatcher()->match($url);
  137. }
  138. /**
  139. * Gets the UrlMatcher instance associated with this Router.
  140. *
  141. * @return UrlMatcherInterface A UrlMatcherInterface instance
  142. */
  143. public function getMatcher()
  144. {
  145. if (null !== $this->matcher) {
  146. return $this->matcher;
  147. }
  148. if (null === $this->options['cache_dir'] || null === $this->options['matcher_cache_class']) {
  149. return $this->matcher = new $this->options['matcher_class']($this->getRouteCollection(), $this->context, $this->defaults);
  150. }
  151. $class = $this->options['matcher_cache_class'];
  152. $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']);
  153. if (!$cache->isFresh($class)) {
  154. $dumper = new $this->options['matcher_dumper_class']($this->getRouteCollection());
  155. $options = array(
  156. 'class' => $class,
  157. 'base_class' => $this->options['matcher_base_class'],
  158. );
  159. $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources());
  160. }
  161. require_once $cache;
  162. return $this->matcher = new $class($this->context, $this->defaults);
  163. }
  164. /**
  165. * Gets the UrlGenerator instance associated with this Router.
  166. *
  167. * @return UrlGeneratorInterface A UrlGeneratorInterface instance
  168. */
  169. public function getGenerator()
  170. {
  171. if (null !== $this->generator) {
  172. return $this->generator;
  173. }
  174. if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) {
  175. return $this->generator = new $this->options['generator_class']($this->getRouteCollection(), $this->context, $this->defaults);
  176. }
  177. $class = $this->options['generator_cache_class'];
  178. $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']);
  179. if (!$cache->isFresh($class)) {
  180. $dumper = new $this->options['generator_dumper_class']($this->getRouteCollection());
  181. $options = array(
  182. 'class' => $class,
  183. 'base_class' => $this->options['generator_base_class'],
  184. );
  185. $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources());
  186. }
  187. require_once $cache;
  188. return $this->generator = new $class($this->context, $this->defaults);
  189. }
  190. }