Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

merged 2.0

  • Loading branch information...
commit c7ba1b9605c06008734c27933616b64e3865473d 2 parents 9d5743b + 8835357
Fabien Potencier fabpot authored
47 src/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php
@@ -31,6 +31,8 @@ class ApacheMatcherDumper extends MatcherDumper
31 31 * @param array $options An array of options
32 32 *
33 33 * @return string A string to be used as Apache rewrite rules
  34 + *
  35 + * @throws \LogicException When the route regex is invalid
34 36 */
35 37 public function dump(array $options = array())
36 38 {
@@ -39,6 +41,8 @@ public function dump(array $options = array())
39 41 'base_uri' => '',
40 42 ), $options);
41 43
  44 + $options['script_name'] = self::escape($options['script_name'], ' ', '\\');
  45 +
42 46 $rules = array("# skip \"real\" requests\nRewriteCond %{REQUEST_FILENAME} -f\nRewriteRule .* - [QSA,L]");
43 47 $methodVars = array();
44 48
@@ -46,8 +50,14 @@ public function dump(array $options = array())
46 50 $compiledRoute = $route->compile();
47 51
48 52 // prepare the apache regex
49   - $regex = preg_replace('/\?P<.+?>/', '', substr(str_replace(array("\n", ' '), '', $compiledRoute->getRegex()), 1, -3));
50   - $regex = '^'.preg_quote($options['base_uri']).substr($regex, 1);
  53 + $regex = $compiledRoute->getRegex();
  54 + $delimiter = $regex[0];
  55 + $regexPatternEnd = strrpos($regex, $delimiter);
  56 + if (strlen($regex) < 2 || 0 === $regexPatternEnd) {
  57 + throw new \LogicException('The "%s" route regex "%s" is invalid', $name, $regex);
  58 + }
  59 + $regex = preg_replace('/\?P<.+?>/', '', substr($regex, 1, $regexPatternEnd - 1));
  60 + $regex = '^'.self::escape(preg_quote($options['base_uri']).substr($regex, 1), ' ', '\\');
