|
1 <?php |
|
2 |
|
3 /* |
|
4 * This file is part of the Symfony package. |
|
5 * |
|
6 * (c) Fabien Potencier <fabien@symfony.com> |
|
7 * |
|
8 * For the full copyright and license information, please view the LICENSE |
|
9 * file that was distributed with this source code. |
|
10 */ |
|
11 |
|
12 namespace Symfony\Component\Routing; |
|
13 |
|
14 use Symfony\Component\Config\Loader\LoaderInterface; |
|
15 use Symfony\Component\Config\ConfigCache; |
|
16 |
|
17 /** |
|
18 * The Router class is an example of the integration of all pieces of the |
|
19 * routing system for easier use. |
|
20 * |
|
21 * @author Fabien Potencier <fabien@symfony.com> |
|
22 */ |
|
23 class Router implements RouterInterface |
|
24 { |
|
25 protected $matcher; |
|
26 protected $generator; |
|
27 protected $defaults; |
|
28 protected $context; |
|
29 protected $loader; |
|
30 protected $collection; |
|
31 protected $resource; |
|
32 protected $options; |
|
33 |
|
34 /** |
|
35 * Constructor. |
|
36 * |
|
37 * @param LoaderInterface $loader A LoaderInterface instance |
|
38 * @param mixed $resource The main resource to load |
|
39 * @param array $options An array of options |
|
40 * @param RequestContext $context The context |
|
41 * @param array $defaults The default values |
|
42 */ |
|
43 public function __construct(LoaderInterface $loader, $resource, array $options = array(), RequestContext $context = null, array $defaults = array()) |
|
44 { |
|
45 $this->loader = $loader; |
|
46 $this->resource = $resource; |
|
47 $this->context = null === $context ? new RequestContext() : $context; |
|
48 $this->defaults = $defaults; |
|
49 $this->setOptions($options); |
|
50 } |
|
51 |
|
52 /** |
|
53 * Sets options. |
|
54 * |
|
55 * Available options: |
|
56 * |
|
57 * * cache_dir: The cache directory (or null to disable caching) |
|
58 * * debug: Whether to enable debugging or not (false by default) |
|
59 * * resource_type: Type hint for the main resource (optional) |
|
60 * |
|
61 * @param array $options An array of options |
|
62 * |
|
63 * @throws \InvalidArgumentException When unsupported option is provided |
|
64 */ |
|
65 public function setOptions(array $options) |
|
66 { |
|
67 $this->options = array( |
|
68 'cache_dir' => null, |
|
69 'debug' => false, |
|
70 'generator_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', |
|
71 'generator_base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', |
|
72 'generator_dumper_class' => 'Symfony\\Component\\Routing\\Generator\\Dumper\\PhpGeneratorDumper', |
|
73 'generator_cache_class' => 'ProjectUrlGenerator', |
|
74 'matcher_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', |
|
75 'matcher_base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', |
|
76 'matcher_dumper_class' => 'Symfony\\Component\\Routing\\Matcher\\Dumper\\PhpMatcherDumper', |
|
77 'matcher_cache_class' => 'ProjectUrlMatcher', |
|
78 'resource_type' => null, |
|
79 ); |
|
80 |
|
81 // check option names and live merge, if errors are encountered Exception will be thrown |
|
82 $invalid = array(); |
|
83 $isInvalid = false; |
|
84 foreach ($options as $key => $value) { |
|
85 if (array_key_exists($key, $this->options)) { |
|
86 $this->options[$key] = $value; |
|
87 } else { |
|
88 $isInvalid = true; |
|
89 $invalid[] = $key; |
|
90 } |
|
91 } |
|
92 |
|
93 if ($isInvalid) { |
|
94 throw new \InvalidArgumentException(sprintf('The Router does not support the following options: "%s".', implode('\', \'', $invalid))); |
|
95 } |
|
96 } |
|
97 |
|
98 /** |
|
99 * Sets an option. |
|
100 * |
|
101 * @param string $key The key |
|
102 * @param mixed $value The value |
|
103 * |
|
104 * @throws \InvalidArgumentException |
|
105 */ |
|
106 public function setOption($key, $value) |
|
107 { |
|
108 if (!array_key_exists($key, $this->options)) { |
|
109 throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); |
|
110 } |
|
111 |
|
112 $this->options[$key] = $value; |
|
113 } |
|
114 |
|
115 /** |
|
116 * Gets an option value. |
|
117 * |
|
118 * @param string $key The key |
|
119 * |
|
120 * @return mixed The value |
|
121 * |
|
122 * @throws \InvalidArgumentException |
|
123 */ |
|
124 public function getOption($key) |
|
125 { |
|
126 if (!array_key_exists($key, $this->options)) { |
|
127 throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); |
|
128 } |
|
129 |
|
130 return $this->options[$key]; |
|
131 } |
|
132 |
|
133 /** |
|
134 * Gets the RouteCollection instance associated with this Router. |
|
135 * |
|
136 * @return RouteCollection A RouteCollection instance |
|
137 */ |
|
138 public function getRouteCollection() |
|
139 { |
|
140 if (null === $this->collection) { |
|
141 $this->collection = $this->loader->load($this->resource, $this->options['resource_type']); |
|
142 } |
|
143 |
|
144 return $this->collection; |
|
145 } |
|
146 |
|
147 /** |
|
148 * Sets the request context. |
|
149 * |
|
150 * @param RequestContext $context The context |
|
151 */ |
|
152 public function setContext(RequestContext $context) |
|
153 { |
|
154 $this->context = $context; |
|
155 |
|
156 $this->getMatcher()->setContext($context); |
|
157 $this->getGenerator()->setContext($context); |
|
158 } |
|
159 |
|
160 /** |
|
161 * Gets the request context. |
|
162 * |
|
163 * @return RequestContext The context |
|
164 */ |
|
165 public function getContext() |
|
166 { |
|
167 return $this->context; |
|
168 } |
|
169 |
|
170 /** |
|
171 * Generates a URL from the given parameters. |
|
172 * |
|
173 * @param string $name The name of the route |
|
174 * @param mixed $parameters An array of parameters |
|
175 * @param Boolean $absolute Whether to generate an absolute URL |
|
176 * |
|
177 * @return string The generated URL |
|
178 */ |
|
179 public function generate($name, $parameters = array(), $absolute = false) |
|
180 { |
|
181 return $this->getGenerator()->generate($name, $parameters, $absolute); |
|
182 } |
|
183 |
|
184 /** |
|
185 * Tries to match a URL with a set of routes. |
|
186 * |
|
187 * Returns false if no route matches the URL. |
|
188 * |
|
189 * @param string $url URL to be parsed |
|
190 * |
|
191 * @return array|false An array of parameters or false if no route matches |
|
192 */ |
|
193 public function match($url) |
|
194 { |
|
195 return $this->getMatcher()->match($url); |
|
196 } |
|
197 |
|
198 /** |
|
199 * Gets the UrlMatcher instance associated with this Router. |
|
200 * |
|
201 * @return UrlMatcherInterface A UrlMatcherInterface instance |
|
202 */ |
|
203 public function getMatcher() |
|
204 { |
|
205 if (null !== $this->matcher) { |
|
206 return $this->matcher; |
|
207 } |
|
208 |
|
209 if (null === $this->options['cache_dir'] || null === $this->options['matcher_cache_class']) { |
|
210 return $this->matcher = new $this->options['matcher_class']($this->getRouteCollection(), $this->context, $this->defaults); |
|
211 } |
|
212 |
|
213 $class = $this->options['matcher_cache_class']; |
|
214 $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']); |
|
215 if (!$cache->isFresh($class)) { |
|
216 $dumper = new $this->options['matcher_dumper_class']($this->getRouteCollection()); |
|
217 |
|
218 $options = array( |
|
219 'class' => $class, |
|
220 'base_class' => $this->options['matcher_base_class'], |
|
221 ); |
|
222 |
|
223 $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources()); |
|
224 } |
|
225 |
|
226 require_once $cache; |
|
227 |
|
228 return $this->matcher = new $class($this->context, $this->defaults); |
|
229 } |
|
230 |
|
231 /** |
|
232 * Gets the UrlGenerator instance associated with this Router. |
|
233 * |
|
234 * @return UrlGeneratorInterface A UrlGeneratorInterface instance |
|
235 */ |
|
236 public function getGenerator() |
|
237 { |
|
238 if (null !== $this->generator) { |
|
239 return $this->generator; |
|
240 } |
|
241 |
|
242 if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) { |
|
243 return $this->generator = new $this->options['generator_class']($this->getRouteCollection(), $this->context, $this->defaults); |
|
244 } |
|
245 |
|
246 $class = $this->options['generator_cache_class']; |
|
247 $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']); |
|
248 if (!$cache->isFresh($class)) { |
|
249 $dumper = new $this->options['generator_dumper_class']($this->getRouteCollection()); |
|
250 |
|
251 $options = array( |
|
252 'class' => $class, |
|
253 'base_class' => $this->options['generator_base_class'], |
|
254 ); |
|
255 |
|
256 $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources()); |
|
257 } |
|
258 |
|
259 require_once $cache; |
|
260 |
|
261 return $this->generator = new $class($this->context, $this->defaults); |
|
262 } |
|
263 } |