Compiles a single Route to PHP code used to match it against the path info.
Route $route A Route instance:
string $name The name of the Route:
Boolean $supportsRedirections Whether redirections are supported by the base class:
string|null $parentPrefix The prefix of the parent collection used to optimize the code:
string PHP code
\LogicException
private function compileRoute(Route $route, $name, $supportsRedirections, $parentPrefix = null) {
$code = '';
$compiledRoute = $route
->compile();
$conditions = array();
$hasTrailingSlash = false;
$matches = false;
$hostMatches = false;
$methods = array();
if ($req = $route
->getRequirement('_method')) {
$methods = explode('|', strtoupper($req));
// GET and HEAD are equivalent
if (in_array('GET', $methods) && !in_array('HEAD', $methods)) {
$methods[] = 'HEAD';
}
}
$supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods));
if (!count($compiledRoute
->getPathVariables()) && false !== preg_match('#^(.)\\^(?P<url>.*?)\\$\\1#', $compiledRoute
->getRegex(), $m)) {
if ($supportsTrailingSlash && substr($m['url'], -1) === '/') {
$conditions[] = sprintf("rtrim(\$pathinfo, '/') === %s", var_export(rtrim(str_replace('\\', '', $m['url']), '/'), true));
$hasTrailingSlash = true;
}
else {
$conditions[] = sprintf("\$pathinfo === %s", var_export(str_replace('\\', '', $m['url']), true));
}
}
else {
if ($compiledRoute
->getStaticPrefix() && $compiledRoute
->getStaticPrefix() !== $parentPrefix) {
$conditions[] = sprintf("0 === strpos(\$pathinfo, %s)", var_export($compiledRoute
->getStaticPrefix(), true));
}
$regex = $compiledRoute
->getRegex();
if ($supportsTrailingSlash && ($pos = strpos($regex, '/$'))) {
$regex = substr($regex, 0, $pos) . '/?$' . substr($regex, $pos + 2);
$hasTrailingSlash = true;
}
$conditions[] = sprintf("preg_match(%s, \$pathinfo, \$matches)", var_export($regex, true));
$matches = true;
}
if ($compiledRoute
->getHostVariables()) {
$hostMatches = true;
}
$conditions = implode(' && ', $conditions);
$code .= <<<EOF
// {<span class="php-variable">$name</span>}
if ({<span class="php-variable">$conditions</span>}) {
EOF;
if ($methods) {
$gotoname = 'not_' . preg_replace('/[^A-Za-z0-9_]/', '', $name);
if (1 === count($methods)) {
$code .= <<<EOF
if (\$this->context->getMethod() != '{<span class="php-variable">$methods</span>[<span class="php-constant">0</span>]}') {
\$allow[] = '{<span class="php-variable">$methods</span>[<span class="php-constant">0</span>]}';
goto {<span class="php-variable">$gotoname</span>};
}
EOF;
}
else {
$methods = implode("', '", $methods);
$code .= <<<EOF
if (!in_array(\$this->context->getMethod(), array('{<span class="php-variable">$methods</span>}'))) {
\$allow = array_merge(\$allow, array('{<span class="php-variable">$methods</span>}'));
goto {<span class="php-variable">$gotoname</span>};
}
EOF;
}
}
if ($hasTrailingSlash) {
$code .= <<<EOF
if (substr(\$pathinfo, -1) !== '/') {
return \$this->redirect(\$pathinfo.'/', '{<span class="php-variable">$name</span>}');
}
EOF;
}
if ($scheme = $route
->getRequirement('_scheme')) {
if (!$supportsRedirections) {
throw new \LogicException('The "_scheme" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.');
}
$code .= <<<EOF
if (\$this->context->getScheme() !== '{<span class="php-variable">$scheme</span>}') {
return \$this->redirect(\$pathinfo, '{<span class="php-variable">$name</span>}', '{<span class="php-variable">$scheme</span>}');
}
EOF;
}
// optimize parameters array
if ($matches || $hostMatches) {
$vars = array();
if ($hostMatches) {
$vars[] = '$hostMatches';
}
if ($matches) {
$vars[] = '$matches';
}
$vars[] = "array('_route' => '{$name}')";
$code .= sprintf(" return \$this->mergeDefaults(array_replace(%s), %s);\n", implode(', ', $vars), str_replace("\n", '', var_export($route
->getDefaults(), true)));
}
elseif ($route
->getDefaults()) {
$code .= sprintf(" return %s;\n", str_replace("\n", '', var_export(array_replace($route
->getDefaults(), array(
'_route' => $name,
)), true)));
}
else {
$code .= sprintf(" return array('_route' => '%s');\n", $name);
}
$code .= " }\n";
if ($methods) {
$code .= " {$gotoname}:\n";
}
return $code;
}