Вход Регистрация
Файл: forsoc.ru/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php
Строк: 185
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace SymfonyComponentRoutingMatcherDumper;

use 
SymfonyComponentRoutingRoute;

/**
 * Dumps a set of Apache mod_rewrite rules.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Kris Wallsmith <kris@symfony.com>
 */
class ApacheMatcherDumper extends MatcherDumper
{
    
/**
     * 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)
     *
     * @param array $options An array of options
     *
     * @return string A string to be used as Apache rewrite rules
     *
     * @throws LogicException When the route regex is invalid
     */
    
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" requestsnRewriteCond %{REQUEST_FILENAME} -fnRewriteRule .* - [QSA,L]");
        $methodVars = array();
        $hostRegexUnique = 0;
        $prevHostRegex = '';

        foreach ($this->getRoutes()->all() as $name => $route) {
            $compiledRoute = $route->compile();
            $hostRegex = $compiledRoute->getHostRegex();

            if (null !== $hostRegex && $prevHostRegex !== $hostRegex) {
                $prevHostRegex = $hostRegex;
                ++$hostRegexUnique;

                $rule = array();

                $regex = $this->regexToApacheRegex($hostRegex);
                $regex = self::escape($regex, ' ', '
\');

                $rule[] = sprintf('
RewriteCond %%{HTTP:Host} %s', $regex);

                $variables = array();
                $variables[] = sprintf('
E=__ROUTING_host_%s:1', $hostRegexUnique);

                foreach ($compiledRoute->getHostVariables() as $i => $variable) {
                    $variables[] = sprintf('
E=__ROUTING_host_%s_%s:%%%d', $hostRegexUnique, $variable, $i + 1);
                }

                $variables = implode('
,', $variables);

                $rule[] = sprintf('
RewriteRule .? - [%s]', $variables);

                $rules[] = implode("n", $rule);
            }

            $rules[] = $this->dumpRoute($name, $route, $options, $hostRegexUnique);

            if ($req = $route->getRequirement('
_method')) {
                $methods = explode('
|', strtoupper($req));
                $methodVars = array_merge($methodVars, $methods);
            }
        }
        if (0 < count($methodVars)) {
            $rule = array('
# 405 Method Not Allowed');
            
$methodVars array_values(array_unique($methodVars));
            if (
in_array('GET'$methodVars) && !in_array('HEAD'$methodVars)) {
                
$methodVars[] = 'HEAD';
            }
            foreach (
$methodVars as $i => $methodVar) {
                
$rule[] = sprintf('RewriteCond %%{ENV:_ROUTING__allow_%s} =1%s'$methodVar, isset($methodVars[$i 1]) ? ' [OR]' '');
            }
            
$rule[] = sprintf('RewriteRule .* %s [QSA,L]'$options['script_name']);

            
$rules[] = implode("n"$rule);
        }

        return 
implode("nn"$rules)."n";
    }

    
/**
     * Dumps a single route.
     *
     * @param string $name            Route name
     * @param Route  $route           The route
     * @param array  $options         Options
     * @param bool   $hostRegexUnique Unique identifier for the host regex
     *
     * @return string The compiled route
     */
    
private function dumpRoute($name$route, array $options$hostRegexUnique)
    {
        
$compiledRoute $route->compile();

        
// prepare the apache regex
        
$regex $this->regexToApacheRegex($compiledRoute->getRegex());
        
$regex '^'.self::escape(preg_quote($options['base_uri']).substr($regex1), ' ''\');

        $methods = $this->getRouteMethods($route);

        $hasTrailingSlash = (!$methods || in_array('
HEAD', $methods)) && '/$' === substr($regex, -2) && '^/$' !== $regex;

        $variables = array('
E=_ROUTING_route:'.$name);
        foreach ($compiledRoute->getHostVariables() as $variable) {
            $variables[] = sprintf('
E=_ROUTING_param_%s:%%{ENV:__ROUTING_host_%s_%s}', $variable, $hostRegexUnique, $variable);
        }
        foreach ($compiledRoute->getPathVariables() as $i => $variable) {
            $variables[] = '
E=_ROUTING_param_'.$variable.':%'.($i + 1);
        }
        foreach ($this->normalizeValues($route->getDefaults()) as $key => $value) {
            $variables[] = '
E=_ROUTING_default_'.$key.':'.strtr($value, array(
                '
:' => '\:',
                '
=' => '\=',
                '
\' => '\\',
                ' ' => '
',
            ));
        }
        $variables = implode('
,', $variables);

        $rule = array("# $name");

        // method mismatch
        if (0 < count($methods)) {
            $allow = array();
            foreach ($methods as $method) {
                $allow[] = '
E=_ROUTING_allow_'.$method.':1';
            }

            if ($compiledRoute->getHostRegex()) {
                $rule[] = sprintf('
RewriteCond %%{ENV:__ROUTING_host_%s} =1', $hostRegexUnique);
            }

            $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) {
            if ($compiledRoute->getHostRegex()) {
                $rule[] = sprintf('
RewriteCond %%{ENV:__ROUTING_host_%s} =1', $hostRegexUnique);
            }

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

        // the main rule

        if ($compiledRoute->getHostRegex()) {
            $rule[] = sprintf('
RewriteCond %%{ENV:__ROUTING_host_%s} =1', $hostRegexUnique);
        }

        $rule[] = "RewriteCond %{REQUEST_URI} $regex";
        $rule[] = "RewriteRule .* {$options['
script_name']} [QSA,L,$variables]";

        return implode("n", $rule);
    }

    /**
     * Returns methods allowed for a route.
     *
     * @param Route $route The route
     *
     * @return array The methods
     */
    private function getRouteMethods(Route $route)
    {
        $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';
            }
        }

        return $methods;
    }

    /**
     * Converts a regex to make it suitable for mod_rewrite.
     *
     * @param string $regex The regex
     *
     * @return string The converted regex
     */
    private function regexToApacheRegex($regex)
    {
        $regexPatternEnd = strrpos($regex, $regex[0]);

        return preg_replace('
/?P<.+?>/', '', substr($regex, 1, $regexPatternEnd - 1));
    }

    /**
     * Escapes a string.
     *
     * @param string $string The string to be escaped
     * @param string $char   The character to be escaped
     * @param string $with   The character to be used for escaping
     *
     * @return string The escaped string
     */
    private static function escape($string, $char, $with)
    {
        $escaped = false;
        $output = '';
        foreach (str_split($string) as $symbol) {
            if ($escaped) {
                $output .= $symbol;
                $escaped = false;
                continue;
            }
            if ($symbol === $char) {
                $output .= $with.$char;
                continue;
            }
            if ($symbol === $with) {
                $escaped = true;
            }
            $output .= $symbol;
        }

        return $output;
    }

    /**
     * Normalizes an array of values.
     *
     * @param array $values
     *
     * @return string[]
     */
    private function normalizeValues(array $values)
    {
        $normalizedValues = array();
        foreach ($values as $key => $value) {
            if (is_array($value)) {
                foreach ($value as $index => $bit) {
                    $normalizedValues[sprintf('%s[%s]', $key, $index)] = $bit;
                }
            } else {
                $normalizedValues[$key] = (string) $value;
            }
        }

        return $normalizedValues;
    }
}
Онлайн: 0
Реклама