You are here

private function PhpMatcherDumper::compileRoute in Zircon Profile 8

Same name and namespace in other branches
  1. 8.0 vendor/symfony/routing/Matcher/Dumper/PhpMatcherDumper.php \Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper::compileRoute()

Compiles a single Route to PHP code used to match it against the path info.

Parameters

Route $route A Route instance:

string $name The name of the Route:

bool $supportsRedirections Whether redirections are supported by the base class:

string|null $parentPrefix The prefix of the parent collection used to optimize the code:

Return value

string PHP code

Throws

\LogicException

1 call to PhpMatcherDumper::compileRoute()
PhpMatcherDumper::compilePrefixRoutes in vendor/symfony/routing/Matcher/Dumper/PhpMatcherDumper.php
Generates PHP code recursively to match a tree of routes.

File

vendor/symfony/routing/Matcher/Dumper/PhpMatcherDumper.php, line 210

Class

PhpMatcherDumper
PhpMatcherDumper creates a PHP class able to match URLs for a given set of routes.

Namespace

Symfony\Component\Routing\Matcher\Dumper

Code

private function compileRoute(Route $route, $name, $supportsRedirections, $parentPrefix = null) {
  $code = '';
  $compiledRoute = $route
    ->compile();
  $conditions = array();
  $hasTrailingSlash = false;
  $matches = false;
  $hostMatches = false;
  $methods = $route
    ->getMethods();

  // 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;
  }
  if ($route
    ->getCondition()) {
    $conditions[] = $this
      ->getExpressionLanguage()
      ->compile($route
      ->getCondition(), array(
      'context',
      'request',
    ));
  }
  $conditions = implode(' && ', $conditions);
  $code .= <<<EOF
        // {<span class="php-variable">$name</span>}
        if ({<span class="php-variable">$conditions</span>}) {

EOF;
  $gotoname = 'not_' . preg_replace('/[^A-Za-z0-9_]/', '', $name);
  if ($methods) {
    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 ($schemes = $route
    ->getSchemes()) {
    if (!$supportsRedirections) {
      throw new \LogicException('The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.');
    }
    $schemes = str_replace("\n", '', var_export(array_flip($schemes), true));
    $code .= <<<EOF
            \$requiredSchemes = {<span class="php-variable">$schemes</span>};
            if (!isset(\$requiredSchemes[\$this->context->getScheme()])) {
                return \$this->redirect(\$pathinfo, '{<span class="php-variable">$name</span>}', key(\$requiredSchemes));
            }


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;
}