PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/symfony/symfony/src/Symfony/Component/Routing/Router.php

https://gitlab.com/freebird/WebApp
PHP | 346 lines | 182 code | 48 blank | 116 comment | 21 complexity | 92adec8f908dc7d63991ab2eed322b58 MD5 | raw file
  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. use Psr\Log\LoggerInterface;
  14. use Symfony\Component\Routing\Generator\ConfigurableRequirementsInterface;
  15. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  16. use Symfony\Component\Routing\Generator\Dumper\GeneratorDumperInterface;
  17. use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
  18. use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
  19. use Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface;
  20. use Symfony\Component\HttpFoundation\Request;
  21. use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
  22. /**
  23. * The Router class is an example of the integration of all pieces of the
  24. * routing system for easier use.
  25. *
  26. * @author Fabien Potencier <fabien@symfony.com>
  27. */
  28. class Router implements RouterInterface, RequestMatcherInterface
  29. {
  30. /**
  31. * @var UrlMatcherInterface|null
  32. */
  33. protected $matcher;
  34. /**
  35. * @var UrlGeneratorInterface|null
  36. */
  37. protected $generator;
  38. /**
  39. * @var RequestContext
  40. */
  41. protected $context;
  42. /**
  43. * @var LoaderInterface
  44. */
  45. protected $loader;
  46. /**
  47. * @var RouteCollection|null
  48. */
  49. protected $collection;
  50. /**
  51. * @var mixed
  52. */
  53. protected $resource;
  54. /**
  55. * @var array
  56. */
  57. protected $options = array();
  58. /**
  59. * @var LoggerInterface|null
  60. */
  61. protected $logger;
  62. /**
  63. * @var ExpressionFunctionProviderInterface[]
  64. */
  65. private $expressionLanguageProviders = array();
  66. /**
  67. * Constructor.
  68. *
  69. * @param LoaderInterface $loader A LoaderInterface instance
  70. * @param mixed $resource The main resource to load
  71. * @param array $options An array of options
  72. * @param RequestContext $context The context
  73. * @param LoggerInterface $logger A logger instance
  74. */
  75. public function __construct(LoaderInterface $loader, $resource, array $options = array(), RequestContext $context = null, LoggerInterface $logger = null)
  76. {
  77. $this->loader = $loader;
  78. $this->resource = $resource;
  79. $this->logger = $logger;
  80. $this->context = $context ?: new RequestContext();
  81. $this->setOptions($options);
  82. }
  83. /**
  84. * Sets options.
  85. *
  86. * Available options:
  87. *
  88. * * cache_dir: The cache directory (or null to disable caching)
  89. * * debug: Whether to enable debugging or not (false by default)
  90. * * resource_type: Type hint for the main resource (optional)
  91. *
  92. * @param array $options An array of options
  93. *
  94. * @throws \InvalidArgumentException When unsupported option is provided
  95. */
  96. public function setOptions(array $options)
  97. {
  98. $this->options = array(
  99. 'cache_dir' => null,
  100. 'debug' => false,
  101. 'generator_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator',
  102. 'generator_base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator',
  103. 'generator_dumper_class' => 'Symfony\\Component\\Routing\\Generator\\Dumper\\PhpGeneratorDumper',
  104. 'generator_cache_class' => 'ProjectUrlGenerator',
  105. 'matcher_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher',
  106. 'matcher_base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher',
  107. 'matcher_dumper_class' => 'Symfony\\Component\\Routing\\Matcher\\Dumper\\PhpMatcherDumper',
  108. 'matcher_cache_class' => 'ProjectUrlMatcher',
  109. 'resource_type' => null,
  110. 'strict_requirements' => true,
  111. );
  112. // check option names and live merge, if errors are encountered Exception will be thrown
  113. $invalid = array();
  114. foreach ($options as $key => $value) {
  115. if (array_key_exists($key, $this->options)) {
  116. $this->options[$key] = $value;
  117. } else {
  118. $invalid[] = $key;
  119. }
  120. }
  121. if ($invalid) {
  122. throw new \InvalidArgumentException(sprintf('The Router does not support the following options: "%s".', implode('", "', $invalid)));
  123. }
  124. }
  125. /**
  126. * Sets an option.
  127. *
  128. * @param string $key The key
  129. * @param mixed $value The value
  130. *
  131. * @throws \InvalidArgumentException
  132. */
  133. public function setOption($key, $value)
  134. {
  135. if (!array_key_exists($key, $this->options)) {
  136. throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key));
  137. }
  138. $this->options[$key] = $value;
  139. }
  140. /**
  141. * Gets an option value.
  142. *
  143. * @param string $key The key
  144. *
  145. * @return mixed The value
  146. *
  147. * @throws \InvalidArgumentException
  148. */
  149. public function getOption($key)
  150. {
  151. if (!array_key_exists($key, $this->options)) {
  152. throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key));
  153. }
  154. return $this->options[$key];
  155. }
  156. /**
  157. * {@inheritdoc}
  158. */
  159. public function getRouteCollection()
  160. {
  161. if (null === $this->collection) {
  162. $this->collection = $this->loader->load($this->resource, $this->options['resource_type']);
  163. }
  164. return $this->collection;
  165. }
  166. /**
  167. * {@inheritdoc}
  168. */
  169. public function setContext(RequestContext $context)
  170. {
  171. $this->context = $context;
  172. if (null !== $this->matcher) {
  173. $this->getMatcher()->setContext($context);
  174. }
  175. if (null !== $this->generator) {
  176. $this->getGenerator()->setContext($context);
  177. }
  178. }
  179. /**
  180. * {@inheritdoc}
  181. */
  182. public function getContext()
  183. {
  184. return $this->context;
  185. }
  186. /**
  187. * {@inheritdoc}
  188. */
  189. public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH)
  190. {
  191. return $this->getGenerator()->generate($name, $parameters, $referenceType);
  192. }
  193. /**
  194. * {@inheritdoc}
  195. */
  196. public function match($pathinfo)
  197. {
  198. return $this->getMatcher()->match($pathinfo);
  199. }
  200. /**
  201. * {@inheritdoc}
  202. */
  203. public function matchRequest(Request $request)
  204. {
  205. $matcher = $this->getMatcher();
  206. if (!$matcher instanceof RequestMatcherInterface) {
  207. // fallback to the default UrlMatcherInterface
  208. return $matcher->match($request->getPathInfo());
  209. }
  210. return $matcher->matchRequest($request);
  211. }
  212. /**
  213. * Gets the UrlMatcher instance associated with this Router.
  214. *
  215. * @return UrlMatcherInterface A UrlMatcherInterface instance
  216. */
  217. public function getMatcher()
  218. {
  219. if (null !== $this->matcher) {
  220. return $this->matcher;
  221. }
  222. if (null === $this->options['cache_dir'] || null === $this->options['matcher_cache_class']) {
  223. $this->matcher = new $this->options['matcher_class']($this->getRouteCollection(), $this->context);
  224. if (method_exists($this->matcher, 'addExpressionLanguageProvider')) {
  225. foreach ($this->expressionLanguageProviders as $provider) {
  226. $this->matcher->addExpressionLanguageProvider($provider);
  227. }
  228. }
  229. return $this->matcher;
  230. }
  231. $class = $this->options['matcher_cache_class'];
  232. $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']);
  233. if (!$cache->isFresh()) {
  234. $dumper = $this->getMatcherDumperInstance();
  235. if (method_exists($dumper, 'addExpressionLanguageProvider')) {
  236. foreach ($this->expressionLanguageProviders as $provider) {
  237. $dumper->addExpressionLanguageProvider($provider);
  238. }
  239. }
  240. $options = array(
  241. 'class' => $class,
  242. 'base_class' => $this->options['matcher_base_class'],
  243. );
  244. $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources());
  245. }
  246. require_once $cache;
  247. return $this->matcher = new $class($this->context);
  248. }
  249. /**
  250. * Gets the UrlGenerator instance associated with this Router.
  251. *
  252. * @return UrlGeneratorInterface A UrlGeneratorInterface instance
  253. */
  254. public function getGenerator()
  255. {
  256. if (null !== $this->generator) {
  257. return $this->generator;
  258. }
  259. if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) {
  260. $this->generator = new $this->options['generator_class']($this->getRouteCollection(), $this->context, $this->logger);
  261. } else {
  262. $class = $this->options['generator_cache_class'];
  263. $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']);
  264. if (!$cache->isFresh()) {
  265. $dumper = $this->getGeneratorDumperInstance();
  266. $options = array(
  267. 'class' => $class,
  268. 'base_class' => $this->options['generator_base_class'],
  269. );
  270. $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources());
  271. }
  272. require_once $cache;
  273. $this->generator = new $class($this->context, $this->logger);
  274. }
  275. if ($this->generator instanceof ConfigurableRequirementsInterface) {
  276. $this->generator->setStrictRequirements($this->options['strict_requirements']);
  277. }
  278. return $this->generator;
  279. }
  280. public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
  281. {
  282. $this->expressionLanguageProviders[] = $provider;
  283. }
  284. /**
  285. * @return GeneratorDumperInterface
  286. */
  287. protected function getGeneratorDumperInstance()
  288. {
  289. return new $this->options['generator_dumper_class']($this->getRouteCollection());
  290. }
  291. /**
  292. * @return MatcherDumperInterface
  293. */
  294. protected function getMatcherDumperInstance()
  295. {
  296. return new $this->options['matcher_dumper_class']($this->getRouteCollection());
  297. }
  298. }