vendor/symfony/src/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php
changeset 0 7f95f8617b0b
equal deleted inserted replaced
-1:000000000000 0:7f95f8617b0b
       
     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     public function dump(array $options = array())
       
    37     {
       
    38         $options = array_merge(array(
       
    39             'script_name' => 'app.php',
       
    40             'base_uri'    => '',
       
    41         ), $options);
       
    42 
       
    43         $rules = array("# skip \"real\" requests\nRewriteCond %{REQUEST_FILENAME} -f\nRewriteRule .* - [QSA,L]");
       
    44         $methodVars = array();
       
    45 
       
    46         foreach ($this->getRoutes()->all() as $name => $route) {
       
    47             $compiledRoute = $route->compile();
       
    48 
       
    49             // prepare the apache regex
       
    50             $regex = preg_replace('/\?P<.+?>/', '', substr(str_replace(array("\n", ' '), '', $compiledRoute->getRegex()), 1, -2));
       
    51             $regex = '^'.preg_quote($options['base_uri']).substr($regex, 1);
       
    52 
       
    53             $hasTrailingSlash = '/$' == substr($regex, -2) && '^/$' != $regex;
       
    54 
       
    55             $variables = array('E=_ROUTING__route:'.$name);
       
    56             foreach ($compiledRoute->getVariables() as $i => $variable) {
       
    57                 $variables[] = 'E=_ROUTING_'.$variable.':%'.($i + 1);
       
    58             }
       
    59             foreach ($route->getDefaults() as $key => $value) {
       
    60                 // todo: a more legit way to escape the value?
       
    61                 $variables[] = 'E=_ROUTING_'.$key.':'.strtr($value, array(
       
    62                     ':'  => '\\:',
       
    63                     '='  => '\\=',
       
    64                     '\\' => '\\\\',
       
    65                     ' '  => '\\ ',
       
    66                 ));
       
    67             }
       
    68             $variables = implode(',', $variables);
       
    69 
       
    70             $rule = array("# $name");
       
    71 
       
    72             // method mismatch
       
    73             if ($req = $route->getRequirement('_method')) {
       
    74                 $methods = explode('|', strtoupper($req));
       
    75                 // GET and HEAD are equivalent
       
    76                 if (in_array('GET', $methods) && !in_array('HEAD', $methods)) {
       
    77                     $methods[] = 'HEAD';
       
    78                 }
       
    79                 $allow = array();
       
    80                 foreach ($methods as $method) {
       
    81                     $methodVars[] = $method;
       
    82                     $allow[] = 'E=_ROUTING__allow_'.$method.':1';
       
    83                 }
       
    84 
       
    85                 $rule[] = "RewriteCond %{REQUEST_URI} $regex";
       
    86                 $rule[] = sprintf("RewriteCond %%{REQUEST_METHOD} !^(%s)$ [NC]", implode('|', $methods));
       
    87                 $rule[] = sprintf('RewriteRule .* - [S=%d,%s]', $hasTrailingSlash ? 2 : 1, implode(',', $allow));
       
    88             }
       
    89 
       
    90             // redirect with trailing slash appended
       
    91             if ($hasTrailingSlash) {
       
    92                 $rule[] = 'RewriteCond %{REQUEST_URI} '.substr($regex, 0, -2).'$';
       
    93                 $rule[] = 'RewriteRule .* $0/ [QSA,L,R=301]';
       
    94             }
       
    95 
       
    96             // the main rule
       
    97             $rule[] = "RewriteCond %{REQUEST_URI} $regex";
       
    98             $rule[] = "RewriteRule .* {$options['script_name']} [QSA,L,$variables]";
       
    99 
       
   100             $rules[] = implode("\n", $rule);
       
   101         }
       
   102 
       
   103         if (0 < count($methodVars)) {
       
   104             $rule = array('# 405 Method Not Allowed');
       
   105             $methodVars = array_values(array_unique($methodVars));
       
   106             foreach ($methodVars as $i => $methodVar) {
       
   107                 $rule[] = sprintf('RewriteCond %%{_ROUTING__allow_%s} !-z%s', $methodVar, isset($methodVars[$i + 1]) ? ' [OR]' : '');
       
   108             }
       
   109             $rule[] = sprintf('RewriteRule .* %s [QSA,L]', $options['script_name']);
       
   110 
       
   111             $rules[] = implode("\n", $rule);
       
   112         }
       
   113 
       
   114         return implode("\n\n", $rules)."\n";
       
   115     }
       
   116 }