[FrameworkBundle] Removed the deprecated RouterApacheDumperCommand

This commit is contained in:
Saro0h 2014-12-26 18:51:38 +01:00
parent d6af4d6efa
commit b552b1b182
5 changed files with 0 additions and 848 deletions

View File

@ -1,93 +0,0 @@
<?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 Symfony\Bundle\FrameworkBundle\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Routing\Matcher\Dumper\ApacheMatcherDumper;
use Symfony\Component\Routing\RouterInterface;
/**
* RouterApacheDumperCommand.
*
* @deprecated Deprecated since version 2.5, to be removed in 3.0.
* The performance gains are minimal and it's very hard to replicate
* the behavior of PHP implementation.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class RouterApacheDumperCommand extends ContainerAwareCommand
{
/**
* {@inheritdoc}
*/
public function isEnabled()
{
if (!$this->getContainer()->has('router')) {
return false;
}
$router = $this->getContainer()->get('router');
if (!$router instanceof RouterInterface) {
return false;
}
return parent::isEnabled();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('router:dump-apache')
->setDefinition(array(
new InputArgument('script_name', InputArgument::OPTIONAL, 'The script name of the application\'s front controller.'),
new InputOption('base-uri', null, InputOption::VALUE_REQUIRED, 'The base URI'),
))
->setDescription('[DEPRECATED] Dumps all routes as Apache rewrite rules')
->setHelp(<<<EOF
The <info>%command.name%</info> dumps all routes as Apache rewrite rules.
These can then be used with the ApacheUrlMatcher to use Apache for route
matching.
<info>php %command.full_name%</info>
EOF
)
;
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
trigger_error('The router:dump-apache command is deprecated since 2.5 and will be removed in 3.0', E_USER_DEPRECATED);
$router = $this->getContainer()->get('router');
$dumpOptions = array();
if ($input->getArgument('script_name')) {
$dumpOptions['script_name'] = $input->getArgument('script_name');
}
if ($input->getOption('base-uri')) {
$dumpOptions['base_uri'] = $input->getOption('base-uri');
}
$dumper = new ApacheMatcherDumper($router->getRouteCollection());
$output->writeln($dumper->dump($dumpOptions), OutputInterface::OUTPUT_RAW);
}
}

View File

@ -1,124 +0,0 @@
<?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 Symfony\Component\Routing\Matcher;
trigger_error('The Symfony\Component\Routing\Matcher\Dumper\ApacheUrlMatcher is deprecated since it\'s hard to replicate the behaviour of the PHP implementation and the performance gains are minimal.', E_USER_DEPRECATED);
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
/**
* ApacheUrlMatcher matches URL based on Apache mod_rewrite matching (see ApacheMatcherDumper).
*
* @deprecated Deprecated since version 2.5, to be removed in 3.0.
* The performance gains are minimal and it's very hard to replicate
* the behavior of PHP implementation.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
*/
class ApacheUrlMatcher extends UrlMatcher
{
/**
* Tries to match a URL based on Apache mod_rewrite matching.
*
* Returns false if no route matches the URL.
*
* @param string $pathinfo The pathinfo to be parsed
*
* @return array An array of parameters
*
* @throws MethodNotAllowedException If the current method is not allowed
*/
public function match($pathinfo)
{
$parameters = array();
$defaults = array();
$allow = array();
$route = null;
foreach ($this->denormalizeValues($_SERVER) as $key => $value) {
$name = $key;
// skip non-routing variables
// this improves performance when $_SERVER contains many usual
// variables like HTTP_*, DOCUMENT_ROOT, REQUEST_URI, ...
if (false === strpos($name, '_ROUTING_')) {
continue;
}
while (0 === strpos($name, 'REDIRECT_')) {
$name = substr($name, 9);
}
// expect _ROUTING_<type>_<name>
// or _ROUTING_<type>
if (0 !== strpos($name, '_ROUTING_')) {
continue;
}
if (false !== $pos = strpos($name, '_', 9)) {
$type = substr($name, 9, $pos-9);
$name = substr($name, $pos+1);
} else {
$type = substr($name, 9);
}
if ('param' === $type) {
if ('' !== $value) {
$parameters[$name] = $value;
}
} elseif ('default' === $type) {
$defaults[$name] = $value;
} elseif ('route' === $type) {
$route = $value;
} elseif ('allow' === $type) {
$allow[] = $name;
}
unset($_SERVER[$key]);
}
if (null !== $route) {
$parameters['_route'] = $route;
return $this->mergeDefaults($parameters, $defaults);
} elseif (0 < count($allow)) {
throw new MethodNotAllowedException($allow);
} else {
return parent::match($pathinfo);
}
}
/**
* Denormalizes an array of values.
*
* @param string[] $values
*
* @return array
*/
private function denormalizeValues(array $values)
{
$normalizedValues = array();
foreach ($values as $key => $value) {
if (preg_match('~^(.*)\[(\d+)\]$~', $key, $matches)) {
if (!isset($normalizedValues[$matches[1]])) {
$normalizedValues[$matches[1]] = array();
}
$normalizedValues[$matches[1]][(int) $matches[2]] = $value;
} else {
$normalizedValues[$key] = $value;
}
}
return $normalizedValues;
}
}