51 61
52 62 $methods = array();
53 63 if ($req = $route->getRequirement('_method')) {
@@ -65,7 +75,6 @@ public function dump(array $options = array())
65 75 $variables[] = 'E=_ROUTING_'.$variable.':%'.($i + 1);
66 76 }
67 77 foreach ($route->getDefaults() as $key => $value) {
68   - // todo: a more legit way to escape the value?
69 78 $variables[] = 'E=_ROUTING_'.$key.':'.strtr($value, array(
70 79 ':' => '\\:',
71 80 '=' => '\\=',
@@ -121,4 +130,36 @@ public function dump(array $options = array())
121 130
122 131 return implode("\n\n", $rules)."\n";
123 132 }
  133 +
  134 + /**
  135 + * Escapes a string.
  136 + *
  137 + * @param string $string The string to be escaped
  138 + * @param string $char The character to be escaped
  139 + * @param string $with The character to be used for escaping
  140 + *
  141 + * @return string The escaped string
  142 + */
  143 + static private function escape($string, $char, $with)
  144 + {
  145 + $escaped = false;
  146 + $output = '';
  147 + foreach(str_split($string) as $symbol) {
  148 + if ($escaped) {
  149 + $output .= $symbol;
  150 + $escaped = false;
  151 + continue;
  152 + }
  153 + if ($symbol === $char) {
  154 + $output .= $with.$char;
  155 + continue;
  156 + }
  157 + if ($symbol === $with) {
  158 + $escaped = true;
  159 + }
  160 + $output .= $symbol;
  161 + }
  162 +
  163 + return $output;
  164 + }
124 165 }
4 src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php
@@ -159,7 +159,7 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren
159 159
160 160 $supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods));
161 161
162   - if (!count($compiledRoute->getVariables()) && false !== preg_match('#^(.)\^(?P<url>.*?)\$\1#', str_replace(array("\n", ' '), '', $compiledRoute->getRegex()), $m)) {
  162 + if (!count($compiledRoute->getVariables()) && false !== preg_match('#^(.)\^(?P<url>.*?)\$\1#', $compiledRoute->getRegex(), $m)) {
163 163 if ($supportsTrailingSlash && substr($m['url'], -1) === '/') {
164 164 $conditions[] = sprintf("rtrim(\$pathinfo, '/') === %s", var_export(rtrim(str_replace('\\', '', $m['url']), '/'), true));
165 165 $hasTrailingSlash = true;
@@ -171,7 +171,7 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren
171 171 $conditions[] = sprintf("0 === strpos(\$pathinfo, %s)", var_export($compiledRoute->getStaticPrefix(), true));
172 172 }
173 173
174   - $regex = str_replace(array("\n", ' '), '', $compiledRoute->getRegex());
  174 + $regex = $compiledRoute->getRegex();
175 175 if ($supportsTrailingSlash && $pos = strpos($regex, '/$')) {
176 176 $regex = substr($regex, 0, $pos).'/?$'.substr($regex, $pos + 2);
177 177 $hasTrailingSlash = true;
66 src/Symfony/Component/Routing/RouteCompiler.php
@@ -66,7 +66,8 @@ public function compile(Route $route)
66 66 // find the first optional token
67 67 $firstOptional = INF;
68 68 for ($i = count($tokens) - 1; $i >= 0; $i--) {
69   - if ('variable' === $tokens[$i][0] && $route->hasDefault($tokens[$i][3])) {
  69 + $token = $tokens[$i];
  70 + if ('variable' === $token[0] && $route->hasDefault($token[3])) {
70 71 $firstOptional = $i;
71 72 } else {
72 73 break;
@@ -74,36 +75,53 @@ public function compile(Route $route)
74 75 }
75 76
76 77 // compute the matching regexp
77   - $regex = '';
78   - $indent = 1;
79   - if (1 === count($tokens) && 0 === $firstOptional) {
80   - $token = $tokens[0];
81   - ++$indent;
82   - $regex .= str_repeat(' ', $indent * 4).sprintf("%s(?:\n", preg_quote($token[1], '#'));
83   - $regex .= str_repeat(' ', $indent * 4).sprintf("(?P<%s>%s)\n", $token[3], $token[2]);
84   - } else {
85   - foreach ($tokens as $i => $token) {
86   - if ('text' === $token[0]) {
87   - $regex .= str_repeat(' ', $indent * 4).preg_quote($token[1], '#')."\n";
88   - } else {
89   - if ($i >= $firstOptional) {
90   - $regex .= str_repeat(' ', $indent * 4)."(?:\n";
91   - ++$indent;
92   - }
93   - $regex .= str_repeat(' ', $indent * 4).sprintf("%s(?P<%s>%s)\n", preg_quote($token[1], '#'), $token[3], $token[2]);
94   - }
95   - }
96   - }
97   - while (--$indent) {
98   - $regex .= str_repeat(' ', $indent * 4).")?\n";
  78 + $regexp = '';
  79 + for ($i = 0, $nbToken = count($tokens); $i < $nbToken; $i++) {
  80 + $regexp .= $this->computeRegexp($tokens, $i, $firstOptional);
99 81 }
100 82
101 83 return new CompiledRoute(
102 84 $route,
103 85 'text' === $tokens[0][0] ? $tokens[0][1] : '',
104   - sprintf("#^\n%s$#xs", $regex),
  86 + sprintf("#^%s$#s", $regexp),
105 87 array_reverse($tokens),
106 88 $variables
107 89 );
108 90 }
  91 +
  92 + /**
  93 + * Computes the regexp used to match the token.
  94 + *
  95 + * @param array $tokens The route tokens
  96 + * @param integer $index The index of the current token
  97 + * @param integer $firstOptional The index of the first optional token
  98 + *
  99 + * @return string The regexp
  100 + */
  101 + private function computeRegexp(array $tokens, $index, $firstOptional)
  102 + {
  103 + $token = $tokens[$index];
  104 + if('text' === $token[0]) {
  105 + // Text tokens
  106 + return preg_quote($token[1], '#');
  107 + } else {
  108 + // Variable tokens
  109 + if (0 === $index && 0 === $firstOptional && 1 == count($tokens)) {
  110 + // When the only token is an optional variable token, the separator is required
  111 + return sprintf('%s(?P<%s>%s)?', preg_quote($token[1], '#'), $token[3], $token[2]);
  112 + } else {
  113 + $nbTokens = count($tokens);
  114 + $regexp = sprintf('%s(?P<%s>%s)', preg_quote($token[1], '#'), $token[3], $token[2]);
  115 + if ($index >= $firstOptional) {
  116 + // Enclose each optional tokens in a subpattern to make it optional
  117 + $regexp = "(?:$regexp";
  118 + if ($nbTokens - 1 == $index) {
  119 + // Close the optional subpatterns
  120 + $regexp .= str_repeat(")?", $nbTokens - $firstOptional);
  121 + }
  122 + }
  123 + return $regexp;
  124 + }
  125 + }
  126 + }
109 127 }
4 src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apache
@@ -60,6 +60,10 @@ RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baz5unsafe,E=_ROUTING_foo:%1]
60 60 RewriteCond %{REQUEST_URI} ^/test/baz$
61 61 RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baz6,E=_ROUTING_foo:bar\ baz]
62 62
  63 +# baz7
  64 +RewriteCond %{REQUEST_URI} ^/te\ st/baz$
  65 +RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baz7]
  66 +
63 67 # 405 Method Not Allowed
64 68 RewriteCond %{_ROUTING__allow_GET} !-z [OR]
65 69 RewriteCond %{_ROUTING__allow_HEAD} !-z [OR]
33 src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php
@@ -26,12 +26,12 @@ public function match($pathinfo)
26 26 $pathinfo = rawurldecode($pathinfo);
27 27
28 28 // foo
29   - if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?P<bar>baz|symfony)$#xs', $pathinfo, $matches)) {
  29 + if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?P<bar>baz|symfony)$#s', $pathinfo, $matches)) {
