update v 1.0.7.5
This commit is contained in:
@@ -54,22 +54,6 @@ class Route
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated in 2.2, to be removed in 3.0. Use setPath instead.
|
||||
*/
|
||||
public function setPattern($pattern)
|
||||
{
|
||||
$this->path = $pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated in 2.2, to be removed in 3.0. Use getPath instead.
|
||||
*/
|
||||
public function getPattern()
|
||||
{
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
public function setPath($path)
|
||||
{
|
||||
$this->path = $path;
|
@@ -1,6 +1,13 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
2.8.0
|
||||
-----
|
||||
|
||||
* allowed specifying a directory to recursively load all routing configuration files it contains
|
||||
* Added ObjectRouteLoader and ServiceRouteLoader that allow routes to be loaded
|
||||
by calling a method on an object/service.
|
||||
|
||||
2.5.0
|
||||
-----
|
||||
|
@@ -15,8 +15,6 @@ namespace Symfony\Component\Routing\Exception;
|
||||
* ExceptionInterface.
|
||||
*
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
interface ExceptionInterface
|
||||
{
|
@@ -15,8 +15,6 @@ namespace Symfony\Component\Routing\Exception;
|
||||
* Exception thrown when a parameter is not valid.
|
||||
*
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class InvalidParameterException extends \InvalidArgumentException implements ExceptionInterface
|
||||
{
|
@@ -17,8 +17,6 @@ namespace Symfony\Component\Routing\Exception;
|
||||
* This exception should trigger an HTTP 405 response in your application code.
|
||||
*
|
||||
* @author Kris Wallsmith <kris@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class MethodNotAllowedException extends \RuntimeException implements ExceptionInterface
|
||||
{
|
@@ -16,8 +16,6 @@ namespace Symfony\Component\Routing\Exception;
|
||||
* mandatory parameters.
|
||||
*
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class MissingMandatoryParametersException extends \InvalidArgumentException implements ExceptionInterface
|
||||
{
|
@@ -17,8 +17,6 @@ namespace Symfony\Component\Routing\Exception;
|
||||
* This exception should trigger an HTTP 404 response in your application code.
|
||||
*
|
||||
* @author Kris Wallsmith <kris@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class ResourceNotFoundException extends \RuntimeException implements ExceptionInterface
|
||||
{
|
@@ -15,8 +15,6 @@ namespace Symfony\Component\Routing\Exception;
|
||||
* Exception thrown when a route does not exist.
|
||||
*
|
||||
* @author Alexandre Salomé <alexandre.salome@gmail.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class RouteNotFoundException extends \InvalidArgumentException implements ExceptionInterface
|
||||
{
|
@@ -17,8 +17,6 @@ use Symfony\Component\Routing\RouteCollection;
|
||||
* GeneratorDumperInterface is the interface that all generator dumper classes must implement.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
interface GeneratorDumperInterface
|
||||
{
|
@@ -16,8 +16,6 @@ namespace Symfony\Component\Routing\Generator\Dumper;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Tobias Schultze <http://tobion.de>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class PhpGeneratorDumper extends GeneratorDumper
|
||||
{
|
||||
@@ -32,8 +30,6 @@ class PhpGeneratorDumper extends GeneratorDumper
|
||||
* @param array $options An array of options
|
||||
*
|
||||
* @return string A PHP class representing the generator class
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function dump(array $options = array())
|
||||
{
|
||||
@@ -57,7 +53,7 @@ use Psr\Log\LoggerInterface;
|
||||
*/
|
||||
class {$options['class']} extends {$options['base_class']}
|
||||
{
|
||||
private static \$declaredRoutes = {$this->generateDeclaredRoutes()};
|
||||
private static \$declaredRoutes;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -66,6 +62,9 @@ class {$options['class']} extends {$options['base_class']}
|
||||
{
|
||||
\$this->context = \$context;
|
||||
\$this->logger = \$logger;
|
||||
if (null === self::\$declaredRoutes) {
|
||||
self::\$declaredRoutes = {$this->generateDeclaredRoutes()};
|
||||
}
|
||||
}
|
||||
|
||||
{$this->generateGenerateMethod()}
|
||||
@@ -108,16 +107,16 @@ EOF;
|
||||
*/
|
||||
private function generateGenerateMethod()
|
||||
{
|
||||
return <<<EOF
|
||||
public function generate(\$name, \$parameters = array(), \$referenceType = self::ABSOLUTE_PATH)
|
||||
return <<<'EOF'
|
||||
public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH)
|
||||
{
|
||||
if (!isset(self::\$declaredRoutes[\$name])) {
|
||||
throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', \$name));
|
||||
if (!isset(self::$declaredRoutes[$name])) {
|
||||
throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name));
|
||||
}
|
||||
|
||||
list(\$variables, \$defaults, \$requirements, \$tokens, \$hostTokens, \$requiredSchemes) = self::\$declaredRoutes[\$name];
|
||||
list($variables, $defaults, $requirements, $tokens, $hostTokens, $requiredSchemes) = self::$declaredRoutes[$name];
|
||||
|
||||
return \$this->doGenerate(\$variables, \$defaults, \$requirements, \$tokens, \$parameters, \$name, \$referenceType, \$hostTokens, \$requiredSchemes);
|
||||
return $this->doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes);
|
||||
}
|
||||
EOF;
|
||||
}
|
@@ -24,8 +24,6 @@ use Psr\Log\LoggerInterface;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Tobias Schultze <http://tobion.de>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInterface
|
||||
{
|
||||
@@ -83,8 +81,6 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt
|
||||
* @param RouteCollection $routes A RouteCollection instance
|
||||
* @param RequestContext $context The context
|
||||
* @param LoggerInterface|null $logger A logger instance
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null)
|
||||
{
|
||||
@@ -206,23 +202,10 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt
|
||||
$scheme = $this->context->getScheme();
|
||||
|
||||
if ($requiredSchemes) {
|
||||
$schemeMatched = false;
|
||||
foreach ($requiredSchemes as $requiredScheme) {
|
||||
if ($scheme === $requiredScheme) {
|
||||
$schemeMatched = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$schemeMatched) {
|
||||
if (!in_array($scheme, $requiredSchemes, true)) {
|
||||
$referenceType = self::ABSOLUTE_URL;
|
||||
$scheme = current($requiredSchemes);
|
||||
}
|
||||
} elseif (isset($requirements['_scheme']) && ($req = strtolower($requirements['_scheme'])) && $scheme !== $req) {
|
||||
// We do this for BC; to be removed if _scheme is not supported anymore
|
||||
$referenceType = self::ABSOLUTE_URL;
|
||||
$scheme = $req;
|
||||
}
|
||||
|
||||
if ($hostTokens) {
|
||||
@@ -277,7 +260,10 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt
|
||||
}
|
||||
|
||||
// add a query string if needed
|
||||
$extra = array_diff_key($parameters, $variables, $defaults);
|
||||
$extra = array_udiff_assoc(array_diff_key($parameters, $variables), $defaults, function ($a, $b) {
|
||||
return $a == $b ? 0 : 1;
|
||||
});
|
||||
|
||||
if ($extra && $query = http_build_query($extra, '', '&')) {
|
||||
// "/" and "?" can be left decoded for better user experience, see
|
||||
// http://tools.ietf.org/html/rfc3986#section-3.4
|
@@ -28,33 +28,31 @@ use Symfony\Component\Routing\RequestContextAwareInterface;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Tobias Schultze <http://tobion.de>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
interface UrlGeneratorInterface extends RequestContextAwareInterface
|
||||
{
|
||||
/**
|
||||
* Generates an absolute URL, e.g. "http://example.com/dir/file".
|
||||
*/
|
||||
const ABSOLUTE_URL = true;
|
||||
const ABSOLUTE_URL = 0;
|
||||
|
||||
/**
|
||||
* Generates an absolute path, e.g. "/dir/file".
|
||||
*/
|
||||
const ABSOLUTE_PATH = false;
|
||||
const ABSOLUTE_PATH = 1;
|
||||
|
||||
/**
|
||||
* Generates a relative path based on the current request path, e.g. "../parent-file".
|
||||
*
|
||||
* @see UrlGenerator::getRelativePath()
|
||||
*/
|
||||
const RELATIVE_PATH = 'relative';
|
||||
const RELATIVE_PATH = 2;
|
||||
|
||||
/**
|
||||
* Generates a network path, e.g. "//example.com/dir/file".
|
||||
* Such reference reuses the current scheme but specifies the host.
|
||||
*/
|
||||
const NETWORK_PATH = 'network';
|
||||
const NETWORK_PATH = 3;
|
||||
|
||||
/**
|
||||
* Generates a URL or path for a specific route based on the given parameters.
|
||||
@@ -71,9 +69,9 @@ interface UrlGeneratorInterface extends RequestContextAwareInterface
|
||||
*
|
||||
* If there is no route with the given name, the generator must throw the RouteNotFoundException.
|
||||
*
|
||||
* @param string $name The name of the route
|
||||
* @param mixed $parameters An array of parameters
|
||||
* @param bool|string $referenceType The type of reference to be generated (one of the constants)
|
||||
* @param string $name The name of the route
|
||||
* @param mixed $parameters An array of parameters
|
||||
* @param int $referenceType The type of reference to be generated (one of the constants)
|
||||
*
|
||||
* @return string The generated URL
|
||||
*
|
||||
@@ -81,8 +79,6 @@ interface UrlGeneratorInterface extends RequestContextAwareInterface
|
||||
* @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route
|
||||
* @throws InvalidParameterException When a parameter value for a placeholder is not correct because
|
||||
* it does not match the requirement
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH);
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2004-2015 Fabien Potencier
|
||||
Copyright (c) 2004-2016 Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
@@ -110,7 +110,7 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
||||
|
||||
$class = new \ReflectionClass($class);
|
||||
if ($class->isAbstract()) {
|
||||
throw new \InvalidArgumentException(sprintf('Annotations from class "%s" cannot be read as it is abstract.', $class));
|
||||
throw new \InvalidArgumentException(sprintf('Annotations from class "%s" cannot be read as it is abstract.', $class->getName()));
|
||||
}
|
||||
|
||||
$globals = $this->getGlobals($class);
|
||||
@@ -139,14 +139,14 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
||||
|
||||
$defaults = array_replace($globals['defaults'], $annot->getDefaults());
|
||||
foreach ($method->getParameters() as $param) {
|
||||
if (!isset($defaults[$param->getName()]) && $param->isOptional()) {
|
||||
if (!isset($defaults[$param->getName()]) && $param->isDefaultValueAvailable()) {
|
||||
$defaults[$param->getName()] = $param->getDefaultValue();
|
||||
}
|
||||
}
|
||||
$requirements = array_replace($globals['requirements'], $annot->getRequirements());
|
||||
$options = array_replace($globals['options'], $annot->getOptions());
|
||||
$schemes = array_replace($globals['schemes'], $annot->getSchemes());
|
||||
$methods = array_replace($globals['methods'], $annot->getMethods());
|
||||
$schemes = array_merge($globals['schemes'], $annot->getSchemes());
|
||||
$methods = array_merge($globals['methods'], $annot->getMethods());
|
||||
|
||||
$host = $annot->getHost();
|
||||
if (null === $host) {
|
||||
@@ -220,11 +220,8 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
||||
);
|
||||
|
||||
if ($annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) {
|
||||
// for BC reasons
|
||||
if (null !== $annot->getPath()) {
|
||||
$globals['path'] = $annot->getPath();
|
||||
} elseif (null !== $annot->getPattern()) {
|
||||
$globals['path'] = $annot->getPattern();
|
||||
}
|
||||
|
||||
if (null !== $annot->getRequirements()) {
|
@@ -66,12 +66,16 @@ class AnnotationDirectoryLoader extends AnnotationFileLoader
|
||||
*/
|
||||
public function supports($resource, $type = null)
|
||||
{
|
||||
if (!is_string($resource)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$path = $this->locator->locate($resource);
|
||||
} catch (\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return is_string($resource) && is_dir($path) && (!$type || 'annotation' === $type);
|
||||
return is_dir($path) && (!$type || 'annotation' === $type);
|
||||
}
|
||||
}
|
@@ -64,6 +64,10 @@ class AnnotationFileLoader extends FileLoader
|
||||
$collection->addResource(new FileResource($path));
|
||||
$collection->addCollection($this->loader->load($class, $type));
|
||||
}
|
||||
if (PHP_VERSION_ID >= 70000) {
|
||||
// PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098
|
||||
gc_mem_caches();
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
@@ -88,10 +92,10 @@ class AnnotationFileLoader extends FileLoader
|
||||
$class = false;
|
||||
$namespace = false;
|
||||
$tokens = token_get_all(file_get_contents($file));
|
||||
for ($i = 0, $count = count($tokens); $i < $count; ++$i) {
|
||||
for ($i = 0; isset($tokens[$i]); ++$i) {
|
||||
$token = $tokens[$i];
|
||||
|
||||
if (!is_array($token)) {
|
||||
if (!isset($token[1])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -100,15 +104,32 @@ class AnnotationFileLoader extends FileLoader
|
||||
}
|
||||
|
||||
if (true === $namespace && T_STRING === $token[0]) {
|
||||
$namespace = '';
|
||||
do {
|
||||
$namespace .= $token[1];
|
||||
$token = $tokens[++$i];
|
||||
} while ($i < $count && is_array($token) && in_array($token[0], array(T_NS_SEPARATOR, T_STRING)));
|
||||
$namespace = $token[1];
|
||||
while (isset($tokens[++$i][1]) && in_array($tokens[$i][0], array(T_NS_SEPARATOR, T_STRING))) {
|
||||
$namespace .= $tokens[$i][1];
|
||||
}
|
||||
$token = $tokens[$i];
|
||||
}
|
||||
|
||||
if (T_CLASS === $token[0]) {
|
||||
$class = true;
|
||||
// Skip usage of ::class constant
|
||||
$isClassConstant = false;
|
||||
for ($j = $i - 1; $j > 0; --$j) {
|
||||
if (!isset($tokens[$j][1])) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (T_DOUBLE_COLON === $tokens[$j][0]) {
|
||||
$isClassConstant = true;
|
||||
break;
|
||||
} elseif (!in_array($tokens[$j][0], array(T_WHITESPACE, T_DOC_COMMENT, T_COMMENT))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isClassConstant) {
|
||||
$class = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (T_NAMESPACE === $token[0]) {
|
@@ -20,8 +20,6 @@ use Symfony\Component\Routing\RouteCollection;
|
||||
* The Closure must return a RouteCollection instance.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class ClosureLoader extends Loader
|
||||
{
|
||||
@@ -32,8 +30,6 @@ class ClosureLoader extends Loader
|
||||
* @param string|null $type The resource type
|
||||
*
|
||||
* @return RouteCollection A RouteCollection instance
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function load($closure, $type = null)
|
||||
{
|
||||
@@ -42,8 +38,6 @@ class ClosureLoader extends Loader
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function supports($resource, $type = null)
|
||||
{
|
40
vendor/symfony/routing/Loader/DependencyInjection/ServiceRouterLoader.php
vendored
Normal file
40
vendor/symfony/routing/Loader/DependencyInjection/ServiceRouterLoader.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?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\Loader\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\Routing\Loader\ObjectRouteLoader;
|
||||
|
||||
/**
|
||||
* A route loader that executes a service to load the routes.
|
||||
*
|
||||
* This depends on the DependencyInjection component.
|
||||
*
|
||||
* @author Ryan Weaver <ryan@knpuniversity.com>
|
||||
*/
|
||||
class ServiceRouterLoader extends ObjectRouteLoader
|
||||
{
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
protected function getServiceObject($id)
|
||||
{
|
||||
return $this->container->get($id);
|
||||
}
|
||||
}
|
58
vendor/symfony/routing/Loader/DirectoryLoader.php
vendored
Normal file
58
vendor/symfony/routing/Loader/DirectoryLoader.php
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
<?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\Loader;
|
||||
|
||||
use Symfony\Component\Config\Loader\FileLoader;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
use Symfony\Component\Config\Resource\DirectoryResource;
|
||||
|
||||
class DirectoryLoader extends FileLoader
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function load($file, $type = null)
|
||||
{
|
||||
$path = $this->locator->locate($file);
|
||||
|
||||
$collection = new RouteCollection();
|
||||
$collection->addResource(new DirectoryResource($path));
|
||||
|
||||
foreach (scandir($path) as $dir) {
|
||||
if ('.' !== $dir[0]) {
|
||||
$this->setCurrentDir($path);
|
||||
$subPath = $path.'/'.$dir;
|
||||
$subType = null;
|
||||
|
||||
if (is_dir($subPath)) {
|
||||
$subPath .= '/';
|
||||
$subType = 'directory';
|
||||
}
|
||||
|
||||
$subCollection = $this->import($subPath, $subType, false, $path);
|
||||
$collection->addCollection($subCollection);
|
||||
}
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports($resource, $type = null)
|
||||
{
|
||||
// only when type is forced to directory, not to conflict with AnnotationLoader
|
||||
|
||||
return 'directory' === $type;
|
||||
}
|
||||
}
|
95
vendor/symfony/routing/Loader/ObjectRouteLoader.php
vendored
Normal file
95
vendor/symfony/routing/Loader/ObjectRouteLoader.php
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
<?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\Loader;
|
||||
|
||||
use Symfony\Component\Config\Loader\Loader;
|
||||
use Symfony\Component\Config\Resource\FileResource;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
/**
|
||||
* A route loader that calls a method on an object to load the routes.
|
||||
*
|
||||
* @author Ryan Weaver <ryan@knpuniversity.com>
|
||||
*/
|
||||
abstract class ObjectRouteLoader extends Loader
|
||||
{
|
||||
/**
|
||||
* Returns the object that the method will be called on to load routes.
|
||||
*
|
||||
* For example, if your application uses a service container,
|
||||
* the $id may be a service id.
|
||||
*
|
||||
* @param string $id
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
abstract protected function getServiceObject($id);
|
||||
|
||||
/**
|
||||
* Calls the service that will load the routes.
|
||||
*
|
||||
* @param mixed $resource Some value that will resolve to a callable
|
||||
* @param string|null $type The resource type
|
||||
*
|
||||
* @return RouteCollection
|
||||
*/
|
||||
public function load($resource, $type = null)
|
||||
{
|
||||
$parts = explode(':', $resource);
|
||||
if (count($parts) != 2) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid resource "%s" passed to the "service" route loader: use the format "service_name:methodName"', $resource));
|
||||
}
|
||||
|
||||
$serviceString = $parts[0];
|
||||
$method = $parts[1];
|
||||
|
||||
$loaderObject = $this->getServiceObject($serviceString);
|
||||
|
||||
if (!is_object($loaderObject)) {
|
||||
throw new \LogicException(sprintf('%s:getServiceObject() must return an object: %s returned', get_class($this), gettype($loaderObject)));
|
||||
}
|
||||
|
||||
if (!method_exists($loaderObject, $method)) {
|
||||
throw new \BadMethodCallException(sprintf('Method "%s" not found on "%s" when importing routing resource "%s"', $method, get_class($loaderObject), $resource));
|
||||
}
|
||||
|
||||
$routeCollection = call_user_func(array($loaderObject, $method), $this);
|
||||
|
||||
if (!$routeCollection instanceof RouteCollection) {
|
||||
$type = is_object($routeCollection) ? get_class($routeCollection) : gettype($routeCollection);
|
||||
|
||||
throw new \LogicException(sprintf('The %s::%s method must return a RouteCollection: %s returned', get_class($loaderObject), $method, $type));
|
||||
}
|
||||
|
||||
// make the service file tracked so that if it changes, the cache rebuilds
|
||||
$this->addClassResource(new \ReflectionClass($loaderObject), $routeCollection);
|
||||
|
||||
return $routeCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function supports($resource, $type = null)
|
||||
{
|
||||
return 'service' === $type;
|
||||
}
|
||||
|
||||
private function addClassResource(\ReflectionClass $class, RouteCollection $collection)
|
||||
{
|
||||
do {
|
||||
if (is_file($class->getFileName())) {
|
||||
$collection->addResource(new FileResource($class->getFileName()));
|
||||
}
|
||||
} while ($class = $class->getParentClass());
|
||||
}
|
||||
}
|
@@ -21,8 +21,6 @@ use Symfony\Component\Routing\RouteCollection;
|
||||
* The file must return a RouteCollection instance.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class PhpFileLoader extends FileLoader
|
||||
{
|
||||
@@ -33,8 +31,6 @@ class PhpFileLoader extends FileLoader
|
||||
* @param string|null $type The resource type
|
||||
*
|
||||
* @return RouteCollection A RouteCollection instance
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function load($file, $type = null)
|
||||
{
|
||||
@@ -49,8 +45,6 @@ class PhpFileLoader extends FileLoader
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function supports($resource, $type = null)
|
||||
{
|
@@ -22,8 +22,6 @@ use Symfony\Component\Config\Util\XmlUtils;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Tobias Schultze <http://tobion.de>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class XmlFileLoader extends FileLoader
|
||||
{
|
||||
@@ -40,8 +38,6 @@ class XmlFileLoader extends FileLoader
|
||||
*
|
||||
* @throws \InvalidArgumentException When the file cannot be loaded or when the XML cannot be
|
||||
* parsed because it does not validate against the scheme.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function load($file, $type = null)
|
||||
{
|
||||
@@ -94,8 +90,6 @@ class XmlFileLoader extends FileLoader
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function supports($resource, $type = null)
|
||||
{
|
||||
@@ -113,19 +107,10 @@ class XmlFileLoader extends FileLoader
|
||||
*/
|
||||
protected function parseRoute(RouteCollection $collection, \DOMElement $node, $path)
|
||||
{
|
||||
if ('' === ($id = $node->getAttribute('id')) || (!$node->hasAttribute('pattern') && !$node->hasAttribute('path'))) {
|
||||
if ('' === ($id = $node->getAttribute('id')) || !$node->hasAttribute('path')) {
|
||||
throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have an "id" and a "path" attribute.', $path));
|
||||
}
|
||||
|
||||
if ($node->hasAttribute('pattern')) {
|
||||
if ($node->hasAttribute('path')) {
|
||||
throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" cannot define both a "path" and a "pattern" attribute. Use only "path".', $path));
|
||||
}
|
||||
|
||||
$node->setAttribute('path', $node->getAttribute('pattern'));
|
||||
$node->removeAttribute('pattern');
|
||||
}
|
||||
|
||||
$schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY);
|
||||
$methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY);
|
||||
|
@@ -14,6 +14,7 @@ namespace Symfony\Component\Routing\Loader;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Config\Resource\FileResource;
|
||||
use Symfony\Component\Yaml\Exception\ParseException;
|
||||
use Symfony\Component\Yaml\Parser as YamlParser;
|
||||
use Symfony\Component\Config\Loader\FileLoader;
|
||||
|
||||
@@ -22,13 +23,11 @@ use Symfony\Component\Config\Loader\FileLoader;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Tobias Schultze <http://tobion.de>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class YamlFileLoader extends FileLoader
|
||||
{
|
||||
private static $availableKeys = array(
|
||||
'resource', 'type', 'prefix', 'pattern', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition',
|
||||
'resource', 'type', 'prefix', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition',
|
||||
);
|
||||
private $yamlParser;
|
||||
|
||||
@@ -41,8 +40,6 @@ class YamlFileLoader extends FileLoader
|
||||
* @return RouteCollection A RouteCollection instance
|
||||
*
|
||||
* @throws \InvalidArgumentException When a route can't be parsed because YAML is invalid
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function load($file, $type = null)
|
||||
{
|
||||
@@ -60,31 +57,26 @@ class YamlFileLoader extends FileLoader
|
||||
$this->yamlParser = new YamlParser();
|
||||
}
|
||||
|
||||
$config = $this->yamlParser->parse(file_get_contents($path));
|
||||
try {
|
||||
$parsedConfig = $this->yamlParser->parse(file_get_contents($path));
|
||||
} catch (ParseException $e) {
|
||||
throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e);
|
||||
}
|
||||
|
||||
$collection = new RouteCollection();
|
||||
$collection->addResource(new FileResource($path));
|
||||
|
||||
// empty file
|
||||
if (null === $config) {
|
||||
if (null === $parsedConfig) {
|
||||
return $collection;
|
||||
}
|
||||
|
||||
// not an array
|
||||
if (!is_array($config)) {
|
||||
if (!is_array($parsedConfig)) {
|
||||
throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $path));
|
||||
}
|
||||
|
||||
foreach ($config as $name => $config) {
|
||||
if (isset($config['pattern'])) {
|
||||
if (isset($config['path'])) {
|
||||
throw new \InvalidArgumentException(sprintf('The file "%s" cannot define both a "path" and a "pattern" attribute. Use only "path".', $path));
|
||||
}
|
||||
|
||||
$config['path'] = $config['pattern'];
|
||||
unset($config['pattern']);
|
||||
}
|
||||
|
||||
foreach ($parsedConfig as $name => $config) {
|
||||
$this->validate($config, $name, $path);
|
||||
|
||||
if (isset($config['resource'])) {
|
||||
@@ -99,8 +91,6 @@ class YamlFileLoader extends FileLoader
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function supports($resource, $type = null)
|
||||
{
|
@@ -37,8 +37,7 @@
|
||||
<xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" />
|
||||
|
||||
<xsd:attribute name="id" type="xsd:string" use="required" />
|
||||
<xsd:attribute name="path" type="xsd:string" />
|
||||
<xsd:attribute name="pattern" type="xsd:string" />
|
||||
<xsd:attribute name="path" type="xsd:string" use="required" />
|
||||
<xsd:attribute name="host" type="xsd:string" />
|
||||
<xsd:attribute name="schemes" type="xsd:string" />
|
||||
<xsd:attribute name="methods" type="xsd:string" />
|
@@ -15,6 +15,8 @@ namespace Symfony\Component\Routing\Matcher\Dumper;
|
||||
* Collection of routes.
|
||||
*
|
||||
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class DumperCollection implements \IteratorAggregate
|
||||
{
|
@@ -15,6 +15,8 @@ namespace Symfony\Component\Routing\Matcher\Dumper;
|
||||
* Prefix tree of routes preserving routes order.
|
||||
*
|
||||
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class DumperPrefixCollection extends DumperCollection
|
||||
{
|
@@ -17,6 +17,8 @@ use Symfony\Component\Routing\Route;
|
||||
* Container for a Route.
|
||||
*
|
||||
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class DumperRoute
|
||||
{
|
@@ -215,14 +215,11 @@ EOF;
|
||||
$hasTrailingSlash = false;
|
||||
$matches = false;
|
||||
$hostMatches = false;
|
||||
$methods = array();
|
||||
$methods = $route->getMethods();
|
||||
|
||||
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';
|
||||
}
|
||||
// GET and HEAD are equivalent
|
||||
if (in_array('GET', $methods) && !in_array('HEAD', $methods)) {
|
||||
$methods[] = 'HEAD';
|
||||
}
|
||||
|
||||
$supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods));
|
@@ -16,8 +16,6 @@ use Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
abstract class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface
|
||||
{
|
@@ -15,8 +15,6 @@ namespace Symfony\Component\Routing\Matcher;
|
||||
* RedirectableUrlMatcherInterface knows how to redirect the user.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
interface RedirectableUrlMatcherInterface
|
||||
{
|
||||
@@ -28,8 +26,6 @@ interface RedirectableUrlMatcherInterface
|
||||
* @param string|null $scheme The URL scheme (null to keep the current one)
|
||||
*
|
||||
* @return array An array of parameters
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function redirect($path, $route, $scheme = null);
|
||||
}
|
@@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\Routing\Matcher;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Exception\ExceptionInterface;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
@@ -40,6 +41,15 @@ class TraceableUrlMatcher extends UrlMatcher
|
||||
return $this->traces;
|
||||
}
|
||||
|
||||
public function getTracesForRequest(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
$traces = $this->getTraces($request->getPathInfo());
|
||||
$this->request = null;
|
||||
|
||||
return $traces;
|
||||
}
|
||||
|
||||
protected function matchCollection($pathinfo, RouteCollection $routes)
|
||||
{
|
||||
foreach ($routes as $name => $route) {
|
||||
@@ -78,16 +88,16 @@ class TraceableUrlMatcher extends UrlMatcher
|
||||
}
|
||||
|
||||
// check HTTP method requirement
|
||||
if ($req = $route->getRequirement('_method')) {
|
||||
if ($requiredMethods = $route->getMethods()) {
|
||||
// HEAD and GET are equivalent as per RFC
|
||||
if ('HEAD' === $method = $this->context->getMethod()) {
|
||||
$method = 'GET';
|
||||
}
|
||||
|
||||
if (!in_array($method, $req = explode('|', strtoupper($req)))) {
|
||||
$this->allow = array_merge($this->allow, $req);
|
||||
if (!in_array($method, $requiredMethods)) {
|
||||
$this->allow = array_merge($this->allow, $requiredMethods);
|
||||
|
||||
$this->addTrace(sprintf('Method "%s" does not match the requirement ("%s")', $this->context->getMethod(), implode(', ', $req)), self::ROUTE_ALMOST_MATCHES, $name, $route);
|
||||
$this->addTrace(sprintf('Method "%s" does not match any of the required methods (%s)', $this->context->getMethod(), implode(', ', $requiredMethods)), self::ROUTE_ALMOST_MATCHES, $name, $route);
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -107,7 +117,7 @@ class TraceableUrlMatcher extends UrlMatcher
|
||||
$scheme = $this->context->getScheme();
|
||||
|
||||
if (!$route->hasScheme($scheme)) {
|
||||
$this->addTrace(sprintf('Scheme "%s" does not match any of the required schemes ("%s"); the user will be redirected to first required scheme', $scheme, implode(', ', $requiredSchemes)), self::ROUTE_ALMOST_MATCHES, $name, $route);
|
||||
$this->addTrace(sprintf('Scheme "%s" does not match any of the required schemes (%s); the user will be redirected to first required scheme', $scheme, implode(', ', $requiredSchemes)), self::ROUTE_ALMOST_MATCHES, $name, $route);
|
||||
|
||||
return true;
|
||||
}
|
@@ -24,8 +24,6 @@ use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
|
||||
* UrlMatcher matches URL based on a set of routes.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
||||
{
|
||||
@@ -61,8 +59,6 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
||||
*
|
||||
* @param RouteCollection $routes A RouteCollection instance
|
||||
* @param RequestContext $context The context
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct(RouteCollection $routes, RequestContext $context)
|
||||
{
|
||||
@@ -98,7 +94,7 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
||||
}
|
||||
|
||||
throw 0 < count($this->allow)
|
||||
? new MethodNotAllowedException(array_unique(array_map('strtoupper', $this->allow)))
|
||||
? new MethodNotAllowedException(array_unique($this->allow))
|
||||
: new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo));
|
||||
}
|
||||
|
||||
@@ -152,14 +148,14 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
||||
}
|
||||
|
||||
// check HTTP method requirement
|
||||
if ($req = $route->getRequirement('_method')) {
|
||||
if ($requiredMethods = $route->getMethods()) {
|
||||
// HEAD and GET are equivalent as per RFC
|
||||
if ('HEAD' === $method = $this->context->getMethod()) {
|
||||
$method = 'GET';
|
||||
}
|
||||
|
||||
if (!in_array($method, $req = explode('|', strtoupper($req)))) {
|
||||
$this->allow = array_merge($this->allow, $req);
|
||||
if (!in_array($method, $requiredMethods)) {
|
||||
$this->allow = array_merge($this->allow, $requiredMethods);
|
||||
|
||||
continue;
|
||||
}
|
@@ -19,8 +19,6 @@ use Symfony\Component\Routing\Exception\MethodNotAllowedException;
|
||||
* UrlMatcherInterface is the interface that all URL matcher classes must implement.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
interface UrlMatcherInterface extends RequestContextAwareInterface
|
||||
{
|
||||
@@ -36,8 +34,6 @@ interface UrlMatcherInterface extends RequestContextAwareInterface
|
||||
*
|
||||
* @throws ResourceNotFoundException If the resource could not be found
|
||||
* @throws MethodNotAllowedException If the resource was found but the request method is not allowed
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function match($pathinfo);
|
||||
}
|
13
vendor/symfony/routing/README.md
vendored
Normal file
13
vendor/symfony/routing/README.md
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
Routing Component
|
||||
=================
|
||||
|
||||
The Routing component maps an HTTP request to a set of configuration variables.
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
* [Documentation](https://symfony.com/doc/current/components/routing/index.html)
|
||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||
in the [main Symfony repository](https://github.com/symfony/symfony)
|
@@ -20,8 +20,6 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Tobias Schultze <http://tobion.de>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class RequestContext
|
||||
{
|
||||
@@ -50,8 +48,6 @@ class RequestContext
|
||||
* @param int $httpsPort The HTTPS port
|
||||
* @param string $path The path
|
||||
* @param string $queryString The query string
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct($baseUrl = '', $method = 'GET', $host = 'localhost', $scheme = 'http', $httpPort = 80, $httpsPort = 443, $path = '/', $queryString = '')
|
||||
{
|
||||
@@ -102,8 +98,6 @@ class RequestContext
|
||||
* @param string $baseUrl The base URL
|
||||
*
|
||||
* @return RequestContext The current instance, implementing a fluent interface
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setBaseUrl($baseUrl)
|
||||
{
|
||||
@@ -154,8 +148,6 @@ class RequestContext
|
||||
* @param string $method The HTTP method
|
||||
*
|
||||
* @return RequestContext The current instance, implementing a fluent interface
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setMethod($method)
|
||||
{
|
||||
@@ -182,8 +174,6 @@ class RequestContext
|
||||
* @param string $host The HTTP host
|
||||
*
|
||||
* @return RequestContext The current instance, implementing a fluent interface
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setHost($host)
|
||||
{
|
||||
@@ -208,8 +198,6 @@ class RequestContext
|
||||
* @param string $scheme The HTTP scheme
|
||||
*
|
||||
* @return RequestContext The current instance, implementing a fluent interface
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setScheme($scheme)
|
||||
{
|
||||
@@ -234,8 +222,6 @@ class RequestContext
|
||||
* @param int $httpPort The HTTP port
|
||||
*
|
||||
* @return RequestContext The current instance, implementing a fluent interface
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setHttpPort($httpPort)
|
||||
{
|
||||
@@ -260,8 +246,6 @@ class RequestContext
|
||||
* @param int $httpsPort The HTTPS port
|
||||
*
|
||||
* @return RequestContext The current instance, implementing a fluent interface
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setHttpsPort($httpsPort)
|
||||
{
|
||||
@@ -286,8 +270,6 @@ class RequestContext
|
||||
* @param string $queryString The query string (after "?")
|
||||
*
|
||||
* @return RequestContext The current instance, implementing a fluent interface
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setQueryString($queryString)
|
||||
{
|
||||
@@ -352,8 +334,6 @@ class RequestContext
|
||||
* @param mixed $parameter The parameter value
|
||||
*
|
||||
* @return RequestContext The current instance, implementing a fluent interface
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setParameter($name, $parameter)
|
||||
{
|
@@ -11,17 +11,12 @@
|
||||
|
||||
namespace Symfony\Component\Routing;
|
||||
|
||||
/**
|
||||
* @api
|
||||
*/
|
||||
interface RequestContextAwareInterface
|
||||
{
|
||||
/**
|
||||
* Sets the request context.
|
||||
*
|
||||
* @param RequestContext $context The context
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setContext(RequestContext $context);
|
||||
|
||||
@@ -29,8 +24,6 @@ interface RequestContextAwareInterface
|
||||
* Gets the request context.
|
||||
*
|
||||
* @return RequestContext The context
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function getContext();
|
||||
}
|
@@ -16,8 +16,6 @@ namespace Symfony\Component\Routing;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Tobias Schultze <http://tobion.de>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class Route implements \Serializable
|
||||
{
|
||||
@@ -81,8 +79,6 @@ class Route implements \Serializable
|
||||
* @param string|array $schemes A required URI scheme or an array of restricted schemes
|
||||
* @param string|array $methods A required HTTP method or an array of restricted methods
|
||||
* @param string $condition A condition that should evaluate to true for the route to match
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function __construct($path, array $defaults = array(), array $requirements = array(), array $options = array(), $host = '', $schemes = array(), $methods = array(), $condition = '')
|
||||
{
|
||||
@@ -91,14 +87,8 @@ class Route implements \Serializable
|
||||
$this->setRequirements($requirements);
|
||||
$this->setOptions($options);
|
||||
$this->setHost($host);
|
||||
// The conditions make sure that an initial empty $schemes/$methods does not override the corresponding requirement.
|
||||
// They can be removed when the BC layer is removed.
|
||||
if ($schemes) {
|
||||
$this->setSchemes($schemes);
|
||||
}
|
||||
if ($methods) {
|
||||
$this->setMethods($methods);
|
||||
}
|
||||
$this->setSchemes($schemes);
|
||||
$this->setMethods($methods);
|
||||
$this->setCondition($condition);
|
||||
}
|
||||
|
||||
@@ -142,34 +132,6 @@ class Route implements \Serializable
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pattern for the path.
|
||||
*
|
||||
* @return string The pattern
|
||||
*
|
||||
* @deprecated Deprecated in 2.2, to be removed in 3.0. Use getPath instead.
|
||||
*/
|
||||
public function getPattern()
|
||||
{
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the pattern for the path.
|
||||
*
|
||||
* This method implements a fluent interface.
|
||||
*
|
||||
* @param string $pattern The path pattern
|
||||
*
|
||||
* @return Route The current Route instance
|
||||
*
|
||||
* @deprecated Deprecated in 2.2, to be removed in 3.0. Use setPath instead.
|
||||
*/
|
||||
public function setPattern($pattern)
|
||||
{
|
||||
return $this->setPath($pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pattern for the path.
|
||||
*
|
||||
@@ -250,14 +212,6 @@ class Route implements \Serializable
|
||||
public function setSchemes($schemes)
|
||||
{
|
||||
$this->schemes = array_map('strtolower', (array) $schemes);
|
||||
|
||||
// this is to keep BC and will be removed in a future version
|
||||
if ($this->schemes) {
|
||||
$this->requirements['_scheme'] = implode('|', $this->schemes);
|
||||
} else {
|
||||
unset($this->requirements['_scheme']);
|
||||
}
|
||||
|
||||
$this->compiled = null;
|
||||
|
||||
return $this;
|
||||
@@ -299,14 +253,6 @@ class Route implements \Serializable
|
||||
public function setMethods($methods)
|
||||
{
|
||||
$this->methods = array_map('strtoupper', (array) $methods);
|
||||
|
||||
// this is to keep BC and will be removed in a future version
|
||||
if ($this->methods) {
|
||||
$this->requirements['_method'] = implode('|', $this->methods);
|
||||
} else {
|
||||
unset($this->requirements['_method']);
|
||||
}
|
||||
|
||||
$this->compiled = null;
|
||||
|
||||
return $this;
|
||||
@@ -368,8 +314,6 @@ class Route implements \Serializable
|
||||
* @param mixed $value The option value
|
||||
*
|
||||
* @return Route The current Route instance
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setOption($name, $value)
|
||||
{
|
||||
@@ -479,8 +423,6 @@ class Route implements \Serializable
|
||||
* @param mixed $default The default value
|
||||
*
|
||||
* @return Route The current Route instance
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setDefault($name, $default)
|
||||
{
|
||||
@@ -566,8 +508,6 @@ class Route implements \Serializable
|
||||
* @param string $regex The regex
|
||||
*
|
||||
* @return Route The current Route instance
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function setRequirement($key, $regex)
|
||||
{
|
||||
@@ -643,13 +583,6 @@ class Route implements \Serializable
|
||||
throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" cannot be empty.', $key));
|
||||
}
|
||||
|
||||
// this is to keep BC and will be removed in a future version
|
||||
if ('_scheme' === $key) {
|
||||
$this->setSchemes(explode('|', $regex));
|
||||
} elseif ('_method' === $key) {
|
||||
$this->setMethods(explode('|', $regex));
|
||||
}
|
||||
|
||||
return $regex;
|
||||
}
|
||||
}
|
@@ -22,8 +22,6 @@ use Symfony\Component\Config\Resource\ResourceInterface;
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Tobias Schultze <http://tobion.de>
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class RouteCollection implements \IteratorAggregate, \Countable
|
||||
{
|
||||
@@ -73,8 +71,6 @@ class RouteCollection implements \IteratorAggregate, \Countable
|
||||
*
|
||||
* @param string $name The route name
|
||||
* @param Route $route A Route instance
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function add($name, Route $route)
|
||||
{
|
||||
@@ -122,8 +118,6 @@ class RouteCollection implements \IteratorAggregate, \Countable
|
||||
* routes of the added collection.
|
||||
*
|
||||
* @param RouteCollection $collection A RouteCollection instance
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function addCollection(RouteCollection $collection)
|
||||
{
|
||||
@@ -143,8 +137,6 @@ class RouteCollection implements \IteratorAggregate, \Countable
|
||||
* @param string $prefix An optional prefix to add before each pattern of the route collection
|
||||
* @param array $defaults An array of default values
|
||||
* @param array $requirements An array of requirements
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
public function addPrefix($prefix, array $defaults = array(), array $requirements = array())
|
||||
{
|
372
vendor/symfony/routing/RouteCollectionBuilder.php
vendored
Normal file
372
vendor/symfony/routing/RouteCollectionBuilder.php
vendored
Normal file
@@ -0,0 +1,372 @@
|
||||
<?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;
|
||||
|
||||
use Symfony\Component\Config\Exception\FileLoaderLoadException;
|
||||
use Symfony\Component\Config\Loader\LoaderInterface;
|
||||
use Symfony\Component\Config\Resource\ResourceInterface;
|
||||
|
||||
/**
|
||||
* Helps add and import routes into a RouteCollection.
|
||||
*
|
||||
* @author Ryan Weaver <ryan@knpuniversity.com>
|
||||
*/
|
||||
class RouteCollectionBuilder
|
||||
{
|
||||
/**
|
||||
* @var Route[]|RouteCollectionBuilder[]
|
||||
*/
|
||||
private $routes = array();
|
||||
|
||||
private $loader;
|
||||
private $defaults = array();
|
||||
private $prefix;
|
||||
private $host;
|
||||
private $condition;
|
||||
private $requirements = array();
|
||||
private $options = array();
|
||||
private $schemes;
|
||||
private $methods;
|
||||
private $resources = array();
|
||||
|
||||
/**
|
||||
* @param LoaderInterface $loader
|
||||
*/
|
||||
public function __construct(LoaderInterface $loader = null)
|
||||
{
|
||||
$this->loader = $loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import an external routing resource and returns the RouteCollectionBuilder.
|
||||
*
|
||||
* $routes->import('blog.yml', '/blog');
|
||||
*
|
||||
* @param mixed $resource
|
||||
* @param string|null $prefix
|
||||
* @param string $type
|
||||
*
|
||||
* @return RouteCollectionBuilder
|
||||
*
|
||||
* @throws FileLoaderLoadException
|
||||
*/
|
||||
public function import($resource, $prefix = '/', $type = null)
|
||||
{
|
||||
/** @var RouteCollection $collection */
|
||||
$collection = $this->load($resource, $type);
|
||||
|
||||
// create a builder from the RouteCollection
|
||||
$builder = $this->createBuilder();
|
||||
foreach ($collection->all() as $name => $route) {
|
||||
$builder->addRoute($route, $name);
|
||||
}
|
||||
|
||||
foreach ($collection->getResources() as $resource) {
|
||||
$builder->addResource($resource);
|
||||
}
|
||||
|
||||
// mount into this builder
|
||||
$this->mount($prefix, $builder);
|
||||
|
||||
return $builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a route and returns it for future modification.
|
||||
*
|
||||
* @param string $path The route path
|
||||
* @param string $controller The route's controller
|
||||
* @param string|null $name The name to give this route
|
||||
*
|
||||
* @return Route
|
||||
*/
|
||||
public function add($path, $controller, $name = null)
|
||||
{
|
||||
$route = new Route($path);
|
||||
$route->setDefault('_controller', $controller);
|
||||
$this->addRoute($route, $name);
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a RouteCollectionBuilder that can be configured and then added with mount().
|
||||
*
|
||||
* @return RouteCollectionBuilder
|
||||
*/
|
||||
public function createBuilder()
|
||||
{
|
||||
return new self($this->loader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a RouteCollectionBuilder.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param RouteCollectionBuilder $builder
|
||||
*/
|
||||
public function mount($prefix, RouteCollectionBuilder $builder)
|
||||
{
|
||||
$builder->prefix = trim(trim($prefix), '/');
|
||||
$this->routes[] = $builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a Route object to the builder.
|
||||
*
|
||||
* @param Route $route
|
||||
* @param string|null $name
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addRoute(Route $route, $name = null)
|
||||
{
|
||||
if (null === $name) {
|
||||
// used as a flag to know which routes will need a name later
|
||||
$name = '_unnamed_route_'.spl_object_hash($route);
|
||||
}
|
||||
|
||||
$this->routes[$name] = $route;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the host on all embedded routes (unless already set).
|
||||
*
|
||||
* @param string $pattern
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setHost($pattern)
|
||||
{
|
||||
$this->host = $pattern;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a condition on all embedded routes (unless already set).
|
||||
*
|
||||
* @param string $condition
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setCondition($condition)
|
||||
{
|
||||
$this->condition = $condition;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a default value that will be added to all embedded routes (unless that
|
||||
* default value is already set).
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDefault($key, $value)
|
||||
{
|
||||
$this->defaults[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a requirement that will be added to all embedded routes (unless that
|
||||
* requirement is already set).
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $regex
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setRequirement($key, $regex)
|
||||
{
|
||||
$this->requirements[$key] = $regex;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an opiton that will be added to all embedded routes (unless that
|
||||
* option is already set).
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setOption($key, $value)
|
||||
{
|
||||
$this->options[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the schemes on all embedded routes (unless already set).
|
||||
*
|
||||
* @param array|string $schemes
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setSchemes($schemes)
|
||||
{
|
||||
$this->schemes = $schemes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the methods on all embedded routes (unless already set).
|
||||
*
|
||||
* @param array|string $methods
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setMethods($methods)
|
||||
{
|
||||
$this->methods = $methods;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a resource for this collection.
|
||||
*
|
||||
* @param ResourceInterface $resource
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function addResource(ResourceInterface $resource)
|
||||
{
|
||||
$this->resources[] = $resource;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the final RouteCollection and returns it.
|
||||
*
|
||||
* @return RouteCollection
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
$routeCollection = new RouteCollection();
|
||||
|
||||
foreach ($this->routes as $name => $route) {
|
||||
if ($route instanceof Route) {
|
||||
$route->setDefaults(array_merge($this->defaults, $route->getDefaults()));
|
||||
$route->setOptions(array_merge($this->options, $route->getOptions()));
|
||||
|
||||
foreach ($this->requirements as $key => $val) {
|
||||
if (!$route->hasRequirement($key)) {
|
||||
$route->setRequirement($key, $val);
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $this->prefix) {
|
||||
$route->setPath('/'.$this->prefix.$route->getPath());
|
||||
}
|
||||
|
||||
if (!$route->getHost()) {
|
||||
$route->setHost($this->host);
|
||||
}
|
||||
|
||||
if (!$route->getCondition()) {
|
||||
$route->setCondition($this->condition);
|
||||
}
|
||||
|
||||
if (!$route->getSchemes()) {
|
||||
$route->setSchemes($this->schemes);
|
||||
}
|
||||
|
||||
if (!$route->getMethods()) {
|
||||
$route->setMethods($this->methods);
|
||||
}
|
||||
|
||||
// auto-generate the route name if it's been marked
|
||||
if ('_unnamed_route_' === substr($name, 0, 15)) {
|
||||
$name = $this->generateRouteName($route);
|
||||
}
|
||||
|
||||
$routeCollection->add($name, $route);
|
||||
} else {
|
||||
/* @var self $route */
|
||||
$subCollection = $route->build();
|
||||
$subCollection->addPrefix($this->prefix);
|
||||
|
||||
$routeCollection->addCollection($subCollection);
|
||||
}
|
||||
|
||||
foreach ($this->resources as $resource) {
|
||||
$routeCollection->addResource($resource);
|
||||
}
|
||||
}
|
||||
|
||||
return $routeCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a route name based on details of this route.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function generateRouteName(Route $route)
|
||||
{
|
||||
$methods = implode('_', $route->getMethods()).'_';
|
||||
|
||||
$routeName = $methods.$route->getPath();
|
||||
$routeName = str_replace(array('/', ':', '|', '-'), '_', $routeName);
|
||||
$routeName = preg_replace('/[^a-z0-9A-Z_.]+/', '', $routeName);
|
||||
|
||||
// Collapse consecutive underscores down into a single underscore.
|
||||
$routeName = preg_replace('/_+/', '_', $routeName);
|
||||
|
||||
return $routeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a loader able to load an imported resource and loads it.
|
||||
*
|
||||
* @param mixed $resource A resource
|
||||
* @param string|null $type The resource type or null if unknown
|
||||
*
|
||||
* @return RouteCollection
|
||||
*
|
||||
* @throws FileLoaderLoadException If no loader is found
|
||||
*/
|
||||
private function load($resource, $type = null)
|
||||
{
|
||||
if (null === $this->loader) {
|
||||
throw new \BadMethodCallException('Cannot import other routing resources: you must pass a LoaderInterface when constructing RouteCollectionBuilder.');
|
||||
}
|
||||
|
||||
if ($this->loader->supports($resource, $type)) {
|
||||
return $this->loader->load($resource, $type);
|
||||
}
|
||||
|
||||
if (null === $resolver = $this->loader->getResolver()) {
|
||||
throw new FileLoaderLoadException($resource);
|
||||
}
|
||||
|
||||
if (false === $loader = $resolver->resolve($resource, $type)) {
|
||||
throw new FileLoaderLoadException($resource);
|
||||
}
|
||||
|
||||
return $loader->load($resource, $type);
|
||||
}
|
||||
}
|
@@ -12,7 +12,9 @@
|
||||
namespace Symfony\Component\Routing;
|
||||
|
||||
use Symfony\Component\Config\Loader\LoaderInterface;
|
||||
use Symfony\Component\Config\ConfigCache;
|
||||
use Symfony\Component\Config\ConfigCacheInterface;
|
||||
use Symfony\Component\Config\ConfigCacheFactoryInterface;
|
||||
use Symfony\Component\Config\ConfigCacheFactory;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Routing\Generator\ConfigurableRequirementsInterface;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
@@ -71,6 +73,11 @@ class Router implements RouterInterface, RequestMatcherInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @var ConfigCacheFactoryInterface|null
|
||||
*/
|
||||
private $configCacheFactory;
|
||||
|
||||
/**
|
||||
* @var ExpressionFunctionProviderInterface[]
|
||||
*/
|
||||
@@ -209,6 +216,16 @@ class Router implements RouterInterface, RequestMatcherInterface
|
||||
return $this->context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ConfigCache factory to use.
|
||||
*
|
||||
* @param ConfigCacheFactoryInterface $configCacheFactory The factory to use.
|
||||
*/
|
||||
public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory)
|
||||
{
|
||||
$this->configCacheFactory = $configCacheFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -261,27 +278,27 @@ class Router implements RouterInterface, RequestMatcherInterface
|
||||
return $this->matcher;
|
||||
}
|
||||
|
||||
$class = $this->options['matcher_cache_class'];
|
||||
$cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']);
|
||||
if (!$cache->isFresh()) {
|
||||
$dumper = $this->getMatcherDumperInstance();
|
||||
if (method_exists($dumper, 'addExpressionLanguageProvider')) {
|
||||
foreach ($this->expressionLanguageProviders as $provider) {
|
||||
$dumper->addExpressionLanguageProvider($provider);
|
||||
$cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/'.$this->options['matcher_cache_class'].'.php',
|
||||
function (ConfigCacheInterface $cache) {
|
||||
$dumper = $this->getMatcherDumperInstance();
|
||||
if (method_exists($dumper, 'addExpressionLanguageProvider')) {
|
||||
foreach ($this->expressionLanguageProviders as $provider) {
|
||||
$dumper->addExpressionLanguageProvider($provider);
|
||||
}
|
||||
}
|
||||
|
||||
$options = array(
|
||||
'class' => $this->options['matcher_cache_class'],
|
||||
'base_class' => $this->options['matcher_base_class'],
|
||||
);
|
||||
|
||||
$cache->write($dumper->dump($options), $this->getRouteCollection()->getResources());
|
||||
}
|
||||
);
|
||||
|
||||
$options = array(
|
||||
'class' => $class,
|
||||
'base_class' => $this->options['matcher_base_class'],
|
||||
);
|
||||
require_once $cache->getPath();
|
||||
|
||||
$cache->write($dumper->dump($options), $this->getRouteCollection()->getResources());
|
||||
}
|
||||
|
||||
require_once $cache;
|
||||
|
||||
return $this->matcher = new $class($this->context);
|
||||
return $this->matcher = new $this->options['matcher_cache_class']($this->context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -298,22 +315,22 @@ class Router implements RouterInterface, RequestMatcherInterface
|
||||
if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) {
|
||||
$this->generator = new $this->options['generator_class']($this->getRouteCollection(), $this->context, $this->logger);
|
||||
} else {
|
||||
$class = $this->options['generator_cache_class'];
|
||||
$cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']);
|
||||
if (!$cache->isFresh()) {
|
||||
$dumper = $this->getGeneratorDumperInstance();
|
||||
$cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/'.$this->options['generator_cache_class'].'.php',
|
||||
function (ConfigCacheInterface $cache) {
|
||||
$dumper = $this->getGeneratorDumperInstance();
|
||||
|
||||
$options = array(
|
||||
'class' => $class,
|
||||
'base_class' => $this->options['generator_base_class'],
|
||||
);
|
||||
$options = array(
|
||||
'class' => $this->options['generator_cache_class'],
|
||||
'base_class' => $this->options['generator_base_class'],
|
||||
);
|
||||
|
||||
$cache->write($dumper->dump($options), $this->getRouteCollection()->getResources());
|
||||
}
|
||||
$cache->write($dumper->dump($options), $this->getRouteCollection()->getResources());
|
||||
}
|
||||
);
|
||||
|
||||
require_once $cache;
|
||||
require_once $cache->getPath();
|
||||
|
||||
$this->generator = new $class($this->context, $this->logger);
|
||||
$this->generator = new $this->options['generator_cache_class']($this->context, $this->logger);
|
||||
}
|
||||
|
||||
if ($this->generator instanceof ConfigurableRequirementsInterface) {
|
||||
@@ -343,4 +360,19 @@ class Router implements RouterInterface, RequestMatcherInterface
|
||||
{
|
||||
return new $this->options['matcher_dumper_class']($this->getRouteCollection());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the ConfigCache factory implementation, falling back to a
|
||||
* default implementation if necessary.
|
||||
*
|
||||
* @return ConfigCacheFactoryInterface $configCacheFactory
|
||||
*/
|
||||
private function getConfigCacheFactory()
|
||||
{
|
||||
if (null === $this->configCacheFactory) {
|
||||
$this->configCacheFactory = new ConfigCacheFactory($this->options['debug']);
|
||||
}
|
||||
|
||||
return $this->configCacheFactory;
|
||||
}
|
||||
}
|
@@ -1,122 +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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@@ -1,281 +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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
Routing Component
|
||||
=================
|
||||
|
||||
Routing associates a request with the code that will convert it to a response.
|
||||
|
||||
The example below demonstrates how you can set up a fully working routing
|
||||
system:
|
||||
|
||||
```php
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Matcher\UrlMatcher;
|
||||
use Symfony\Component\Routing\RequestContext;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
$routes = new RouteCollection();
|
||||
$routes->add('hello', new Route('/hello', array('controller' => 'foo')));
|
||||
|
||||
$context = new RequestContext();
|
||||
|
||||
// this is optional and can be done without a Request instance
|
||||
$context->fromRequest(Request::createFromGlobals());
|
||||
|
||||
$matcher = new UrlMatcher($routes, $context);
|
||||
|
||||
$parameters = $matcher->match('/hello');
|
||||
```
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
You can run the unit tests with the following command:
|
||||
|
||||
$ cd path/to/Symfony/Component/Routing/
|
||||
$ composer install
|
||||
$ phpunit
|
@@ -1,204 +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;
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
class LegacyApacheMatcherDumperTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected static $fixturesPath;
|
||||
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
self::$fixturesPath = realpath(__DIR__.'/../../Fixtures/');
|
||||
}
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@@ -1,156 +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;
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
class LegacyApacheUrlMatcherTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $server;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
|
||||
$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',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@@ -36,25 +36,14 @@ class RouteTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
return array(
|
||||
array('value', '/Blog', 'getPath'),
|
||||
array('requirements', array('_method' => 'GET'), 'getRequirements'),
|
||||
array('requirements', array('locale' => 'en'), 'getRequirements'),
|
||||
array('options', array('compiler_class' => 'RouteCompiler'), 'getOptions'),
|
||||
array('name', 'blog_index', 'getName'),
|
||||
array('defaults', array('_controller' => 'MyBlogBundle:Blog:index'), 'getDefaults'),
|
||||
array('schemes', array('https'), 'getSchemes'),
|
||||
array('methods', array('GET', 'POST'), 'getMethods'),
|
||||
array('host', array('{locale}.example.com'), 'getHost'),
|
||||
array('condition', array('context.getMethod() == "GET"'), 'getCondition'),
|
||||
array('host', '{locale}.example.com', 'getHost'),
|
||||
array('condition', 'context.getMethod() == "GET"', 'getCondition'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testLegacyGetPattern()
|
||||
{
|
||||
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
|
||||
|
||||
$route = new Route(array('value' => '/Blog'));
|
||||
$this->assertEquals($route->getPattern(), '/Blog');
|
||||
}
|
||||
}
|
13
vendor/symfony/routing/Tests/Fixtures/AnnotatedClasses/FooTrait.php
vendored
Normal file
13
vendor/symfony/routing/Tests/Fixtures/AnnotatedClasses/FooTrait.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses;
|
||||
|
||||
trait FooTrait
|
||||
{
|
||||
public function doBar()
|
||||
{
|
||||
$baz = self::class;
|
||||
if (true) {
|
||||
}
|
||||
}
|
||||
}
|
19
vendor/symfony/routing/Tests/Fixtures/OtherAnnotatedClasses/VariadicClass.php
vendored
Normal file
19
vendor/symfony/routing/Tests/Fixtures/OtherAnnotatedClasses/VariadicClass.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?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\Fixtures\OtherAnnotatedClasses;
|
||||
|
||||
class VariadicClass
|
||||
{
|
||||
public function routeAction(...$params)
|
||||
{
|
||||
}
|
||||
}
|
3
vendor/symfony/routing/Tests/Fixtures/bad_format.yml
vendored
Normal file
3
vendor/symfony/routing/Tests/Fixtures/bad_format.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
blog_show:
|
||||
path: /blog/{slug}
|
||||
defaults: { _controller: "MyBundle:Blog:show" }
|
2
vendor/symfony/routing/Tests/Fixtures/directory/recurse/routes1.yml
vendored
Normal file
2
vendor/symfony/routing/Tests/Fixtures/directory/recurse/routes1.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
route1:
|
||||
path: /route/1
|
2
vendor/symfony/routing/Tests/Fixtures/directory/recurse/routes2.yml
vendored
Normal file
2
vendor/symfony/routing/Tests/Fixtures/directory/recurse/routes2.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
route2:
|
||||
path: /route/2
|
2
vendor/symfony/routing/Tests/Fixtures/directory/routes3.yml
vendored
Normal file
2
vendor/symfony/routing/Tests/Fixtures/directory/routes3.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
route3:
|
||||
path: /route/3
|
3
vendor/symfony/routing/Tests/Fixtures/directory_import/import.yml
vendored
Normal file
3
vendor/symfony/routing/Tests/Fixtures/directory_import/import.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
_directory:
|
||||
resource: "../directory"
|
||||
type: directory
|
0
vendor/symfony/routing/Tests/Fixtures/foo.xml
vendored
Normal file
0
vendor/symfony/routing/Tests/Fixtures/foo.xml
vendored
Normal file
0
vendor/symfony/routing/Tests/Fixtures/foo1.xml
vendored
Normal file
0
vendor/symfony/routing/Tests/Fixtures/foo1.xml
vendored
Normal file
@@ -6,6 +6,5 @@
|
||||
|
||||
<route id="blog_show" path="/blog/{slug}">
|
||||
<default key="_controller">MyBundle:Blog:show</default>
|
||||
<requirement key="_method">GET</requirement>
|
||||
<!-- </route> -->
|
||||
</routes>
|
@@ -6,7 +6,6 @@
|
||||
|
||||
<route id="blog_show" path="/blog/{slug}">
|
||||
<default key="_controller">MyBundle:Blog:show</default>
|
||||
<requirement key="_method">GET</requirement>
|
||||
<option key="compiler_class">RouteCompiler</option>
|
||||
<foo key="bar">baz</foo>
|
||||
</route>
|
@@ -14,15 +14,5 @@ $collection->add('blog_show', new Route(
|
||||
array('GET', 'POST', 'put', 'OpTiOnS'),
|
||||
'context.getMethod() == "GET"'
|
||||
));
|
||||
$collection->add('blog_show_legacy', new Route(
|
||||
'/blog/{slug}',
|
||||
array('_controller' => 'MyBlogBundle:Blog:show'),
|
||||
array('_method' => 'GET|POST|put|OpTiOnS', '_scheme' => 'https', 'locale' => '\w+'),
|
||||
array('compiler_class' => 'RouteCompiler'),
|
||||
'{locale}.example.com',
|
||||
array(),
|
||||
array(),
|
||||
'context.getMethod() == "GET"'
|
||||
));
|
||||
|
||||
return $collection;
|
@@ -11,15 +11,5 @@
|
||||
<condition>context.getMethod() == "GET"</condition>
|
||||
</route>
|
||||
|
||||
<route id="blog_show_legacy" pattern="/blog/{slug}" host="{locale}.example.com">
|
||||
<default key="_controller">MyBundle:Blog:show</default>
|
||||
<default key="slug" xsi:nil="true" />
|
||||
<requirement key="_method">GET|POST|put|OpTiOnS</requirement>
|
||||
<requirement key="_scheme">hTTps</requirement>
|
||||
<requirement key="locale">\w+</requirement>
|
||||
<option key="compiler_class">RouteCompiler</option>
|
||||
<condition>context.getMethod() == "GET"</condition>
|
||||
</route>
|
||||
|
||||
<route id="blog_show_inherited" path="/blog/{slug}" />
|
||||
</routes>
|
@@ -9,14 +9,5 @@ blog_show:
|
||||
options:
|
||||
compiler_class: RouteCompiler
|
||||
|
||||
blog_show_legacy:
|
||||
pattern: /blog/{slug}
|
||||
defaults: { _controller: "MyBundle:Blog:show" }
|
||||
host: "{locale}.example.com"
|
||||
requirements: { '_method': 'GET|POST|put|OpTiOnS', _scheme: https, 'locale': '\w+' }
|
||||
condition: 'context.getMethod() == "GET"'
|
||||
options:
|
||||
compiler_class: RouteCompiler
|
||||
|
||||
blog_show_inherited:
|
||||
path: /blog/{slug}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user