vendor/symfony/src/Symfony/Component/Routing/RouteCompiler.php
changeset 0 7f95f8617b0b
equal deleted inserted replaced
-1:000000000000 0:7f95f8617b0b
       
     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 /**
       
    15  * RouteCompiler compiles Route instances to CompiledRoute instances.
       
    16  *
       
    17  * @author Fabien Potencier <fabien@symfony.com>
       
    18  */
       
    19 class RouteCompiler implements RouteCompilerInterface
       
    20 {
       
    21     /**
       
    22      * Compiles the current route instance.
       
    23      *
       
    24      * @param Route $route A Route instance
       
    25      *
       
    26      * @return CompiledRoute A CompiledRoute instance
       
    27      */
       
    28     public function compile(Route $route)
       
    29     {
       
    30         $pattern = $route->getPattern();
       
    31         $len = strlen($pattern);
       
    32         $tokens = array();
       
    33         $variables = array();
       
    34         $pos = 0;
       
    35         preg_match_all('#.\{([\w\d_]+)\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
       
    36         foreach ($matches as $match) {
       
    37             if ($text = substr($pattern, $pos, $match[0][1] - $pos)) {
       
    38                 $tokens[] = array('text', $text);
       
    39             }
       
    40             $seps = array($pattern[$pos]);
       
    41             $pos = $match[0][1] + strlen($match[0][0]);
       
    42             $var = $match[1][0];
       
    43 
       
    44             if ($req = $route->getRequirement($var)) {
       
    45                 $regexp = $req;
       
    46             } else {
       
    47                 if ($pos !== $len) {
       
    48                     $seps[] = $pattern[$pos];
       
    49                 }
       
    50                 $regexp = sprintf('[^%s]+?', preg_quote(implode('', array_unique($seps)), '#'));
       
    51             }
       
    52 
       
    53             $tokens[] = array('variable', $match[0][0][0], $regexp, $var);
       
    54             $variables[] = $var;
       
    55         }
       
    56 
       
    57         if ($pos < $len) {
       
    58             $tokens[] = array('text', substr($pattern, $pos));
       
    59         }
       
    60 
       
    61         // find the first optional token
       
    62         $firstOptional = INF;
       
    63         for ($i = count($tokens) - 1; $i >= 0; $i--) {
       
    64             if ('variable' === $tokens[$i][0] && $route->hasDefault($tokens[$i][3])) {
       
    65                 $firstOptional = $i;
       
    66             } else {
       
    67                 break;
       
    68             }
       
    69         }
       
    70 
       
    71         // compute the matching regexp
       
    72         $regex = '';
       
    73         $indent = 1;
       
    74         if (1 === count($tokens) && 0 === $firstOptional) {
       
    75             $token = $tokens[0];
       
    76             ++$indent;
       
    77             $regex .= str_repeat(' ', $indent * 4).sprintf("%s(?:\n", preg_quote($token[1], '#'));
       
    78             $regex .= str_repeat(' ', $indent * 4).sprintf("(?P<%s>%s)\n", $token[3], $token[2]);
       
    79         } else {
       
    80             foreach ($tokens as $i => $token) {
       
    81                 if ('text' === $token[0]) {
       
    82                     $regex .= str_repeat(' ', $indent * 4).preg_quote($token[1], '#')."\n";
       
    83                 } else {
       
    84                     if ($i >= $firstOptional) {
       
    85                         $regex .= str_repeat(' ', $indent * 4)."(?:\n";
       
    86                         ++$indent;
       
    87                     }
       
    88                     $regex .= str_repeat(' ', $indent * 4).sprintf("%s(?P<%s>%s)\n", preg_quote($token[1], '#'), $token[3], $token[2]);
       
    89                 }
       
    90             }
       
    91         }
       
    92         while (--$indent) {
       
    93             $regex .= str_repeat(' ', $indent * 4).")?\n";
       
    94         }
       
    95 
       
    96         return new CompiledRoute(
       
    97             $route,
       
    98             'text' === $tokens[0][0] ? $tokens[0][1] : '',
       
    99             sprintf("#^\n%s$#x", $regex),
       
   100             array_reverse($tokens),
       
   101             $variables
       
   102         );
       
   103     }
       
   104 }