30 30 return array_merge($this->mergeDefaults($matches, array ( 'def' => 'test',)), array('_route' => 'foo'));
31 31 }
32 32
33 33 // bar
34   - if (0 === strpos($pathinfo, '/bar') && preg_match('#^/bar/(?P<foo>[^/]+?)$#xs', $pathinfo, $matches)) {
  34 + if (0 === strpos($pathinfo, '/bar') && preg_match('#^/bar/(?P<foo>[^/]+?)$#s', $pathinfo, $matches)) {
35 35 if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) {
36 36 $allow = array_merge($allow, array('GET', 'HEAD'));
37 37 goto not_bar;
@@ -42,7 +42,7 @@ public function match($pathinfo)
42 42 not_bar:
43 43
44 44 // barhead
45   - if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P<foo>[^/]+?)$#xs', $pathinfo, $matches)) {
  45 + if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P<foo>[^/]+?)$#s', $pathinfo, $matches)) {
46 46 if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) {
47 47 $allow = array_merge($allow, array('GET', 'HEAD'));
48 48 goto not_barhead;
@@ -68,13 +68,13 @@ public function match($pathinfo)
68 68 }
69 69
70 70 // baz4
71   - if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P<foo>[^/]+?)/$#xs', $pathinfo, $matches)) {
  71 + if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P<foo>[^/]+?)/$#s', $pathinfo, $matches)) {
72 72 $matches['_route'] = 'baz4';
73 73 return $matches;
74 74 }
75 75
76 76 // baz5
77   - if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P<foo>[^/]+?)/$#xs', $pathinfo, $matches)) {
  77 + if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P<foo>[^/]+?)/$#s', $pathinfo, $matches)) {
