[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/vendor/symfony/routing/Matcher/Dumper/ -> ApacheMatcherDumper.php (source)

   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\Matcher\Dumper;
  13  
  14  @trigger_error('The '.__NAMESPACE__.'\ApacheMatcherDumper class is deprecated since Symfony 2.5 and will be removed in 3.0. It\'s hard to replicate the behaviour of the PHP implementation and the performance gains are minimal.', E_USER_DEPRECATED);
  15  
  16  use Symfony\Component\Routing\Route;
  17  
  18  /**
  19   * Dumps a set of Apache mod_rewrite rules.
  20   *
  21   * @deprecated since version 2.5, to be removed in 3.0.
  22   *             The performance gains are minimal and it's very hard to replicate
  23   *             the behavior of PHP implementation.
  24   *
  25   * @author Fabien Potencier <fabien@symfony.com>
  26   * @author Kris Wallsmith <kris@symfony.com>
  27   */
  28  class ApacheMatcherDumper extends MatcherDumper
  29  {
  30      /**
  31       * Dumps a set of Apache mod_rewrite rules.
  32       *
  33       * Available options:
  34       *
  35       *  * script_name: The script name (app.php by default)
  36       *  * base_uri:    The base URI ("" by default)
  37       *
  38       * @return string A string to be used as Apache rewrite rules
  39       *
  40       * @throws \LogicException When the route regex is invalid
  41       */
  42      public function dump(array $options = array())
  43      {
  44          $options = array_merge(array(
  45              'script_name' => 'app.php',
  46              'base_uri' => '',
  47          ), $options);
  48  
  49          $options['script_name'] = self::escape($options['script_name'], ' ', '\\');
  50  
  51          $rules = array("# skip \"real\" requests\nRewriteCond %{REQUEST_FILENAME} -f\nRewriteRule .* - [QSA,L]");
  52          $methodVars = array();
  53          $hostRegexUnique = 0;
  54          $prevHostRegex = '';
  55  
  56          foreach ($this->getRoutes()->all() as $name => $route) {
  57              if ($route->getCondition()) {
  58                  throw new \LogicException(sprintf('Unable to dump the routes for Apache as route "%s" has a condition.', $name));
  59              }
  60  
  61              $compiledRoute = $route->compile();
  62              $hostRegex = $compiledRoute->getHostRegex();
  63  
  64              if (null !== $hostRegex && $prevHostRegex !== $hostRegex) {
  65                  $prevHostRegex = $hostRegex;
  66                  ++$hostRegexUnique;
  67  
  68                  $rule = array();
  69  
  70                  $regex = $this->regexToApacheRegex($hostRegex);
  71                  $regex = self::escape($regex, ' ', '\\');
  72  
  73                  $rule[] = sprintf('RewriteCond %%{HTTP:Host} %s', $regex);
  74  
  75                  $variables = array();
  76                  $variables[] = sprintf('E=__ROUTING_host_%s:1', $hostRegexUnique);
  77  
  78                  foreach ($compiledRoute->getHostVariables() as $i => $variable) {
  79                      $variables[] = sprintf('E=__ROUTING_host_%s_%s:%%%d', $hostRegexUnique, $variable, $i + 1);
  80                  }
  81  
  82                  $variables = implode(',', $variables);
  83  
  84                  $rule[] = sprintf('RewriteRule .? - [%s]', $variables);
  85  
  86                  $rules[] = implode("\n", $rule);
  87              }
  88  
  89              $rules[] = $this->dumpRoute($name, $route, $options, $hostRegexUnique);
  90  
  91              $methodVars = array_merge($methodVars, $route->getMethods());
  92          }
  93          if (0 < \count($methodVars)) {
  94              $rule = array('# 405 Method Not Allowed');
  95              $methodVars = array_values(array_unique($methodVars));
  96              if (\in_array('GET', $methodVars) && !\in_array('HEAD', $methodVars)) {
  97                  $methodVars[] = 'HEAD';
  98              }
  99              foreach ($methodVars as $i => $methodVar) {
 100                  $rule[] = sprintf('RewriteCond %%{ENV:_ROUTING__allow_%s} =1%s', $methodVar, isset($methodVars[$i + 1]) ? ' [OR]' : '');
 101              }
 102              $rule[] = sprintf('RewriteRule .* %s [QSA,L]', $options['script_name']);
 103  
 104              $rules[] = implode("\n", $rule);
 105          }
 106  
 107          return implode("\n\n", $rules)."\n";
 108      }
 109  
 110      /**
 111       * Dumps a single route.
 112       *
 113       * @param string $name            Route name
 114       * @param Route  $route           The route
 115       * @param array  $options         Options
 116       * @param bool   $hostRegexUnique Unique identifier for the host regex
 117       *
 118       * @return string The compiled route
 119       */
 120      private function dumpRoute($name, $route, array $options, $hostRegexUnique)
 121      {
 122          $compiledRoute = $route->compile();
 123  
 124          // prepare the apache regex
 125          $regex = $this->regexToApacheRegex($compiledRoute->getRegex());
 126          $regex = '^'.self::escape(preg_quote($options['base_uri']).substr($regex, 1), ' ', '\\');
 127  
 128          $methods = $this->getRouteMethods($route);
 129  
 130          $hasTrailingSlash = (!$methods || \in_array('HEAD', $methods)) && '/$' === substr($regex, -2) && '^/$' !== $regex;
 131  
 132          $variables = array('E=_ROUTING_route:'.$name);
 133          foreach ($compiledRoute->getHostVariables() as $variable) {
 134              $variables[] = sprintf('E=_ROUTING_param_%s:%%{ENV:__ROUTING_host_%s_%s}', $variable, $hostRegexUnique, $variable);
 135          }
 136          foreach ($compiledRoute->getPathVariables() as $i => $variable) {
 137              $variables[] = 'E=_ROUTING_param_'.$variable.':%'.($i + 1);
 138          }
 139          foreach ($this->normalizeValues($route->getDefaults()) as $key => $value) {
 140              $variables[] = 'E=_ROUTING_default_'.$key.':'.strtr($value, array(
 141                  ':' => '\\:',
 142                  '=' => '\\=',
 143                  '\\' => '\\\\',
 144                  ' ' => '\\ ',
 145              ));
 146          }
 147          $variables = implode(',', $variables);
 148  
 149          $rule = array("# $name");
 150  
 151          // method mismatch
 152          if (0 < \count($methods)) {
 153              $allow = array();
 154              foreach ($methods as $method) {
 155                  $allow[] = 'E=_ROUTING_allow_'.$method.':1';
 156              }
 157  
 158              if ($compiledRoute->getHostRegex()) {
 159                  $rule[] = sprintf('RewriteCond %%{ENV:__ROUTING_host_%s} =1', $hostRegexUnique);
 160              }
 161  
 162              $rule[] = "RewriteCond %{REQUEST_URI} $regex";
 163              $rule[] = sprintf('RewriteCond %%{REQUEST_METHOD} !^(%s)$ [NC]', implode('|', $methods));
 164              $rule[] = sprintf('RewriteRule .* - [S=%d,%s]', $hasTrailingSlash ? 2 : 1, implode(',', $allow));
 165          }
 166  
 167          // redirect with trailing slash appended
 168          if ($hasTrailingSlash) {
 169              if ($compiledRoute->getHostRegex()) {
 170                  $rule[] = sprintf('RewriteCond %%{ENV:__ROUTING_host_%s} =1', $hostRegexUnique);
 171              }
 172  
 173              $rule[] = 'RewriteCond %{REQUEST_URI} '.substr($regex, 0, -2).'$';
 174              $rule[] = 'RewriteRule .* $0/ [QSA,L,R=301]';
 175          }
 176  
 177          // the main rule
 178  
 179          if ($compiledRoute->getHostRegex()) {
 180              $rule[] = sprintf('RewriteCond %%{ENV:__ROUTING_host_%s} =1', $hostRegexUnique);
 181          }
 182  
 183          $rule[] = "RewriteCond %{REQUEST_URI} $regex";
 184          $rule[] = "RewriteRule .* {$options['script_name']} [QSA,L,$variables]";
 185  
 186          return implode("\n", $rule);
 187      }
 188  
 189      /**
 190       * Returns methods allowed for a route.
 191       *
 192       * @return array The methods
 193       */
 194      private function getRouteMethods(Route $route)
 195      {
 196          $methods = $route->getMethods();
 197  
 198          // GET and HEAD are equivalent
 199          if (\in_array('GET', $methods) && !\in_array('HEAD', $methods)) {
 200              $methods[] = 'HEAD';
 201          }
 202  
 203          return $methods;
 204      }
 205  
 206      /**
 207       * Converts a regex to make it suitable for mod_rewrite.
 208       *
 209       * @param string $regex The regex
 210       *
 211       * @return string The converted regex
 212       */
 213      private function regexToApacheRegex($regex)
 214      {
 215          $regexPatternEnd = strrpos($regex, $regex[0]);
 216  
 217          return preg_replace('/\?P<.+?>/', '', substr($regex, 1, $regexPatternEnd - 1));
 218      }
 219  
 220      /**
 221       * Escapes a string.
 222       *
 223       * @param string $string The string to be escaped
 224       * @param string $char   The character to be escaped
 225       * @param string $with   The character to be used for escaping
 226       *
 227       * @return string The escaped string
 228       */
 229      private static function escape($string, $char, $with)
 230      {
 231          $escaped = false;
 232          $output = '';
 233          foreach (str_split($string) as $symbol) {
 234              if ($escaped) {
 235                  $output .= $symbol;
 236                  $escaped = false;
 237                  continue;
 238              }
 239              if ($symbol === $char) {
 240                  $output .= $with.$char;
 241                  continue;
 242              }
 243              if ($symbol === $with) {
 244                  $escaped = true;
 245              }
 246              $output .= $symbol;
 247          }
 248  
 249          return $output;
 250      }
 251  
 252      /**
 253       * Normalizes an array of values.
 254       *
 255       * @return string[]
 256       */
 257      private function normalizeValues(array $values)
 258      {
 259          $normalizedValues = array();
 260          foreach ($values as $key => $value) {
 261              if (\is_array($value)) {
 262                  foreach ($value as $index => $bit) {
 263                      $normalizedValues[sprintf('%s[%s]', $key, $index)] = $bit;
 264                  }
 265              } else {
 266                  $normalizedValues[$key] = (string) $value;
 267              }
 268          }
 269  
 270          return $normalizedValues;
 271      }
 272  }


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1