View File

@ -1,283 +0,0 @@
<?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 Symfony\Component\Routing\Matcher\Dumper;
trigger_error('The Symfony\Component\Routing\Matcher\Dumper\ApacheMatcherDumper is deprecated since it\'s hard to replicate the behaviour of the PHP implementation and the performance gains are minimal.', E_USER_DEPRECATED);
use Symfony\Component\Routing\Route;
/**
* Dumps a set of Apache mod_rewrite rules.
*
* @deprecated Deprecated since version 2.5, to be removed in 3.0.
* The performance gains are minimal and it's very hard to replicate
* the behavior of PHP implementation.
*
* @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\" requests\nRewriteCond %{REQUEST_FILENAME} -f\nRewriteRule .* - [QSA,L]");
$methodVars = array();
$hostRegexUnique = 0;
$prevHostRegex = '';
foreach ($this->getRoutes()->all() as $name => $route) {
if ($route->getCondition()) {
throw new \LogicException(sprintf('Unable to dump the routes for Apache as route "%s" has a condition.', $name));
}
$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("\n\n", $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($regex, 1), ' ', '\\');
$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;
}
}

View File

@ -1,152 +0,0 @@
<?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 Symfony\Component\Routing\Tests\Matcher;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Matcher\ApacheUrlMatcher;
class ApacheUrlMatcherTest extends \PHPUnit_Framework_TestCase
{
protected $server;
protected function setUp()
{
$this->server = $_SERVER;
}
protected function tearDown()
{
$_SERVER = $this->server;
}
/**
* @dataProvider getMatchData
*/
public function testMatch($name, $pathinfo, $server, $expect)
{
$collection = new RouteCollection();
$context = new RequestContext();
$matcher = new ApacheUrlMatcher($collection, $context);
$_SERVER = $server;
$result = $matcher->match($pathinfo);
$this->assertSame(var_export($expect, true), var_export($result, true));
}
public function getMatchData()
{
return array(
array(
'Simple route',
'/hello/world',
array(
'_ROUTING_route' => 'hello',
'_ROUTING_param__controller' => 'AcmeBundle:Default:index',
'_ROUTING_param_name' => 'world',
),
array(
'_controller' => 'AcmeBundle:Default:index',
'name' => 'world',
'_route' => 'hello',
),
),
array(
'Route with params and defaults',
'/hello/hugo',
array(
'_ROUTING_route' => 'hello',
'_ROUTING_param__controller' => 'AcmeBundle:Default:index',
'_ROUTING_param_name' => 'hugo',
'_ROUTING_default_name' => 'world',
),
array(
'name' => 'hugo',
'_controller' => 'AcmeBundle:Default:index',
'_route' => 'hello',
),
),
array(
'Route with defaults only',
'/hello',
array(
'_ROUTING_route' => 'hello',
'_ROUTING_param__controller' => 'AcmeBundle:Default:index',
'_ROUTING_default_name' => 'world',
),
array(
'name' => 'world',
'_controller' => 'AcmeBundle:Default:index',
'_route' => 'hello',
),
),
array(
'Redirect with many ignored attributes',
'/legacy/{cat1}/{cat2}/{id}.html',
array(
'_ROUTING_route' => 'product_view',
'_ROUTING_param__controller' => 'FrameworkBundle:Redirect:redirect',
'_ROUTING_default_ignoreAttributes[0]' => 'attr_a',
'_ROUTING_default_ignoreAttributes[1]' => 'attr_b',
),
array(
'ignoreAttributes' => array('attr_a', 'attr_b'),
'_controller' => 'FrameworkBundle:Redirect:redirect',
'_route' => 'product_view',
),
),
array(
'REDIRECT_ envs',
'/hello/world',
array(
'REDIRECT__ROUTING_route' => 'hello',
'REDIRECT__ROUTING_param__controller' => 'AcmeBundle:Default:index',
'REDIRECT__ROUTING_param_name' => 'world',
),
array(
'_controller' => 'AcmeBundle:Default:index',
'name' => 'world',
'_route' => 'hello',
),
),
array(
'REDIRECT_REDIRECT_ envs',
'/hello/world',
array(
'REDIRECT_REDIRECT__ROUTING_route' => 'hello',
'REDIRECT_REDIRECT__ROUTING_param__controller' => 'AcmeBundle:Default:index',
'REDIRECT_REDIRECT__ROUTING_param_name' => 'world',
),
array(
'_controller' => 'AcmeBundle:Default:index',
'name' => 'world',
'_route' => 'hello',
),
),
array(
'REDIRECT_REDIRECT_ envs',
'/hello/world',
array(
'REDIRECT_REDIRECT__ROUTING_route' => 'hello',
'REDIRECT_REDIRECT__ROUTING_param__controller' => 'AcmeBundle:Default:index',
'REDIRECT_REDIRECT__ROUTING_param_name' => 'world',
),
array(
'_controller' => 'AcmeBundle:Default:index',
'name' => 'world',
'_route' => 'hello',
),
),
);
}
}