78 78 if ($this->context->getMethod() != 'POST') {
79 79 $allow[] = 'POST';
80 80 goto not_baz5;
@@ -85,7 +85,7 @@ public function match($pathinfo)
85 85 not_baz5:
86 86
87 87 // baz.baz6
88   - if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P<foo>[^/]+?)/$#xs', $pathinfo, $matches)) {
  88 + if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P<foo>[^/]+?)/$#s', $pathinfo, $matches)) {
89 89 if ($this->context->getMethod() != 'PUT') {
90 90 $allow[] = 'PUT';
91 91 goto not_bazbaz6;
@@ -101,33 +101,38 @@ public function match($pathinfo)
101 101 }
102 102
103 103 // quoter
104   - if (preg_match('#^/(?P<quoter>[\']+)$#xs', $pathinfo, $matches)) {
  104 + if (preg_match('#^/(?P<quoter>[\']+)$#s', $pathinfo, $matches)) {
105 105 $matches['_route'] = 'quoter';
106 106 return $matches;
107 107 }
108 108
  109 + // space
  110 + if ($pathinfo === '/spa ce') {
  111 + return array('_route' => 'space');
  112 + }
  113 +
109 114 if (0 === strpos($pathinfo, '/a')) {
110 115 if (0 === strpos($pathinfo, '/a/b\'b')) {
111 116 // foo1
112   - if (preg_match('#^/a/b\'b/(?P<foo>[^/]+?)$#xs', $pathinfo, $matches)) {
  117 + if (preg_match('#^/a/b\'b/(?P<foo>[^/]+?)$#s', $pathinfo, $matches)) {
113 118 $matches['_route'] = 'foo1';
114 119 return $matches;
115 120 }
116 121
117 122 // bar1
118   - if (preg_match('#^/a/b\'b/(?P<bar>[^/]+?)$#xs', $pathinfo, $matches)) {
  123 + if (preg_match('#^/a/b\'b/(?P<bar>[^/]+?)$#s', $pathinfo, $matches)) {
119 124 $matches['_route'] = 'bar1';
120 125 return $matches;
121 126 }
122 127
123 128 // foo2
124   - if (preg_match('#^/a/b\'b/(?P<foo1>[^/]+?)$#xs', $pathinfo, $matches)) {
  129 + if (preg_match('#^/a/b\'b/(?P<foo1>[^/]+?)$#s', $pathinfo, $matches)) {
125 130 $matches['_route'] = 'foo2';
126 131 return $matches;
127 132 }
128 133
129 134 // bar2
130   - if (preg_match('#^/a/b\'b/(?P<bar1>[^/]+?)$#xs', $pathinfo, $matches)) {
  135 + if (preg_match('#^/a/b\'b/(?P<bar1>[^/]+?)$#s', $pathinfo, $matches)) {
131 136 $matches['_route'] = 'bar2';
132 137 return $matches;
133 138 }
@@ -144,20 +149,20 @@ public function match($pathinfo)
144 149 }
145 150
146 151 // foo4
147   - if (preg_match('#^/aba/(?P<foo>[^/]+?)$#xs', $pathinfo, $matches)) {
  152 + if (preg_match('#^/aba/(?P<foo>[^/]+?)$#s', $pathinfo, $matches)) {
148 153 $matches['_route'] = 'foo4';
149 154 return $matches;
150 155 }
151 156 }
152 157
153 158 // foo3
154   - if (preg_match('#^/(?P<_locale>[^/]+?)/b/(?P<foo>[^/]+?)$#xs', $pathinfo, $matches)) {
  159 + if (preg_match('#^/(?P<_locale>[^/]+?)/b/(?P<foo>[^/]+?)$#s', $pathinfo, $matches)) {
155 160 $matches['_route'] = 'foo3';
156 161 return $matches;
157 162 }
158 163
159 164 // bar3
160   - if (preg_match('#^/(?P<_locale>[^/]+?)/b/(?P<bar>[^/]+?)$#xs', $pathinfo, $matches)) {
  165 + if (preg_match('#^/(?P<_locale>[^/]+?)/b/(?P<bar>[^/]+?)$#s', $pathinfo, $matches)) {
161 166 $matches['_route'] = 'bar3';
162 167 return $matches;
163 168 }
7 src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apache
... ... @@ -0,0 +1,7 @@
  1 +# skip "real" requests
  2 +RewriteCond %{REQUEST_FILENAME} -f
  3 +RewriteRule .* - [QSA,L]
  4 +
  5 +# foo
  6 +RewriteCond %{REQUEST_URI} ^/foo$
  7 +RewriteRule .* ap\ p_d\ ev.php [QSA,L,E=_ROUTING__route:foo]
33 src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php
@@ -26,12 +26,12 @@ public function match($pathinfo)
26 26 $pathinfo = rawurldecode($pathinfo);
27 27
28 28 // foo
29   - if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?P<bar>baz|symfony)$#xs', $pathinfo, $matches)) {
  29 + if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?P<bar>baz|symfony)$#s', $pathinfo, $matches)) {
30 30 return array_merge($this->mergeDefaults($matches, array ( 'def' => 'test',)), array('_route' => 'foo'));
31 31 }
32 32
33 33 // bar
34   - if (0 === strpos($pathinfo, '/bar') && preg_match('#^/bar/(?P<foo>[^/]+?)$#xs', $pathinfo, $matches)) {
  34 + if (0 === strpos($pathinfo, '/bar') && preg_match('#^/bar/(?P<foo>[^/]+?)$#s', $pathinfo, $matches)) {
35 35 if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) {
36 36 $allow = array_merge($allow, array('GET', 'HEAD'));
37 37 goto not_bar;
@@ -42,7 +42,7 @@ public function match($pathinfo)
42 42 not_bar:
43 43
44 44 // barhead
45   - if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P<foo>[^/]+?)$#xs', $pathinfo, $matches)) {
  45 + if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P<foo>[^/]+?)$#s', $pathinfo, $matches)) {
46 46 if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) {
47 47 $allow = array_merge($allow, array('GET', 'HEAD'));
48 48 goto not_barhead;
@@ -71,7 +71,7 @@ public function match($pathinfo)
71 71 }
72 72
73 73 // baz4
74   - if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P<foo>[^/]+?)/?$#xs', $pathinfo, $matches)) {
  74 + if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P<foo>[^/]+?)/?$#s', $pathinfo, $matches)) {
75 75 if (substr($pathinfo, -1) !== '/') {
76 76 return $this->redirect($pathinfo.'/', 'baz4');
77 77 }
@@ -80,7 +80,7 @@ public function match($pathinfo)
80 80 }
81 81
82 82 // baz5
83   - if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P<foo>[^/]+?)/$#xs', $pathinfo, $matches)) {
  83 + if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P<foo>[^/]+?)/$#s', $pathinfo, $matches)) {
84 84 if ($this->context->getMethod() != 'POST') {
85 85 $allow[] = 'POST';
86 86 goto not_baz5;
@@ -91,7 +91,7 @@ public function match($pathinfo)
91 91 not_baz5:
92 92
93 93 // baz.baz6
94   - if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P<foo>[^/]+?)/$#xs', $pathinfo, $matches)) {
  94 + if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P<foo>[^/]+?)/$#s', $pathinfo, $matches)) {
95 95 if ($this->context->getMethod() != 'PUT') {
96 96 $allow[] = 'PUT';
97 97 goto not_bazbaz6;
@@ -107,33 +107,38 @@ public function match($pathinfo)
107 107 }
108 108
109 109 // quoter
110   - if (preg_match('#^/(?P<quoter>[\']+)$#xs', $pathinfo, $matches)) {
  110 + if (preg_match('#^/(?P<quoter>[\']+)$#s', $pathinfo, $matches)) {
111 111 $matches['_route'] = 'quoter';
112 112 return $matches;
113 113 }
114 114
  115 + // space
  116 + if ($pathinfo === '/spa ce') {
  117 + return array('_route' => 'space');
  118 + }
  119 +
115 120 if (0 === strpos($pathinfo, '/a')) {
116 121 if (0 === strpos($pathinfo, '/a/b\'b')) {
117 122 // foo1
118   - if (preg_match('#^/a/b\'b/(?P<foo>[^/]+?)$#xs', $pathinfo, $matches)) {
  123 + if (preg_match('#^/a/b\'b/(?P<foo>[^/]+?)$#s', $pathinfo, $matches)) {
119 124 $matches['_route'] = 'foo1';
120 125 return $matches;
121 126 }
122 127
123 128 // bar1
124   - if (preg_match('#^/a/b\'b/(?P<bar>[^/]+?)$#xs', $pathinfo, $matches)) {
  129 + if (preg_match('#^/a/b\'b/(?P<bar>[^/]+?)$#s', $pathinfo, $matches)) {
125 130 $matches['_route'] = 'bar1';
126 131 return $matches;
127 132 }
128 133
129 134 // foo2
130   - if (preg_match('#^/a/b\'b/(?P<foo1>[^/]+?)$#xs', $pathinfo, $matches)) {
  135 + if (preg_match('#^/a/b\'b/(?P<foo1>[^/]+?)$#s', $pathinfo, $matches)) {
131 136 $matches['_route'] = 'foo2';
132 137 return $matches;
133 138 }
134 139
135 140 // bar2
136   - if (preg_match('#^/a/b\'b/(?P<bar1>[^/]+?)$#xs', $pathinfo, $matches)) {
  141 + if (preg_match('#^/a/b\'b/(?P<bar1>[^/]+?)$#s', $pathinfo, $matches)) {
137 142 $matches['_route'] = 'bar2';
138 143 return $matches;
139 144 }
@@ -150,20 +155,20 @@ public function match($pathinfo)
150 155 }
151 156
152 157 // foo4
153   - if (preg_match('#^/aba/(?P<foo>[^/]+?)$#xs', $pathinfo, $matches)) {
  158 + if (preg_match('#^/aba/(?P<foo>[^/]+?)$#s', $pathinfo, $matches)) {
154 159 $matches['_route'] = 'foo4';
155 160 return $matches;
156 161 }
157 162 }
158 163
159 164 // foo3
160   - if (preg_match('#^/(?P<_locale>[^/]+?)/b/(?P<foo>[^/]+?)$#xs', $pathinfo, $matches)) {
  165 + if (preg_match('#^/(?P<_locale>[^/]+?)/b/(?P<foo>[^/]+?)$#s', $pathinfo, $matches)) {
161 166 $matches['_route'] = 'foo3';
162 167 return $matches;
163 168 }
164 169
165 170 // bar3
166   - if (preg_match('#^/(?P<_locale>[^/]+?)/b/(?P<bar>[^/]+?)$#xs', $pathinfo, $matches)) {
  171 + if (preg_match('#^/(?P<_locale>[^/]+?)/b/(?P<bar>[^/]+?)$#s', $pathinfo, $matches)) {
167 172 $matches['_route'] = 'bar3';
168 173 return $matches;
169 174 }
44 src/Symfony/Component/Routing/Tests/Matcher/Dumper/ApacheMatcherDumperTest.php
@@ -26,6 +26,42 @@ static public function setUpBeforeClass()
26 26
27 27 public function testDump()
28 28 {
  29 + $dumper = new ApacheMatcherDumper($this->getRouteCollection());
  30 +
  31 + $this->assertStringEqualsFile(self::$fixturesPath.'/dumper/url_matcher1.apache', $dumper->dump(), '->dump() dumps basic routes to the correct apache format.');
  32 + }
  33 +
  34 + /**
  35 + * @dataProvider provideEscapeFixtures
  36 + */
  37 + public function testEscapePattern($src, $dest, $char, $with, $message)
  38 + {
  39 + $r = new \ReflectionMethod(new ApacheMatcherDumper($this->getRouteCollection()), 'escape');
  40 + $r->setAccessible(true);
  41 + $this->assertEquals($dest, $r->invoke(null, $src, $char, $with), $message);
  42 + }
  43 +
  44 + public function provideEscapeFixtures()
  45 + {
  46 + return array(
  47 + array('foo', 'foo', ' ', '-', 'Preserve string that should not be escaped'),
  48 + array('fo-o', 'fo-o', ' ', '-', 'Preserve string that should not be escaped'),
  49 + array('fo o', 'fo- o', ' ', '-', 'Escape special characters'),
  50 + array('fo-- o', 'fo--- o', ' ', '-', 'Escape special characters'),
  51 + array('fo- o', 'fo- o', ' ', '-', 'Do not escape already escaped string'),
  52 + );
  53 + }
  54 +
  55 + public function testEscapeScriptName()
  56 + {
  57 + $collection = new RouteCollection();
  58 + $collection->add('foo', new Route('/foo'));
  59 + $dumper = new ApacheMatcherDumper($collection);
  60 + $this->assertStringEqualsFile(self::$fixturesPath.'/dumper/url_matcher2.apache', $dumper->dump(array('script_name' => 'ap p_d\ ev.php')));
  61 + }
  62 +
  63 + private function getRouteCollection()
  64 + {
29 65 $collection = new RouteCollection();
30 66
31 67 // defaults and requirements
@@ -79,9 +115,11 @@ public function testDump()
79 115 '/test/baz',
80 116 array('foo' => 'bar baz')
81 117 ));
  118 + // space in path
  119 + $collection->add('baz7', new Route(
  120 + '/te st/baz'
  121 + ));
82 122
83   - $dumper = new ApacheMatcherDumper($collection);
84   -
85   - $this->assertStringEqualsFile(self::$fixturesPath.'/dumper/url_matcher1.apache', $dumper->dump(), '->dump() dumps basic routes to the correct apache format.');
  123 + return $collection;
86 124 }
87 125 }
4 src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php
@@ -123,6 +123,10 @@ protected function getRouteCollection()
123 123 array(),
124 124 array('quoter' => '[\']+')
125 125 ));
  126 + // space in pattern
  127 + $collection->add('space', new Route(
  128 + '/spa ce'
  129 + ));
126 130
127 131 // prefixes
128 132 $collection1 = new RouteCollection();
18 src/Symfony/Component/Routing/Tests/RouteCompilerTest.php
@@ -25,7 +25,7 @@ public function testCompile($name, $arguments, $prefix, $regex, $variables, $tok
25 25
26 26 $compiled = $route->compile();
27 27 $this->assertEquals($prefix, $compiled->getStaticPrefix(), $name.' (static prefix)');
28   - $this->assertEquals($regex, str_replace(array("\n", ' '), '', $compiled->getRegex()), $name.' (regex)');
  28 + $this->assertEquals($regex, $compiled->getRegex(), $name.' (regex)');
29 29 $this->assertEquals($variables, $compiled->getVariables(), $name.' (variables)');
30 30 $this->assertEquals($tokens, $compiled->getTokens(), $name.' (tokens)');
31 31 }
@@ -36,14 +36,14 @@ public function provideCompileData()
36 36 array(
37 37 'Static route',
38 38 array('/foo'),
39   - '/foo', '#^/foo$#xs', array(), array(
  39 + '/foo', '#^/foo$#s', array(), array(
40 40 array('text', '/foo'),
41 41 )),
42 42
43 43 array(
44 44 'Route with a variable',
45 45 array('/foo/{bar}'),
46   - '/foo', '#^/foo/(?P<bar>[^/]+?)$#xs', array('bar'), array(
  46 + '/foo', '#^/foo/(?P<bar>[^/]+?)$#s', array('bar'), array(
47 47 array('variable', '/', '[^/]+?', 'bar'),
48 48 array('text', '/foo'),
49 49 )),
@@ -51,7 +51,7 @@ public function provideCompileData()
51 51 array(
52 52 'Route with a variable that has a default value',
53 53 array('/foo/{bar}', array('bar' => 'bar')),
54   - '/foo', '#^/foo(?:/(?P<bar>[^/]+?))?$#xs', array('bar'), array(
  54 + '/foo', '#^/foo(?:/(?P<bar>[^/]+?))?$#s', array('bar'), array(
55 55 array('variable', '/', '[^/]+?', 'bar'),
56 56 array('text', '/foo'),
57 57 )),
@@ -59,7 +59,7 @@ public function provideCompileData()
59 59 array(
60 60 'Route with several variables',
61 61 array('/foo/{bar}/{foobar}'),
62   - '/foo', '#^/foo/(?P<bar>[^/]+?)/(?P<foobar>[^/]+?)$#xs', array('bar', 'foobar'), array(
  62 + '/foo', '#^/foo/(?P<bar>[^/]+?)/(?P<foobar>[^/]+?)$#s', array('bar', 'foobar'), array(
63 63 array('variable', '/', '[^/]+?', 'foobar'),
64 64 array('variable', '/', '[^/]+?', 'bar'),
65 65 array('text', '/foo'),
@@ -68,7 +68,7 @@ public function provideCompileData()
68 68 array(
69 69 'Route with several variables that have default values',
70 70 array('/foo/{bar}/{foobar}', array('bar' => 'bar', 'foobar' => '')),
71   - '/foo', '#^/foo(?:/(?P<bar>[^/]+?)(?:/(?P<foobar>[^/]+?))?)?$#xs', array('bar', 'foobar'), array(
  71 + '/foo', '#^/foo(?:/(?P<bar>[^/]+?)(?:/(?P<foobar>[^/]+?))?)?$#s', array('bar', 'foobar'), array(
72 72 array('variable', '/', '[^/]+?', 'foobar'),
73 73 array('variable', '/', '[^/]+?', 'bar'),
74 74 array('text', '/foo'),
@@ -77,7 +77,7 @@ public function provideCompileData()
77 77 array(
78 78 'Route with several variables but some of them have no default values',
79 79 array('/foo/{bar}/{foobar}', array('bar' => 'bar')),
80   - '/foo', '#^/foo/(?P<bar>[^/]+?)/(?P<foobar>[^/]+?)$#xs', array('bar', 'foobar'), array(
  80 + '/foo', '#^/foo/(?P<bar>[^/]+?)/(?P<foobar>[^/]+?)$#s', array('bar', 'foobar'), array(
81 81 array('variable', '/', '[^/]+?', 'foobar'),
82 82 array('variable', '/', '[^/]+?', 'bar'),
83 83 array('text', '/foo'),
@@ -86,14 +86,14 @@ public function provideCompileData()
86 86 array(
87 87 'Route with an optional variable as the first segment',
88 88 array('/{bar}', array('bar' => 'bar')),
89   - '', '#^/(?:(?P<bar>[^/]+?))?$#xs', array('bar'), array(
  89 + '', '#^/(?P<bar>[^/]+?)?$#s', array('bar'), array(
90 90 array('variable', '/', '[^/]+?', 'bar'),
91 91 )),
92 92
93 93 array(
94 94 'Route with an optional variable as the first segment with requirements',
95 95 array('/{bar}', array('bar' => 'bar'), array('bar' => '(foo|bar)')),
96   - '', '#^/(?:(?P<bar>(foo|bar)))?$#xs', array('bar'), array(
  96 + '', '#^/(?P<bar>(foo|bar))?$#s', array('bar'), array(
97 97 array('variable', '/', '(foo|bar)', 'bar'),
98 98 )),
99 99 );

0 comments on commit c7ba1b9

Please sign in to comment.
Something went wrong with that request. Please try again.