[ Index ]

PHP Cross Reference of phpBB-3.1.12-deutsch

title

Body

[close]

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


Generated: Thu Jan 11 00:25:41 2018 Cross-referenced by PHPXref 0.7.1