View File

@ -1,196 +0,0 @@
<?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 Symfony\Component\Routing\Tests\Matcher\Dumper;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Matcher\Dumper\ApacheMatcherDumper;
class ApacheMatcherDumperTest extends \PHPUnit_Framework_TestCase
{
protected static $fixturesPath;
public static function setUpBeforeClass()
{
self::$fixturesPath = realpath(__DIR__.'/../../Fixtures/');
}
public function testDump()
{
$dumper = new ApacheMatcherDumper($this->getRouteCollection());
$this->assertStringEqualsFile(self::$fixturesPath.'/dumper/url_matcher1.apache', $dumper->dump(), '->dump() dumps basic routes to the correct apache format.');
}
/**
* @dataProvider provideEscapeFixtures
*/
public function testEscapePattern($src, $dest, $char, $with, $message)
{
$r = new \ReflectionMethod(new ApacheMatcherDumper($this->getRouteCollection()), 'escape');
$r->setAccessible(true);
$this->assertEquals($dest, $r->invoke(null, $src, $char, $with), $message);
}
public function provideEscapeFixtures()
{
return array(
array('foo', 'foo', ' ', '-', 'Preserve string that should not be escaped'),
array('fo-o', 'fo-o', ' ', '-', 'Preserve string that should not be escaped'),
array('fo o', 'fo- o', ' ', '-', 'Escape special characters'),
array('fo-- o', 'fo--- o', ' ', '-', 'Escape special characters'),
array('fo- o', 'fo- o', ' ', '-', 'Do not escape already escaped string'),
);
}
public function testEscapeScriptName()
{
$collection = new RouteCollection();
$collection->add('foo', new Route('/foo'));
$dumper = new ApacheMatcherDumper($collection);
$this->assertStringEqualsFile(self::$fixturesPath.'/dumper/url_matcher2.apache', $dumper->dump(array('script_name' => 'ap p_d\ ev.php')));
}
private function getRouteCollection()
{
$collection = new RouteCollection();
// defaults and requirements
$collection->add('foo', new Route(
'/foo/{bar}',
array('def' => 'test'),
array('bar' => 'baz|symfony')
));
// defaults parameters in pattern
$collection->add('foobar', new Route(
'/foo/{bar}',
array('bar' => 'toto')
));
// method requirement
$collection->add('bar', new Route(
'/bar/{foo}',
array(),
array('_method' => 'GET|head')
));
// method requirement (again)
$collection->add('baragain', new Route(
'/baragain/{foo}',
array(),
array('_method' => 'get|post')
));
// simple
$collection->add('baz', new Route(
'/test/baz'
));
// simple with extension
$collection->add('baz2', new Route(
'/test/baz.html'
));
// trailing slash
$collection->add('baz3', new Route(
'/test/baz3/'
));
// trailing slash with variable
$collection->add('baz4', new Route(
'/test/{foo}/'
));
// trailing slash and safe method
$collection->add('baz5', new Route(
'/test/{foo}/',
array(),
array('_method' => 'get')
));
// trailing slash and unsafe method
$collection->add('baz5unsafe', new Route(
'/testunsafe/{foo}/',
array(),
array('_method' => 'post')
));
// complex
$collection->add('baz6', new Route(
'/test/baz',
array('foo' => 'bar baz')
));
// space in path
$collection->add('baz7', new Route(
'/te st/baz'
));
// space preceded with \ in path
$collection->add('baz8', new Route(
'/te\\ st/baz'
));
// space preceded with \ in requirement
$collection->add('baz9', new Route(
'/test/{baz}',
array(),
array(
'baz' => 'te\\\\ st',
)
));
$collection1 = new RouteCollection();
$route1 = new Route('/route1', array(), array(), array(), 'a.example.com');
$collection1->add('route1', $route1);
$collection2 = new RouteCollection();
$route2 = new Route('/route2', array(), array(), array(), 'a.example.com');
$collection2->add('route2', $route2);
$route3 = new Route('/route3', array(), array(), array(), 'b.example.com');
$collection2->add('route3', $route3);
$collection2->addPrefix('/c2');
$collection1->addCollection($collection2);
$route4 = new Route('/route4', array(), array(), array(), 'a.example.com');
$collection1->add('route4', $route4);
$route5 = new Route('/route5', array(), array(), array(), 'c.example.com');
$collection1->add('route5', $route5);
$route6 = new Route('/route6', array(), array(), array(), null);
$collection1->add('route6', $route6);
$collection->addCollection($collection1);
// host and variables
$collection1 = new RouteCollection();
$route11 = new Route('/route11', array(), array(), array(), '{var1}.example.com');
$collection1->add('route11', $route11);
$route12 = new Route('/route12', array('var1' => 'val'), array(), array(), '{var1}.example.com');
$collection1->add('route12', $route12);
$route13 = new Route('/route13/{name}', array(), array(), array(), '{var1}.example.com');
$collection1->add('route13', $route13);
$route14 = new Route('/route14/{name}', array('var1' => 'val'), array(), array(), '{var1}.example.com');
$collection1->add('route14', $route14);
$route15 = new Route('/route15/{name}', array(), array(), array(), 'c.example.com');
$collection1->add('route15', $route15);
$route16 = new Route('/route16/{name}', array('var1' => 'val'), array(), array(), null);
$collection1->add('route16', $route16);
$route17 = new Route('/route17', array(), array(), array(), null);
$collection1->add('route17', $route17);
$collection->addCollection($collection1);
return $collection;
}
}