1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Symfony\Component\Routing;
13:
14: use Symfony\Component\Config\Exception\FileLoaderLoadException;
15: use Symfony\Component\Config\Loader\LoaderInterface;
16: use Symfony\Component\Config\Resource\ResourceInterface;
17:
18: 19: 20: 21: 22:
23: class RouteCollectionBuilder
24: {
25: 26: 27:
28: private $routes = array();
29:
30: private $loader;
31: private $defaults = array();
32: private $prefix;
33: private $host;
34: private $condition;
35: private $requirements = array();
36: private $options = array();
37: private $schemes;
38: private $methods;
39: private $resources = array();
40:
41: 42: 43:
44: public function __construct(LoaderInterface $loader = null)
45: {
46: $this->loader = $loader;
47: }
48:
49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61:
62: public function import($resource, $prefix = '/', $type = null)
63: {
64:
65: $collection = $this->load($resource, $type);
66:
67:
68: $builder = $this->createBuilder();
69: foreach ($collection->all() as $name => $route) {
70: $builder->addRoute($route, $name);
71: }
72:
73: foreach ($collection->getResources() as $resource) {
74: $builder->addResource($resource);
75: }
76:
77:
78: $this->mount($prefix, $builder);
79:
80: return $builder;
81: }
82:
83: 84: 85: 86: 87: 88: 89: 90: 91:
92: public function add($path, $controller, $name = null)
93: {
94: $route = new Route($path);
95: $route->setDefault('_controller', $controller);
96: $this->addRoute($route, $name);
97:
98: return $route;
99: }
100:
101: 102: 103: 104: 105:
106: public function createBuilder()
107: {
108: return new self($this->loader);
109: }
110:
111: 112: 113: 114: 115: 116:
117: public function mount($prefix, RouteCollectionBuilder $builder)
118: {
119: $builder->prefix = trim(trim($prefix), '/');
120: $this->routes[] = $builder;
121: }
122:
123: 124: 125: 126: 127: 128: 129: 130:
131: public function addRoute(Route $route, $name = null)
132: {
133: if (null === $name) {
134:
135: $name = '_unnamed_route_'.spl_object_hash($route);
136: }
137:
138: $this->routes[$name] = $route;
139:
140: return $this;
141: }
142:
143: 144: 145: 146: 147: 148: 149:
150: public function setHost($pattern)
151: {
152: $this->host = $pattern;
153:
154: return $this;
155: }
156:
157: 158: 159: 160: 161: 162: 163:
164: public function setCondition($condition)
165: {
166: $this->condition = $condition;
167:
168: return $this;
169: }
170:
171: 172: 173: 174: 175: 176: 177: 178: 179:
180: public function setDefault($key, $value)
181: {
182: $this->defaults[$key] = $value;
183:
184: return $this;
185: }
186:
187: 188: 189: 190: 191: 192: 193: 194: 195:
196: public function setRequirement($key, $regex)
197: {
198: $this->requirements[$key] = $regex;
199:
200: return $this;
201: }
202:
203: 204: 205: 206: 207: 208: 209: 210: 211:
212: public function setOption($key, $value)
213: {
214: $this->options[$key] = $value;
215:
216: return $this;
217: }
218:
219: 220: 221: 222: 223: 224: 225:
226: public function setSchemes($schemes)
227: {
228: $this->schemes = $schemes;
229:
230: return $this;
231: }
232:
233: 234: 235: 236: 237: 238: 239:
240: public function setMethods($methods)
241: {
242: $this->methods = $methods;
243:
244: return $this;
245: }
246:
247: 248: 249: 250: 251: 252: 253:
254: private function addResource(ResourceInterface $resource)
255: {
256: $this->resources[] = $resource;
257:
258: return $this;
259: }
260:
261: 262: 263: 264: 265:
266: public function build()
267: {
268: $routeCollection = new RouteCollection();
269:
270: foreach ($this->routes as $name => $route) {
271: if ($route instanceof Route) {
272: $route->setDefaults(array_merge($this->defaults, $route->getDefaults()));
273: $route->setOptions(array_merge($this->options, $route->getOptions()));
274:
275:
276: foreach ($this->requirements as $key => $val) {
277: if (!$route->hasRequirement($key)) {
278: $route->setRequirement($key, $val);
279: }
280: }
281:
282: if (null !== $this->prefix) {
283: $route->setPath('/'.$this->prefix.$route->getPath());
284: }
285:
286: if (!$route->getHost()) {
287: $route->setHost($this->host);
288: }
289:
290: if (!$route->getCondition()) {
291: $route->setCondition($this->condition);
292: }
293:
294: if (!$route->getSchemes()) {
295: $route->setSchemes($this->schemes);
296: }
297:
298: if (!$route->getMethods()) {
299: $route->setMethods($this->methods);
300: }
301:
302:
303: if ('_unnamed_route_' === substr($name, 0, 15)) {
304: $name = $this->generateRouteName($route);
305: }
306:
307: $routeCollection->add($name, $route);
308: } else {
309:
310: $subCollection = $route->build();
311: $subCollection->addPrefix($this->prefix);
312:
313: $routeCollection->addCollection($subCollection);
314: }
315:
316: foreach ($this->resources as $resource) {
317: $routeCollection->addResource($resource);
318: }
319: }
320:
321: return $routeCollection;
322: }
323:
324: 325: 326: 327: 328:
329: private function generateRouteName(Route $route)
330: {
331: $methods = implode('_', $route->getMethods()).'_';
332:
333: $routeName = $methods.$route->getPath();
334: $routeName = str_replace(array('/', ':', '|', '-'), '_', $routeName);
335: $routeName = preg_replace('/[^a-z0-9A-Z_.]+/', '', $routeName);
336:
337:
338: $routeName = preg_replace('/_+/', '_', $routeName);
339:
340: return $routeName;
341: }
342:
343: 344: 345: 346: 347: 348: 349: 350: 351: 352:
353: private function load($resource, $type = null)
354: {
355: if (null === $this->loader) {
356: throw new \BadMethodCallException('Cannot import other routing resources: you must pass a LoaderInterface when constructing RouteCollectionBuilder.');
357: }
358:
359: if ($this->loader->supports($resource, $type)) {
360: return $this->loader->load($resource, $type);
361: }
362:
363: if (null === $resolver = $this->loader->getResolver()) {
364: throw new FileLoaderLoadException($resource);
365: }
366:
367: if (false === $loader = $resolver->resolve($resource, $type)) {
368: throw new FileLoaderLoadException($resource);
369: }
370:
371: return $loader->load($resource, $type);
372: }
373: }
374: