Changeset 12969
- Timestamp:
- 11/13/08 12:29:35 (1 year ago)
- Files:
-
- branches/1.2/lib/routing/sfRoute.class.php (modified) (12 diffs)
- branches/1.2/test/unit/routing/sfRouteTest.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/1.2/lib/routing/sfRoute.class.php
r12968 r12969 32 32 $defaults = array(), 33 33 $requirements = array(), 34 $tokens = array(); 34 $tokens = array(), 35 $customToken = false; 35 36 36 37 /** … … 211 212 } 212 213 213 if ($this->options['generate_shortest_url']) 214 { 215 // construct the shortest URL possible 216 $url = array(); 217 $optional = true; 218 $first = true; 219 $tokens = array_reverse($this->tokens); 220 foreach ($tokens as $token) 221 { 222 switch ($token[0]) 223 { 224 case 'variable': 225 if (!$optional || !isset($this->defaults[$token[3]]) || $tparams[$token[3]] != $this->defaults[$token[3]]) 226 { 227 $url[] = urlencode($tparams[$token[3]]); 228 $optional = false; 229 } 230 break; 231 case 'text': 232 $url[] = $token[2]; 233 $optional = false; 234 break; 235 case 'separator': 236 default: 237 if (false === $optional || $first) 238 { 239 $url[] = $token[2]; 240 } 241 break; 242 } 243 244 $first = false; 245 } 246 247 $url = implode('', array_reverse($url)); 248 if (!$url) 249 { 250 $url = '/'; 251 } 214 if ($this->options['generate_shortest_url'] || $this->customToken) 215 { 216 $url = $this->generateWithTokens($tparams); 252 217 } 253 218 else … … 278 243 279 244 /** 245 * Generates a URL for the given parameters by using the route tokens. 246 * 247 * @param array $parameters An array of parameters 248 */ 249 protected function generateWithTokens($parameters) 250 { 251 $url = array(); 252 $optional = $this->options['generate_shortest_url']; 253 $first = true; 254 $tokens = array_reverse($this->tokens); 255 foreach ($tokens as $token) 256 { 257 switch ($token[0]) 258 { 259 case 'variable': 260 if (!$optional || !isset($this->defaults[$token[3]]) || $parameters[$token[3]] != $this->defaults[$token[3]]) 261 { 262 $url[] = urlencode($parameters[$token[3]]); 263 $optional = false; 264 } 265 break; 266 case 'text': 267 $url[] = $token[2]; 268 $optional = false; 269 break; 270 case 'separator': 271 if (false === $optional || $first) 272 { 273 $url[] = $token[2]; 274 } 275 break; 276 default: 277 // handle custom tokens 278 if ($segment = call_user_func_array(array($this, 'generateFor'.ucfirst(array_shift($token))), array_merge(array($optional, $parameters), $token))) 279 { 280 $url[] = $segment; 281 $optional = false; 282 } 283 break; 284 } 285 286 $first = false; 287 } 288 289 $url = implode('', array_reverse($url)); 290 if (!$url) 291 { 292 $url = '/'; 293 } 294 295 return $url; 296 } 297 298 /** 280 299 * Returns the compiled pattern. 281 300 * … … 423 442 } 424 443 444 /** 445 * Pre-compiles a route. 446 */ 425 447 protected function preCompile() 426 448 { … … 432 454 } 433 455 456 /** 457 * Post-compiles a route. 458 */ 434 459 protected function postCompile() 435 460 { … … 443 468 } 444 469 470 /** 471 * Tokenizes the route. 472 */ 445 473 protected function tokenize() 446 474 { … … 455 483 if (false !== $this->tokenizeBufferBefore($buffer, $tokens, $afterASeparator, $currentSeparator)) 456 484 { 485 // a custom token 486 $this->customToken = true; 457 487 } 458 488 else if ($afterASeparator && preg_match('#^'.$this->options['variable_prefix_regex'].'('.$this->options['variable_regex'].')#', $buffer, $match)) … … 485 515 else if (false !== $this->tokenizeBufferAfter($buffer, $tokens, $afterASeparator, $currentSeparator)) 486 516 { 517 // a custom token 518 $this->customToken = true; 487 519 } 488 520 else … … 494 526 } 495 527 528 /** 529 * Tokenizes the buffer before default logic is applied. 530 * 531 * This method must return false if the buffer has not been parsed. 532 * 533 * @param string $buffer The current route buffer 534 * @param array $tokens An array of current tokens 535 * @param Boolean $afterASeparator Whether the buffer is just after a separator 536 * @param string $currentSeparator The last matched separator 537 * 538 * @return Boolean true if a token has been generated, false otherwise 539 */ 496 540 protected function tokenizeBufferBefore(&$buffer, &$tokens, &$afterASeparator, &$currentSeparator) 497 541 { … … 499 543 } 500 544 545 /** 546 * Tokenizes the buffer after default logic is applied. 547 * 548 * This method must return false if the buffer has not been parsed. 549 * 550 * @param string $buffer The current route buffer 551 * @param array $tokens An array of current tokens 552 * @param Boolean $afterASeparator Whether the buffer is just after a separator 553 * @param string $currentSeparator The last matched separator 554 * 555 * @return Boolean true if a token has been generated, false otherwise 556 */ 501 557 protected function tokenizeBufferAfter(&$buffer, &$tokens, &$afterASeparator, &$currentSeparator) 502 558 { … … 598 654 } 599 655 600 protected function generateStarParameter($url, $defaults, $ tparams)656 protected function generateStarParameter($url, $defaults, $parameters) 601 657 { 602 658 if (false === strpos($this->regex, '<_star>')) … … 606 662 607 663 $tmp = array(); 608 foreach (array_diff_key($ tparams, $this->variables, $defaults) as $key => $value)664 foreach (array_diff_key($parameters, $this->variables, $defaults) as $key => $value) 609 665 { 610 666 if (is_array($value)) branches/1.2/test/unit/routing/sfRouteTest.php
r11794 r12969 11 11 require_once(dirname(__FILE__).'/../../bootstrap/unit.php'); 12 12 13 $t = new lime_test(4 1, new lime_output_color());13 $t = new lime_test(43, new lime_output_color()); 14 14 15 15 // ->matchesUrl() … … 148 148 $route = new sfRoute('/foo/:foo/*'); 149 149 $t->is($route->generate(array('foo' => 'bar', 'bar' => 'foo')), '/foo/bar/bar/foo', '->generateStarParameter() replaces * with all the key/pair values that are not variables'); 150 151 // custom token 152 $t->diag('custom token'); 153 154 class MyRoute extends sfRoute 155 { 156 protected function tokenizeBufferBefore(&$buffer, &$tokens, &$afterASeparator, &$currentSeparator) 157 { 158 if ($afterASeparator && preg_match('#^=('.$this->options['variable_regex'].')#', $buffer, $match)) 159 { 160 // a labelled variable 161 $this->tokens[] = array('label', $currentSeparator, $match[0], $match[1]); 162 163 $currentSeparator = ''; 164 $buffer = substr($buffer, strlen($match[0])); 165 $afterASeparator = false; 166 } 167 else 168 { 169 return false; 170 } 171 } 172 173 protected function compileForLabel($separator, $name, $variable) 174 { 175 if (!isset($this->requirements[$variable])) 176 { 177 $this->requirements[$variable] = $this->options['variable_content_regex']; 178 } 179 180 $this->segments[] = preg_quote($separator, '#').$variable.$separator.'(?P<'.$variable.'>'.$this->requirements[$variable].')'; 181 $this->variables[$variable] = $name; 182 183 if (!isset($this->defaults[$variable])) 184 { 185 $this->firstOptional = count($this->segments); 186 } 187 } 188 189 protected function generateForLabel($optional, $tparams, $separator, $name, $variable) 190 { 191 if (!empty($tparams[$variable]) && (!$optional || !isset($this->defaults[$variable]) || $tparams[$variable] != $this->defaults[$variable])) 192 { 193 return $variable . '/' . urlencode($tparams[$variable]); 194 } 195 } 196 } 197 198 $route = new MyRoute('/=foo'); 199 $t->is($route->matchesUrl('/foo/bar'), array('foo' => 'bar'), '->tokenizeBufferBefore() allows to add a custom token'); 200 $t->is($route->generate(array('foo' => 'bar')), '/foo/bar', '->compileForLabel() adds logic to generate a route for a custom token');

