1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Symfony\Component\Routing\Tests;
13:
14: use PHPUnit\Framework\TestCase;
15: use Symfony\Component\Routing\Route;
16: use Symfony\Component\Routing\RouteCompiler;
17:
18: class RouteCompilerTest extends TestCase
19: {
20: 21: 22:
23: public function testCompile($name, $arguments, $prefix, $regex, $variables, $tokens)
24: {
25: $r = new \ReflectionClass('Symfony\\Component\\Routing\\Route');
26: $route = $r->newInstanceArgs($arguments);
27:
28: $compiled = $route->compile();
29: $this->assertEquals($prefix, $compiled->getStaticPrefix(), $name.' (static prefix)');
30: $this->assertEquals($regex, $compiled->getRegex(), $name.' (regex)');
31: $this->assertEquals($variables, $compiled->getVariables(), $name.' (variables)');
32: $this->assertEquals($tokens, $compiled->getTokens(), $name.' (tokens)');
33: }
34:
35: public function provideCompileData()
36: {
37: return array(
38: array(
39: 'Static route',
40: array('/foo'),
41: '/foo', '#^/foo$#s', array(), array(
42: array('text', '/foo'),
43: ),
44: ),
45:
46: array(
47: 'Route with a variable',
48: array('/foo/{bar}'),
49: '/foo', '#^/foo/(?P<bar>[^/]++)$#s', array('bar'), array(
50: array('variable', '/', '[^/]++', 'bar'),
51: array('text', '/foo'),
52: ),
53: ),
54:
55: array(
56: 'Route with a variable that has a default value',
57: array('/foo/{bar}', array('bar' => 'bar')),
58: '/foo', '#^/foo(?:/(?P<bar>[^/]++))?$#s', array('bar'), array(
59: array('variable', '/', '[^/]++', 'bar'),
60: array('text', '/foo'),
61: ),
62: ),
63:
64: array(
65: 'Route with several variables',
66: array('/foo/{bar}/{foobar}'),
67: '/foo', '#^/foo/(?P<bar>[^/]++)/(?P<foobar>[^/]++)$#s', array('bar', 'foobar'), array(
68: array('variable', '/', '[^/]++', 'foobar'),
69: array('variable', '/', '[^/]++', 'bar'),
70: array('text', '/foo'),
71: ),
72: ),
73:
74: array(
75: 'Route with several variables that have default values',
76: array('/foo/{bar}/{foobar}', array('bar' => 'bar', 'foobar' => '')),
77: '/foo', '#^/foo(?:/(?P<bar>[^/]++)(?:/(?P<foobar>[^/]++))?)?$#s', array('bar', 'foobar'), array(
78: array('variable', '/', '[^/]++', 'foobar'),
79: array('variable', '/', '[^/]++', 'bar'),
80: array('text', '/foo'),
81: ),
82: ),
83:
84: array(
85: 'Route with several variables but some of them have no default values',
86: array('/foo/{bar}/{foobar}', array('bar' => 'bar')),
87: '/foo', '#^/foo/(?P<bar>[^/]++)/(?P<foobar>[^/]++)$#s', array('bar', 'foobar'), array(
88: array('variable', '/', '[^/]++', 'foobar'),
89: array('variable', '/', '[^/]++', 'bar'),
90: array('text', '/foo'),
91: ),
92: ),
93:
94: array(
95: 'Route with an optional variable as the first segment',
96: array('/{bar}', array('bar' => 'bar')),
97: '', '#^/(?P<bar>[^/]++)?$#s', array('bar'), array(
98: array('variable', '/', '[^/]++', 'bar'),
99: ),
100: ),
101:
102: array(
103: 'Route with a requirement of 0',
104: array('/{bar}', array('bar' => null), array('bar' => '0')),
105: '', '#^/(?P<bar>0)?$#s', array('bar'), array(
106: array('variable', '/', '0', 'bar'),
107: ),
108: ),
109:
110: array(
111: 'Route with an optional variable as the first segment with requirements',
112: array('/{bar}', array('bar' => 'bar'), array('bar' => '(foo|bar)')),
113: '', '#^/(?P<bar>(foo|bar))?$#s', array('bar'), array(
114: array('variable', '/', '(foo|bar)', 'bar'),
115: ),
116: ),
117:
118: array(
119: 'Route with only optional variables',
120: array('/{foo}/{bar}', array('foo' => 'foo', 'bar' => 'bar')),
121: '', '#^/(?P<foo>[^/]++)?(?:/(?P<bar>[^/]++))?$#s', array('foo', 'bar'), array(
122: array('variable', '/', '[^/]++', 'bar'),
123: array('variable', '/', '[^/]++', 'foo'),
124: ),
125: ),
126:
127: array(
128: 'Route with a variable in last position',
129: array('/foo-{bar}'),
130: '/foo', '#^/foo\-(?P<bar>[^/]++)$#s', array('bar'), array(
131: array('variable', '-', '[^/]++', 'bar'),
132: array('text', '/foo'),
133: ),
134: ),
135:
136: array(
137: 'Route with nested placeholders',
138: array('/{static{var}static}'),
139: '/{static', '#^/\{static(?P<var>[^/]+)static\}$#s', array('var'), array(
140: array('text', 'static}'),
141: array('variable', '', '[^/]+', 'var'),
142: array('text', '/{static'),
143: ),
144: ),
145:
146: array(
147: 'Route without separator between variables',
148: array('/{w}{x}{y}{z}.{_format}', array('z' => 'default-z', '_format' => 'html'), array('y' => '(y|Y)')),
149: '', '#^/(?P<w>[^/\.]+)(?P<x>[^/\.]+)(?P<y>(y|Y))(?:(?P<z>[^/\.]++)(?:\.(?P<_format>[^/]++))?)?$#s', array('w', 'x', 'y', 'z', '_format'), array(
150: array('variable', '.', '[^/]++', '_format'),
151: array('variable', '', '[^/\.]++', 'z'),
152: array('variable', '', '(y|Y)', 'y'),
153: array('variable', '', '[^/\.]+', 'x'),
154: array('variable', '/', '[^/\.]+', 'w'),
155: ),
156: ),
157:
158: array(
159: 'Route with a format',
160: array('/foo/{bar}.{_format}'),
161: '/foo', '#^/foo/(?P<bar>[^/\.]++)\.(?P<_format>[^/]++)$#s', array('bar', '_format'), array(
162: array('variable', '.', '[^/]++', '_format'),
163: array('variable', '/', '[^/\.]++', 'bar'),
164: array('text', '/foo'),
165: ),
166: ),
167: );
168: }
169:
170: 171: 172:
173: public function testRouteWithSameVariableTwice()
174: {
175: $route = new Route('/{name}/{name}');
176:
177: $compiled = $route->compile();
178: }
179:
180: 181: 182: 183:
184: public function testRouteWithVariableNameStartingWithADigit($name)
185: {
186: $route = new Route('/{'.$name.'}');
187: $route->compile();
188: }
189:
190: public function getVariableNamesStartingWithADigit()
191: {
192: return array(
193: array('09'),
194: array('123'),
195: array('1e2'),
196: );
197: }
198:
199: 200: 201:
202: public function testCompileWithHost($name, $arguments, $prefix, $regex, $variables, $pathVariables, $tokens, $hostRegex, $hostVariables, $hostTokens)
203: {
204: $r = new \ReflectionClass('Symfony\\Component\\Routing\\Route');
205: $route = $r->newInstanceArgs($arguments);
206:
207: $compiled = $route->compile();
208: $this->assertEquals($prefix, $compiled->getStaticPrefix(), $name.' (static prefix)');
209: $this->assertEquals($regex, str_replace(array("\n", ' '), '', $compiled->getRegex()), $name.' (regex)');
210: $this->assertEquals($variables, $compiled->getVariables(), $name.' (variables)');
211: $this->assertEquals($pathVariables, $compiled->getPathVariables(), $name.' (path variables)');
212: $this->assertEquals($tokens, $compiled->getTokens(), $name.' (tokens)');
213: $this->assertEquals($hostRegex, str_replace(array("\n", ' '), '', $compiled->getHostRegex()), $name.' (host regex)');
214: $this->assertEquals($hostVariables, $compiled->getHostVariables(), $name.' (host variables)');
215: $this->assertEquals($hostTokens, $compiled->getHostTokens(), $name.' (host tokens)');
216: }
217:
218: public function provideCompileWithHostData()
219: {
220: return array(
221: array(
222: 'Route with host pattern',
223: array('/hello', array(), array(), array(), 'www.example.com'),
224: '/hello', '#^/hello$#s', array(), array(), array(
225: array('text', '/hello'),
226: ),
227: '#^www\.example\.com$#si', array(), array(
228: array('text', 'www.example.com'),
229: ),
230: ),
231: array(
232: 'Route with host pattern and some variables',
233: array('/hello/{name}', array(), array(), array(), 'www.example.{tld}'),
234: '/hello', '#^/hello/(?P<name>[^/]++)$#s', array('tld', 'name'), array('name'), array(
235: array('variable', '/', '[^/]++', 'name'),
236: array('text', '/hello'),
237: ),
238: '#^www\.example\.(?P<tld>[^\.]++)$#si', array('tld'), array(
239: array('variable', '.', '[^\.]++', 'tld'),
240: array('text', 'www.example'),
241: ),
242: ),
243: array(
244: 'Route with variable at beginning of host',
245: array('/hello', array(), array(), array(), '{locale}.example.{tld}'),
246: '/hello', '#^/hello$#s', array('locale', 'tld'), array(), array(
247: array('text', '/hello'),
248: ),
249: '#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#si', array('locale', 'tld'), array(
250: array('variable', '.', '[^\.]++', 'tld'),
251: array('text', '.example'),
252: array('variable', '', '[^\.]++', 'locale'),
253: ),
254: ),
255: array(
256: 'Route with host variables that has a default value',
257: array('/hello', array('locale' => 'a', 'tld' => 'b'), array(), array(), '{locale}.example.{tld}'),
258: '/hello', '#^/hello$#s', array('locale', 'tld'), array(), array(
259: array('text', '/hello'),
260: ),
261: '#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#si', array('locale', 'tld'), array(
262: array('variable', '.', '[^\.]++', 'tld'),
263: array('text', '.example'),
264: array('variable', '', '[^\.]++', 'locale'),
265: ),
266: ),
267: );
268: }
269:
270: 271: 272:
273: public function testRouteWithTooLongVariableName()
274: {
275: $route = new Route(sprintf('/{%s}', str_repeat('a', RouteCompiler::VARIABLE_MAXIMUM_LENGTH + 1)));
276: $route->compile();
277: }
278: }
279: