vendor/symfony/src/Symfony/Component/Routing/RouteCompiler.php
author ymh <ymh.work@gmail.com>
Sat, 24 Sep 2011 15:40:41 +0200
changeset 0 7f95f8617b0b
permissions -rwxr-xr-x
first commit
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
<?php
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
/*
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
 * This file is part of the Symfony package.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
 * (c) Fabien Potencier <fabien@symfony.com>
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
 * For the full copyright and license information, please view the LICENSE
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
 * file that was distributed with this source code.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
 */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
namespace Symfony\Component\Routing;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
/**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
 * RouteCompiler compiles Route instances to CompiledRoute instances.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
 * @author Fabien Potencier <fabien@symfony.com>
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
 */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
class RouteCompiler implements RouteCompilerInterface
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
{
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
     * Compiles the current route instance.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
     * @param Route $route A Route instance
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
     * @return CompiledRoute A CompiledRoute instance
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
    public function compile(Route $route)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
        $pattern = $route->getPattern();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
        $len = strlen($pattern);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
        $tokens = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
        $variables = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
        $pos = 0;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
        preg_match_all('#.\{([\w\d_]+)\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
        foreach ($matches as $match) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
            if ($text = substr($pattern, $pos, $match[0][1] - $pos)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
                $tokens[] = array('text', $text);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
            $seps = array($pattern[$pos]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
            $pos = $match[0][1] + strlen($match[0][0]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
            $var = $match[1][0];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
            if ($req = $route->getRequirement($var)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
                $regexp = $req;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
                if ($pos !== $len) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
                    $seps[] = $pattern[$pos];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
                $regexp = sprintf('[^%s]+?', preg_quote(implode('', array_unique($seps)), '#'));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
            $tokens[] = array('variable', $match[0][0][0], $regexp, $var);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
            $variables[] = $var;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
        if ($pos < $len) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
            $tokens[] = array('text', substr($pattern, $pos));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
        // find the first optional token
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
        $firstOptional = INF;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
        for ($i = count($tokens) - 1; $i >= 0; $i--) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
            if ('variable' === $tokens[$i][0] && $route->hasDefault($tokens[$i][3])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
                $firstOptional = $i;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
                break;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
        // compute the matching regexp
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
        $regex = '';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
        $indent = 1;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
        if (1 === count($tokens) && 0 === $firstOptional) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
            $token = $tokens[0];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
            ++$indent;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
            $regex .= str_repeat(' ', $indent * 4).sprintf("%s(?:\n", preg_quote($token[1], '#'));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
            $regex .= str_repeat(' ', $indent * 4).sprintf("(?P<%s>%s)\n", $token[3], $token[2]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
            foreach ($tokens as $i => $token) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
                if ('text' === $token[0]) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
                    $regex .= str_repeat(' ', $indent * 4).preg_quote($token[1], '#')."\n";
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
                } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
                    if ($i >= $firstOptional) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
                        $regex .= str_repeat(' ', $indent * 4)."(?:\n";
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
                        ++$indent;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
                    $regex .= str_repeat(' ', $indent * 4).sprintf("%s(?P<%s>%s)\n", preg_quote($token[1], '#'), $token[3], $token[2]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
        while (--$indent) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
            $regex .= str_repeat(' ', $indent * 4).")?\n";
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
        return new CompiledRoute(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
            $route,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
            'text' === $tokens[0][0] ? $tokens[0][1] : '',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
            sprintf("#^\n%s$#x", $regex),
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
            array_reverse($tokens),
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
            $variables
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
        );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
}