public function ApacheMatcherDumper::dump

Dumps a set of Apache mod_rewrite rules.

Available options:

  • script_name: The script name (app.php by default)
  • base_uri: The base URI ("" by default)

Parameters

array $options An array of options:

Return value

string A string to be used as Apache rewrite rules

Throws

\LogicException When the route regex is invalid

Overrides MatcherDumperInterface::dump

File

drupal/core/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php, line 36

Class

ApacheMatcherDumper
Dumps a set of Apache mod_rewrite rules.

Namespace

Symfony\Component\Routing\Matcher\Dumper

Code

public function dump(array $options = array()) {
  $options = array_merge(array(
    'script_name' => 'app.php',
    'base_uri' => '',
  ), $options);
  $options['script_name'] = self::escape($options['script_name'], ' ', '\\');
  $rules = array(
    "# skip \"real\" requests\nRewriteCond %{REQUEST_FILENAME} -f\nRewriteRule .* - [QSA,L]",
  );
  $methodVars = array();
  foreach ($this
    ->getRoutes()
    ->all() as $name => $route) {
    $compiledRoute = $route
      ->compile();

    // prepare the apache regex
    $regex = $compiledRoute
      ->getRegex();
    $delimiter = $regex[0];
    $regexPatternEnd = strrpos($regex, $delimiter);
    if (strlen($regex) < 2 || 0 === $regexPatternEnd) {
      throw new \LogicException('The "%s" route regex "%s" is invalid', $name, $regex);
    }
    $regex = preg_replace('/\\?<.+?>/', '', substr($regex, 1, $regexPatternEnd - 1));
    $regex = '^' . self::escape(preg_quote($options['base_uri']) . substr($regex, 1), ' ', '\\');
    $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';
      }
    }
    $hasTrailingSlash = (!$methods || in_array('HEAD', $methods)) && '/$' === substr($regex, -2) && '^/$' !== $regex;
    $variables = array(
      'E=_ROUTING__route:' . $name,
    );
    foreach ($compiledRoute
      ->getVariables() as $i => $variable) {
      $variables[] = 'E=_ROUTING_' . $variable . ':%' . ($i + 1);
    }
    foreach ($route
      ->getDefaults() as $key => $value) {
      $variables[] = 'E=_ROUTING_DEFAULTS_' . $key . ':' . strtr($value, array(
        ':' => '\\:',
        '=' => '\\=',
        '\\' => '\\\\',
        ' ' => '\\ ',
      ));
    }
    $variables = implode(',', $variables);
    $rule = array(
      "# {$name}",
    );

    // method mismatch
    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';
      }
      $allow = array();
      foreach ($methods as $method) {
        $methodVars[] = $method;
        $allow[] = 'E=_ROUTING__allow_' . $method . ':1';
      }
      $rule[] = "RewriteCond %{REQUEST_URI} {$regex}";
      $rule[] = sprintf("RewriteCond %%{REQUEST_METHOD} !^(%s)\$ [NC]", implode('|', $methods));
      $rule[] = sprintf('RewriteRule .* - [S=%d,%s]', $hasTrailingSlash ? 2 : 1, implode(',', $allow));
    }

    // redirect with trailing slash appended
    if ($hasTrailingSlash) {
      $rule[] = 'RewriteCond %{REQUEST_URI} ' . substr($regex, 0, -2) . '$';
      $rule[] = 'RewriteRule .* $0/ [QSA,L,R=301]';
    }

    // the main rule
    $rule[] = "RewriteCond %{REQUEST_URI} {$regex}";
    $rule[] = "RewriteRule .* {$options['script_name']} [QSA,L,{$variables}]";
    $rules[] = implode("\n", $rule);
  }
  if (0 < count($methodVars)) {
    $rule = array(
      '# 405 Method Not Allowed',
    );
    $methodVars = array_values(array_unique($methodVars));
    foreach ($methodVars as $i => $methodVar) {
      $rule[] = sprintf('RewriteCond %%{_ROUTING__allow_%s} !-z%s', $methodVar, isset($methodVars[$i + 1]) ? ' [OR]' : '');
    }
    $rule[] = sprintf('RewriteRule .* %s [QSA,L]', $options['script_name']);
    $rules[] = implode("\n", $rule);
  }
  return implode("\n\n", $rules) . "\n";
}