Laravel 5.6 updates
Travis config update Removed HHVM script as Laravel no longer support HHVM after releasing 5.3
This commit is contained in:
22
vendor/symfony/routing/Annotation/Route.php
vendored
22
vendor/symfony/routing/Annotation/Route.php
vendored
@@ -22,6 +22,7 @@ namespace Symfony\Component\Routing\Annotation;
|
||||
class Route
|
||||
{
|
||||
private $path;
|
||||
private $localizedPaths = array();
|
||||
private $name;
|
||||
private $requirements = array();
|
||||
private $options = array();
|
||||
@@ -38,11 +39,20 @@ class Route
|
||||
*/
|
||||
public function __construct(array $data)
|
||||
{
|
||||
if (isset($data['localized_paths'])) {
|
||||
throw new \BadMethodCallException(sprintf('Unknown property "localized_paths" on annotation "%s".', \get_class($this)));
|
||||
}
|
||||
|
||||
if (isset($data['value'])) {
|
||||
$data['path'] = $data['value'];
|
||||
$data[\is_array($data['value']) ? 'localized_paths' : 'path'] = $data['value'];
|
||||
unset($data['value']);
|
||||
}
|
||||
|
||||
if (isset($data['path']) && \is_array($data['path'])) {
|
||||
$data['localized_paths'] = $data['path'];
|
||||
unset($data['path']);
|
||||
}
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
$method = 'set'.str_replace('_', '', $key);
|
||||
if (!method_exists($this, $method)) {
|
||||
@@ -62,6 +72,16 @@ class Route
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
public function setLocalizedPaths(array $localizedPaths)
|
||||
{
|
||||
$this->localizedPaths = $localizedPaths;
|
||||
}
|
||||
|
||||
public function getLocalizedPaths(): array
|
||||
{
|
||||
return $this->localizedPaths;
|
||||
}
|
||||
|
||||
public function setHost($pattern)
|
||||
{
|
||||
$this->host = $pattern;
|
||||
|
6
vendor/symfony/routing/CHANGELOG.md
vendored
6
vendor/symfony/routing/CHANGELOG.md
vendored
@@ -1,6 +1,12 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
4.0.0
|
||||
-----
|
||||
|
||||
* dropped support for using UTF-8 route patterns without using the `utf8` option
|
||||
* dropped support for using UTF-8 route requirements without using the `utf8` option
|
||||
|
||||
3.4.0
|
||||
-----
|
||||
|
||||
|
10
vendor/symfony/routing/CompiledRoute.php
vendored
10
vendor/symfony/routing/CompiledRoute.php
vendored
@@ -37,9 +37,9 @@ class CompiledRoute implements \Serializable
|
||||
* @param array $hostVariables An array of host variables
|
||||
* @param array $variables An array of variables (variables defined in the path and in the host patterns)
|
||||
*/
|
||||
public function __construct($staticPrefix, $regex, array $tokens, array $pathVariables, $hostRegex = null, array $hostTokens = array(), array $hostVariables = array(), array $variables = array())
|
||||
public function __construct(string $staticPrefix, string $regex, array $tokens, array $pathVariables, string $hostRegex = null, array $hostTokens = array(), array $hostVariables = array(), array $variables = array())
|
||||
{
|
||||
$this->staticPrefix = (string) $staticPrefix;
|
||||
$this->staticPrefix = $staticPrefix;
|
||||
$this->regex = $regex;
|
||||
$this->tokens = $tokens;
|
||||
$this->pathVariables = $pathVariables;
|
||||
@@ -71,11 +71,7 @@ class CompiledRoute implements \Serializable
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
if (\PHP_VERSION_ID >= 70000) {
|
||||
$data = unserialize($serialized, array('allowed_classes' => false));
|
||||
} else {
|
||||
$data = unserialize($serialized);
|
||||
}
|
||||
$data = unserialize($serialized, array('allowed_classes' => false));
|
||||
|
||||
$this->variables = $data['vars'];
|
||||
$this->staticPrefix = $data['path_prefix'];
|
||||
|
@@ -28,7 +28,7 @@ class RoutingResolverPass implements CompilerPassInterface
|
||||
private $resolverServiceId;
|
||||
private $loaderTag;
|
||||
|
||||
public function __construct($resolverServiceId = 'routing.resolver', $loaderTag = 'routing.loader')
|
||||
public function __construct(string $resolverServiceId = 'routing.resolver', string $loaderTag = 'routing.loader')
|
||||
{
|
||||
$this->resolverServiceId = $resolverServiceId;
|
||||
$this->loaderTag = $loaderTag;
|
||||
|
@@ -22,7 +22,7 @@ class MethodNotAllowedException extends \RuntimeException implements ExceptionIn
|
||||
{
|
||||
protected $allowedMethods = array();
|
||||
|
||||
public function __construct(array $allowedMethods, $message = null, $code = 0, \Exception $previous = null)
|
||||
public function __construct(array $allowedMethods, string $message = null, int $code = 0, \Exception $previous = null)
|
||||
{
|
||||
$this->allowedMethods = array_map('strtoupper', $allowedMethods);
|
||||
|
||||
|
@@ -11,6 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Routing\Generator\Dumper;
|
||||
|
||||
use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper;
|
||||
|
||||
/**
|
||||
* PhpGeneratorDumper creates a PHP class able to generate URLs for a given set of routes.
|
||||
*
|
||||
@@ -52,11 +54,13 @@ use Psr\Log\LoggerInterface;
|
||||
class {$options['class']} extends {$options['base_class']}
|
||||
{
|
||||
private static \$declaredRoutes;
|
||||
private \$defaultLocale;
|
||||
|
||||
public function __construct(RequestContext \$context, LoggerInterface \$logger = null)
|
||||
public function __construct(RequestContext \$context, LoggerInterface \$logger = null, string \$defaultLocale = null)
|
||||
{
|
||||
\$this->context = \$context;
|
||||
\$this->logger = \$logger;
|
||||
\$this->defaultLocale = \$defaultLocale;
|
||||
if (null === self::\$declaredRoutes) {
|
||||
self::\$declaredRoutes = {$this->generateDeclaredRoutes()};
|
||||
}
|
||||
@@ -88,7 +92,7 @@ EOF;
|
||||
$properties[] = $compiledRoute->getHostTokens();
|
||||
$properties[] = $route->getSchemes();
|
||||
|
||||
$routes .= sprintf(" '%s' => %s,\n", $name, str_replace("\n", '', var_export($properties, true)));
|
||||
$routes .= sprintf(" '%s' => %s,\n", $name, PhpMatcherDumper::export($properties));
|
||||
}
|
||||
$routes .= ' )';
|
||||
|
||||
@@ -105,7 +109,14 @@ EOF;
|
||||
return <<<'EOF'
|
||||
public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH)
|
||||
{
|
||||
if (!isset(self::$declaredRoutes[$name])) {
|
||||
$locale = $parameters['_locale']
|
||||
?? $this->context->getParameter('_locale')
|
||||
?: $this->defaultLocale;
|
||||
|
||||
if (null !== $locale && (self::$declaredRoutes[$name.'.'.$locale][1]['_canonical_route'] ?? null) === $name) {
|
||||
unset($parameters['_locale']);
|
||||
$name .= '.'.$locale;
|
||||
} elseif (!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));
|
||||
}
|
||||
|
||||
|
@@ -37,6 +37,8 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt
|
||||
|
||||
protected $logger;
|
||||
|
||||
private $defaultLocale;
|
||||
|
||||
/**
|
||||
* This array defines the characters (besides alphanumeric ones) that will not be percent-encoded in the path segment of the generated URL.
|
||||
*
|
||||
@@ -65,11 +67,12 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt
|
||||
'%7C' => '|',
|
||||
);
|
||||
|
||||
public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null)
|
||||
public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null, string $defaultLocale = null)
|
||||
{
|
||||
$this->routes = $routes;
|
||||
$this->context = $context;
|
||||
$this->logger = $logger;
|
||||
$this->defaultLocale = $defaultLocale;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,7 +112,13 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt
|
||||
*/
|
||||
public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH)
|
||||
{
|
||||
if (null === $route = $this->routes->get($name)) {
|
||||
$locale = $parameters['_locale']
|
||||
?? $this->context->getParameter('_locale')
|
||||
?: $this->defaultLocale;
|
||||
|
||||
if (null !== $locale && null !== ($route = $this->routes->get($name.'.'.$locale)) && $route->getDefault('_canonical_route') === $name) {
|
||||
unset($parameters['_locale']);
|
||||
} elseif (null === $route = $this->routes->get($name)) {
|
||||
throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name));
|
||||
}
|
||||
|
||||
|
@@ -124,6 +124,7 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
||||
if ($annot instanceof $this->routeAnnotationClass) {
|
||||
$globals['path'] = '';
|
||||
$globals['name'] = '';
|
||||
$globals['localized_paths'] = array();
|
||||
|
||||
$this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke'));
|
||||
}
|
||||
@@ -142,11 +143,6 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
||||
$name = $globals['name'].$name;
|
||||
|
||||
$defaults = array_replace($globals['defaults'], $annot->getDefaults());
|
||||
foreach ($method->getParameters() as $param) {
|
||||
if (false !== strpos($globals['path'].$annot->getPath(), sprintf('{%s}', $param->getName())) && !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_merge($globals['schemes'], $annot->getSchemes());
|
||||
@@ -162,11 +158,57 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
||||
$condition = $globals['condition'];
|
||||
}
|
||||
|
||||
$route = $this->createRoute($globals['path'].$annot->getPath(), $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
|
||||
$path = $annot->getLocalizedPaths() ?: $annot->getPath();
|
||||
$prefix = $globals['localized_paths'] ?: $globals['path'];
|
||||
$paths = array();
|
||||
|
||||
$this->configureRoute($route, $class, $method, $annot);
|
||||
if (\is_array($path)) {
|
||||
if (!\is_array($prefix)) {
|
||||
foreach ($path as $locale => $localePath) {
|
||||
$paths[$locale] = $prefix.$localePath;
|
||||
}
|
||||
} elseif ($missing = array_diff_key($prefix, $path)) {
|
||||
throw new \LogicException(sprintf('Route to "%s" is missing paths for locale(s) "%s".', $class->name.'::'.$method->name, implode('", "', array_keys($missing))));
|
||||
} else {
|
||||
foreach ($path as $locale => $localePath) {
|
||||
if (!isset($prefix[$locale])) {
|
||||
throw new \LogicException(sprintf('Route to "%s" with locale "%s" is missing a corresponding prefix in class "%s".', $method->name, $locale, $class->name));
|
||||
}
|
||||
|
||||
$collection->add($name, $route);
|
||||
$paths[$locale] = $prefix[$locale].$localePath;
|
||||
}
|
||||
}
|
||||
} elseif (\is_array($prefix)) {
|
||||
foreach ($prefix as $locale => $localePrefix) {
|
||||
$paths[$locale] = $localePrefix.$path;
|
||||
}
|
||||
} else {
|
||||
$paths[] = $prefix.$path;
|
||||
}
|
||||
|
||||
foreach ($method->getParameters() as $param) {
|
||||
if (isset($defaults[$param->name]) || !$param->isDefaultValueAvailable()) {
|
||||
continue;
|
||||
}
|
||||
foreach ($paths as $locale => $path) {
|
||||
if (false !== strpos($path, sprintf('{%s}', $param->name))) {
|
||||
$defaults[$param->name] = $param->getDefaultValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($paths as $locale => $path) {
|
||||
$route = $this->createRoute($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
|
||||
$this->configureRoute($route, $class, $method, $annot);
|
||||
if (0 !== $locale) {
|
||||
$route->setDefault('_locale', $locale);
|
||||
$route->setDefault('_canonical_route', $name);
|
||||
$collection->add($name.'.'.$locale, $route);
|
||||
} else {
|
||||
$collection->add($name, $route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,7 +255,8 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
||||
protected function getGlobals(\ReflectionClass $class)
|
||||
{
|
||||
$globals = array(
|
||||
'path' => '',
|
||||
'path' => null,
|
||||
'localized_paths' => array(),
|
||||
'requirements' => array(),
|
||||
'options' => array(),
|
||||
'defaults' => array(),
|
||||
@@ -233,6 +276,8 @@ abstract class AnnotationClassLoader implements LoaderInterface
|
||||
$globals['path'] = $annot->getPath();
|
||||
}
|
||||
|
||||
$globals['localized_paths'] = $annot->getLocalizedPaths();
|
||||
|
||||
if (null !== $annot->getRequirements()) {
|
||||
$globals['requirements'] = $annot->getRequirements();
|
||||
}
|
||||
|
@@ -59,10 +59,9 @@ 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();
|
||||
}
|
||||
|
||||
// PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098
|
||||
gc_mem_caches();
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
@@ -24,37 +24,27 @@ class CollectionConfigurator
|
||||
|
||||
private $parent;
|
||||
private $parentConfigurator;
|
||||
private $parentPrefixes;
|
||||
|
||||
public function __construct(RouteCollection $parent, $name, self $parentConfigurator = null)
|
||||
public function __construct(RouteCollection $parent, string $name, self $parentConfigurator = null, array $parentPrefixes = null)
|
||||
{
|
||||
$this->parent = $parent;
|
||||
$this->name = $name;
|
||||
$this->collection = new RouteCollection();
|
||||
$this->route = new Route('');
|
||||
$this->parentConfigurator = $parentConfigurator; // for GC control
|
||||
$this->parentPrefixes = $parentPrefixes;
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
$this->collection->addPrefix(rtrim($this->route->getPath(), '/'));
|
||||
if (null === $this->prefixes) {
|
||||
$this->collection->addPrefix($this->route->getPath());
|
||||
}
|
||||
|
||||
$this->parent->addCollection($this->collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a route.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $path
|
||||
*
|
||||
* @return RouteConfigurator
|
||||
*/
|
||||
final public function add($name, $path)
|
||||
{
|
||||
$this->collection->add($this->name.$name, $route = clone $this->route);
|
||||
|
||||
return new RouteConfigurator($this->collection, $route->setPath($path), $this->name, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a sub-collection.
|
||||
*
|
||||
@@ -62,20 +52,44 @@ class CollectionConfigurator
|
||||
*/
|
||||
final public function collection($name = '')
|
||||
{
|
||||
return new self($this->collection, $this->name.$name, $this);
|
||||
return new self($this->collection, $this->name.$name, $this, $this->prefixes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the prefix to add to the path of all child routes.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param string|array $prefix the prefix, or the localized prefixes
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
final public function prefix($prefix)
|
||||
{
|
||||
$this->route->setPath($prefix);
|
||||
if (\is_array($prefix)) {
|
||||
if (null === $this->parentPrefixes) {
|
||||
// no-op
|
||||
} elseif ($missing = array_diff_key($this->parentPrefixes, $prefix)) {
|
||||
throw new \LogicException(sprintf('Collection "%s" is missing prefixes for locale(s) "%s".', $this->name, implode('", "', array_keys($missing))));
|
||||
} else {
|
||||
foreach ($prefix as $locale => $localePrefix) {
|
||||
if (!isset($this->parentPrefixes[$locale])) {
|
||||
throw new \LogicException(sprintf('Collection "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $this->name, $locale));
|
||||
}
|
||||
|
||||
$prefix[$locale] = $this->parentPrefixes[$locale].$localePrefix;
|
||||
}
|
||||
}
|
||||
$this->prefixes = $prefix;
|
||||
$this->route->setPath('/');
|
||||
} else {
|
||||
$this->prefixes = null;
|
||||
$this->route->setPath($prefix);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function createRoute($path): Route
|
||||
{
|
||||
return (clone $this->route)->setPath($path);
|
||||
}
|
||||
}
|
||||
|
@@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\Routing\Loader\Configurator;
|
||||
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
/**
|
||||
@@ -36,13 +37,56 @@ class ImportConfigurator
|
||||
/**
|
||||
* Sets the prefix to add to the path of all child routes.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param string|array $prefix the prefix, or the localized prefixes
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
final public function prefix($prefix)
|
||||
final public function prefix($prefix, bool $trailingSlashOnRoot = true)
|
||||
{
|
||||
$this->route->addPrefix($prefix);
|
||||
if (!\is_array($prefix)) {
|
||||
$this->route->addPrefix($prefix);
|
||||
if (!$trailingSlashOnRoot) {
|
||||
$rootPath = (new Route(trim(trim($prefix), '/').'/'))->getPath();
|
||||
foreach ($this->route->all() as $route) {
|
||||
if ($route->getPath() === $rootPath) {
|
||||
$route->setPath(rtrim($rootPath, '/'));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($prefix as $locale => $localePrefix) {
|
||||
$prefix[$locale] = trim(trim($localePrefix), '/');
|
||||
}
|
||||
foreach ($this->route->all() as $name => $route) {
|
||||
if (null === $locale = $route->getDefault('_locale')) {
|
||||
$this->route->remove($name);
|
||||
foreach ($prefix as $locale => $localePrefix) {
|
||||
$localizedRoute = clone $route;
|
||||
$localizedRoute->setDefault('_locale', $locale);
|
||||
$localizedRoute->setDefault('_canonical_route', $name);
|
||||
$localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath()));
|
||||
$this->route->add($name.'.'.$locale, $localizedRoute);
|
||||
}
|
||||
} elseif (!isset($prefix[$locale])) {
|
||||
throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale));
|
||||
} else {
|
||||
$route->setPath($prefix[$locale].(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath()));
|
||||
$this->route->add($name, $route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the prefix to add to the name of all child routes.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
final public function namePrefix(string $namePrefix)
|
||||
{
|
||||
$this->route->addNamePrefix($namePrefix);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@@ -11,7 +11,6 @@
|
||||
|
||||
namespace Symfony\Component\Routing\Loader\Configurator;
|
||||
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
/**
|
||||
@@ -24,11 +23,12 @@ class RouteConfigurator
|
||||
|
||||
private $parentConfigurator;
|
||||
|
||||
public function __construct(RouteCollection $collection, Route $route, $name = '', CollectionConfigurator $parentConfigurator = null)
|
||||
public function __construct(RouteCollection $collection, $route, string $name = '', CollectionConfigurator $parentConfigurator = null, array $prefixes = null)
|
||||
{
|
||||
$this->collection = $collection;
|
||||
$this->route = $route;
|
||||
$this->name = $name;
|
||||
$this->parentConfigurator = $parentConfigurator; // for GC control
|
||||
$this->prefixes = $prefixes;
|
||||
}
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@ class RoutingConfigurator
|
||||
private $path;
|
||||
private $file;
|
||||
|
||||
public function __construct(RouteCollection $collection, PhpFileLoader $loader, $path, $file)
|
||||
public function __construct(RouteCollection $collection, PhpFileLoader $loader, string $path, string $file)
|
||||
{
|
||||
$this->collection = $collection;
|
||||
$this->loader = $loader;
|
||||
|
@@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\Routing\Loader\Configurator\Traits;
|
||||
|
||||
use Symfony\Component\Routing\Loader\Configurator\CollectionConfigurator;
|
||||
use Symfony\Component\Routing\Loader\Configurator\RouteConfigurator;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
@@ -24,32 +25,66 @@ trait AddTrait
|
||||
|
||||
private $name = '';
|
||||
|
||||
private $prefixes;
|
||||
|
||||
/**
|
||||
* Adds a route.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $path
|
||||
*
|
||||
* @return RouteConfigurator
|
||||
* @param string|array $path the path, or the localized paths of the route
|
||||
*/
|
||||
final public function add($name, $path)
|
||||
final public function add(string $name, $path): RouteConfigurator
|
||||
{
|
||||
$parentConfigurator = $this instanceof RouteConfigurator ? $this->parentConfigurator : null;
|
||||
$this->collection->add($this->name.$name, $route = new Route($path));
|
||||
$paths = array();
|
||||
$parentConfigurator = $this instanceof CollectionConfigurator ? $this : ($this instanceof RouteConfigurator ? $this->parentConfigurator : null);
|
||||
|
||||
return new RouteConfigurator($this->collection, $route, '', $parentConfigurator);
|
||||
if (\is_array($path)) {
|
||||
if (null === $this->prefixes) {
|
||||
$paths = $path;
|
||||
} elseif ($missing = array_diff_key($this->prefixes, $path)) {
|
||||
throw new \LogicException(sprintf('Route "%s" is missing routes for locale(s) "%s".', $name, implode('", "', array_keys($missing))));
|
||||
} else {
|
||||
foreach ($path as $locale => $localePath) {
|
||||
if (!isset($this->prefixes[$locale])) {
|
||||
throw new \LogicException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale));
|
||||
}
|
||||
|
||||
$paths[$locale] = $this->prefixes[$locale].$localePath;
|
||||
}
|
||||
}
|
||||
} elseif (null !== $this->prefixes) {
|
||||
foreach ($this->prefixes as $locale => $prefix) {
|
||||
$paths[$locale] = $prefix.$path;
|
||||
}
|
||||
} else {
|
||||
$this->collection->add($this->name.$name, $route = $this->createRoute($path));
|
||||
|
||||
return new RouteConfigurator($this->collection, $route, $this->name, $parentConfigurator, $this->prefixes);
|
||||
}
|
||||
|
||||
$routes = new RouteCollection();
|
||||
|
||||
foreach ($paths as $locale => $path) {
|
||||
$routes->add($name.'.'.$locale, $route = $this->createRoute($path));
|
||||
$this->collection->add($this->name.$name.'.'.$locale, $route);
|
||||
$route->setDefault('_locale', $locale);
|
||||
$route->setDefault('_canonical_route', $this->name.$name);
|
||||
}
|
||||
|
||||
return new RouteConfigurator($this->collection, $routes, $this->name, $parentConfigurator, $this->prefixes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a route.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $path
|
||||
*
|
||||
* @return RouteConfigurator
|
||||
* @param string|array $path the path, or the localized paths of the route
|
||||
*/
|
||||
final public function __invoke($name, $path)
|
||||
final public function __invoke(string $name, $path): RouteConfigurator
|
||||
{
|
||||
return $this->add($name, $path);
|
||||
}
|
||||
|
||||
private function createRoute($path): Route
|
||||
{
|
||||
return new Route($path);
|
||||
}
|
||||
}
|
||||
|
@@ -60,11 +60,9 @@ trait RouteTrait
|
||||
/**
|
||||
* Sets the condition.
|
||||
*
|
||||
* @param string $condition
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
final public function condition($condition)
|
||||
final public function condition(string $condition)
|
||||
{
|
||||
$this->route->setCondition($condition);
|
||||
|
||||
@@ -74,11 +72,9 @@ trait RouteTrait
|
||||
/**
|
||||
* Sets the pattern for the host.
|
||||
*
|
||||
* @param string $pattern
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
final public function host($pattern)
|
||||
final public function host(string $pattern)
|
||||
{
|
||||
$this->route->setHost($pattern);
|
||||
|
||||
|
@@ -44,9 +44,14 @@ abstract class ObjectRouteLoader extends Loader
|
||||
*/
|
||||
public function load($resource, $type = null)
|
||||
{
|
||||
$parts = explode(':', $resource);
|
||||
if (1 === substr_count($resource, ':')) {
|
||||
$resource = str_replace(':', '::', $resource);
|
||||
@trigger_error(sprintf('Referencing service route loaders with a single colon is deprecated since Symfony 4.1. Use %s instead.', $resource), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$parts = explode('::', $resource);
|
||||
if (2 != \count($parts)) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid resource "%s" passed to the "service" route loader: use the format "service_name:methodName"', $resource));
|
||||
throw new \InvalidArgumentException(sprintf('Invalid resource "%s" passed to the "service" route loader: use the format "service::method"', $resource));
|
||||
}
|
||||
|
||||
$serviceString = $parts[0];
|
||||
@@ -58,7 +63,7 @@ abstract class ObjectRouteLoader extends Loader
|
||||
throw new \LogicException(sprintf('%s:getServiceObject() must return an object: %s returned', \get_class($this), \gettype($loaderObject)));
|
||||
}
|
||||
|
||||
if (!method_exists($loaderObject, $method)) {
|
||||
if (!\is_callable(array($loaderObject, $method))) {
|
||||
throw new \BadMethodCallException(sprintf('Method "%s" not found on "%s" when importing routing resource "%s"', $method, \get_class($loaderObject), $resource));
|
||||
}
|
||||
|
||||
|
@@ -46,7 +46,7 @@ class PhpFileLoader extends FileLoader
|
||||
|
||||
$result = $load($path);
|
||||
|
||||
if ($result instanceof \Closure) {
|
||||
if (\is_object($result) && \is_callable($result)) {
|
||||
$collection = new RouteCollection();
|
||||
$result(new RoutingConfigurator($collection, $this, $path, $file), $this);
|
||||
} else {
|
||||
|
82
vendor/symfony/routing/Loader/XmlFileLoader.php
vendored
82
vendor/symfony/routing/Loader/XmlFileLoader.php
vendored
@@ -107,17 +107,34 @@ class XmlFileLoader extends FileLoader
|
||||
*/
|
||||
protected function parseRoute(RouteCollection $collection, \DOMElement $node, $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 ('' === $id = $node->getAttribute('id')) {
|
||||
throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have an "id" attribute.', $path));
|
||||
}
|
||||
|
||||
$schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY);
|
||||
$methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY);
|
||||
|
||||
list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path);
|
||||
list($defaults, $requirements, $options, $condition, $paths) = $this->parseConfigs($node, $path);
|
||||
|
||||
$route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition);
|
||||
$collection->add($id, $route);
|
||||
if (!$paths && '' === $node->getAttribute('path')) {
|
||||
throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have a "path" attribute or <path> child nodes.', $path));
|
||||
}
|
||||
|
||||
if ($paths && '' !== $node->getAttribute('path')) {
|
||||
throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must not have both a "path" attribute and <path> child nodes.', $path));
|
||||
}
|
||||
|
||||
if (!$paths) {
|
||||
$route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition);
|
||||
$collection->add($id, $route);
|
||||
} else {
|
||||
foreach ($paths as $locale => $p) {
|
||||
$defaults['_locale'] = $locale;
|
||||
$defaults['_canonical_route'] = $id;
|
||||
$route = new Route($p, $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition);
|
||||
$collection->add($id.'.'.$locale, $route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,8 +158,13 @@ class XmlFileLoader extends FileLoader
|
||||
$host = $node->hasAttribute('host') ? $node->getAttribute('host') : null;
|
||||
$schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY) : null;
|
||||
$methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY) : null;
|
||||
$trailingSlashOnRoot = $node->hasAttribute('trailing-slash-on-root') ? XmlUtils::phpize($node->getAttribute('trailing-slash-on-root')) : true;
|
||||
|
||||
list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path);
|
||||
list($defaults, $requirements, $options, $condition, /* $paths */, $prefixes) = $this->parseConfigs($node, $path);
|
||||
|
||||
if ('' !== $prefix && $prefixes) {
|
||||
throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must not have both a "prefix" attribute and <prefix> child nodes.', $path));
|
||||
}
|
||||
|
||||
$this->setCurrentDir(\dirname($path));
|
||||
|
||||
@@ -154,7 +176,39 @@ class XmlFileLoader extends FileLoader
|
||||
|
||||
foreach ($imported as $subCollection) {
|
||||
/* @var $subCollection RouteCollection */
|
||||
$subCollection->addPrefix($prefix);
|
||||
if ('' !== $prefix || !$prefixes) {
|
||||
$subCollection->addPrefix($prefix);
|
||||
if (!$trailingSlashOnRoot) {
|
||||
$rootPath = (new Route(trim(trim($prefix), '/').'/'))->getPath();
|
||||
foreach ($subCollection->all() as $route) {
|
||||
if ($route->getPath() === $rootPath) {
|
||||
$route->setPath(rtrim($rootPath, '/'));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($prefixes as $locale => $localePrefix) {
|
||||
$prefixes[$locale] = trim(trim($localePrefix), '/');
|
||||
}
|
||||
foreach ($subCollection->all() as $name => $route) {
|
||||
if (null === $locale = $route->getDefault('_locale')) {
|
||||
$subCollection->remove($name);
|
||||
foreach ($prefixes as $locale => $localePrefix) {
|
||||
$localizedRoute = clone $route;
|
||||
$localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath()));
|
||||
$localizedRoute->setDefault('_locale', $locale);
|
||||
$localizedRoute->setDefault('_canonical_route', $name);
|
||||
$subCollection->add($name.'.'.$locale, $localizedRoute);
|
||||
}
|
||||
} elseif (!isset($prefixes[$locale])) {
|
||||
throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix when imported in "%s".', $name, $locale, $path));
|
||||
} else {
|
||||
$route->setPath($prefixes[$locale].(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath()));
|
||||
$subCollection->add($name, $route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $host) {
|
||||
$subCollection->setHost($host);
|
||||
}
|
||||
@@ -171,6 +225,10 @@ class XmlFileLoader extends FileLoader
|
||||
$subCollection->addRequirements($requirements);
|
||||
$subCollection->addOptions($options);
|
||||
|
||||
if ($namePrefix = $node->getAttribute('name-prefix')) {
|
||||
$subCollection->addNamePrefix($namePrefix);
|
||||
}
|
||||
|
||||
$collection->addCollection($subCollection);
|
||||
}
|
||||
}
|
||||
@@ -207,6 +265,8 @@ class XmlFileLoader extends FileLoader
|
||||
$requirements = array();
|
||||
$options = array();
|
||||
$condition = null;
|
||||
$prefixes = array();
|
||||
$paths = array();
|
||||
|
||||
foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) {
|
||||
if ($node !== $n->parentNode) {
|
||||
@@ -214,6 +274,12 @@ class XmlFileLoader extends FileLoader
|
||||
}
|
||||
|
||||
switch ($n->localName) {
|
||||
case 'path':
|
||||
$paths[$n->getAttribute('locale')] = trim($n->textContent);
|
||||
break;
|
||||
case 'prefix':
|
||||
$prefixes[$n->getAttribute('locale')] = trim($n->textContent);
|
||||
break;
|
||||
case 'default':
|
||||
if ($this->isElementValueNull($n)) {
|
||||
$defaults[$n->getAttribute('key')] = null;
|
||||
@@ -246,7 +312,7 @@ class XmlFileLoader extends FileLoader
|
||||
$defaults['_controller'] = $controller;
|
||||
}
|
||||
|
||||
return array($defaults, $requirements, $options, $condition);
|
||||
return array($defaults, $requirements, $options, $condition, $paths, $prefixes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
67
vendor/symfony/routing/Loader/YamlFileLoader.php
vendored
67
vendor/symfony/routing/Loader/YamlFileLoader.php
vendored
@@ -17,6 +17,7 @@ use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
use Symfony\Component\Yaml\Exception\ParseException;
|
||||
use Symfony\Component\Yaml\Parser as YamlParser;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
/**
|
||||
* YamlFileLoader loads Yaml routing files.
|
||||
@@ -27,7 +28,7 @@ use Symfony\Component\Yaml\Parser as YamlParser;
|
||||
class YamlFileLoader extends FileLoader
|
||||
{
|
||||
private static $availableKeys = array(
|
||||
'resource', 'type', 'prefix', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition', 'controller',
|
||||
'resource', 'type', 'prefix', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition', 'controller', 'name_prefix', 'trailing_slash_on_root',
|
||||
);
|
||||
private $yamlParser;
|
||||
|
||||
@@ -57,18 +58,10 @@ class YamlFileLoader extends FileLoader
|
||||
$this->yamlParser = new YamlParser();
|
||||
}
|
||||
|
||||
$prevErrorHandler = set_error_handler(function ($level, $message, $script, $line) use ($file, &$prevErrorHandler) {
|
||||
$message = E_USER_DEPRECATED === $level ? preg_replace('/ on line \d+/', ' in "'.$file.'"$0', $message) : $message;
|
||||
|
||||
return $prevErrorHandler ? $prevErrorHandler($level, $message, $script, $line) : false;
|
||||
});
|
||||
|
||||
try {
|
||||
$parsedConfig = $this->yamlParser->parseFile($path);
|
||||
$parsedConfig = $this->yamlParser->parseFile($path, Yaml::PARSE_CONSTANT);
|
||||
} catch (ParseException $e) {
|
||||
throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e);
|
||||
} finally {
|
||||
restore_error_handler();
|
||||
}
|
||||
|
||||
$collection = new RouteCollection();
|
||||
@@ -127,9 +120,20 @@ class YamlFileLoader extends FileLoader
|
||||
$defaults['_controller'] = $config['controller'];
|
||||
}
|
||||
|
||||
$route = new Route($config['path'], $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
|
||||
if (\is_array($config['path'])) {
|
||||
$route = new Route('', $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
|
||||
|
||||
$collection->add($name, $route);
|
||||
foreach ($config['path'] as $locale => $path) {
|
||||
$localizedRoute = clone $route;
|
||||
$localizedRoute->setDefault('_locale', $locale);
|
||||
$localizedRoute->setDefault('_canonical_route', $name);
|
||||
$localizedRoute->setPath($path);
|
||||
$collection->add($name.'.'.$locale, $localizedRoute);
|
||||
}
|
||||
} else {
|
||||
$route = new Route($config['path'], $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
|
||||
$collection->add($name, $route);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,6 +155,7 @@ class YamlFileLoader extends FileLoader
|
||||
$condition = isset($config['condition']) ? $config['condition'] : null;
|
||||
$schemes = isset($config['schemes']) ? $config['schemes'] : null;
|
||||
$methods = isset($config['methods']) ? $config['methods'] : null;
|
||||
$trailingSlashOnRoot = $config['trailing_slash_on_root'] ?? true;
|
||||
|
||||
if (isset($config['controller'])) {
|
||||
$defaults['_controller'] = $config['controller'];
|
||||
@@ -166,7 +171,39 @@ class YamlFileLoader extends FileLoader
|
||||
|
||||
foreach ($imported as $subCollection) {
|
||||
/* @var $subCollection RouteCollection */
|
||||
$subCollection->addPrefix($prefix);
|
||||
if (!\is_array($prefix)) {
|
||||
$subCollection->addPrefix($prefix);
|
||||
if (!$trailingSlashOnRoot) {
|
||||
$rootPath = (new Route(trim(trim($prefix), '/').'/'))->getPath();
|
||||
foreach ($subCollection->all() as $route) {
|
||||
if ($route->getPath() === $rootPath) {
|
||||
$route->setPath(rtrim($rootPath, '/'));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($prefix as $locale => $localePrefix) {
|
||||
$prefix[$locale] = trim(trim($localePrefix), '/');
|
||||
}
|
||||
foreach ($subCollection->all() as $name => $route) {
|
||||
if (null === $locale = $route->getDefault('_locale')) {
|
||||
$subCollection->remove($name);
|
||||
foreach ($prefix as $locale => $localePrefix) {
|
||||
$localizedRoute = clone $route;
|
||||
$localizedRoute->setDefault('_locale', $locale);
|
||||
$localizedRoute->setDefault('_canonical_route', $name);
|
||||
$localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath()));
|
||||
$subCollection->add($name.'.'.$locale, $localizedRoute);
|
||||
}
|
||||
} elseif (!isset($prefix[$locale])) {
|
||||
throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix when imported in "%s".', $name, $locale, $file));
|
||||
} else {
|
||||
$route->setPath($prefix[$locale].(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath()));
|
||||
$subCollection->add($name, $route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $host) {
|
||||
$subCollection->setHost($host);
|
||||
}
|
||||
@@ -183,6 +220,10 @@ class YamlFileLoader extends FileLoader
|
||||
$subCollection->addRequirements($requirements);
|
||||
$subCollection->addOptions($options);
|
||||
|
||||
if (isset($config['name_prefix'])) {
|
||||
$subCollection->addNamePrefix($config['name_prefix']);
|
||||
}
|
||||
|
||||
$collection->addCollection($subCollection);
|
||||
}
|
||||
}
|
||||
|
@@ -24,6 +24,14 @@
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="localized-path">
|
||||
<xsd:simpleContent>
|
||||
<xsd:extension base="xsd:string">
|
||||
<xsd:attribute name="locale" type="xsd:string" use="required" />
|
||||
</xsd:extension>
|
||||
</xsd:simpleContent>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:group name="configs">
|
||||
<xsd:choice>
|
||||
<xsd:element name="default" nillable="true" type="default" />
|
||||
@@ -34,10 +42,12 @@
|
||||
</xsd:group>
|
||||
|
||||
<xsd:complexType name="route">
|
||||
<xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" />
|
||||
|
||||
<xsd:sequence>
|
||||
<xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:element name="path" type="localized-path" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id" type="xsd:string" use="required" />
|
||||
<xsd:attribute name="path" type="xsd:string" use="required" />
|
||||
<xsd:attribute name="path" type="xsd:string" />
|
||||
<xsd:attribute name="host" type="xsd:string" />
|
||||
<xsd:attribute name="schemes" type="xsd:string" />
|
||||
<xsd:attribute name="methods" type="xsd:string" />
|
||||
@@ -45,15 +55,19 @@
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="import">
|
||||
<xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" />
|
||||
|
||||
<xsd:sequence maxOccurs="unbounded" minOccurs="0">
|
||||
<xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:element name="prefix" type="localized-path" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="resource" type="xsd:string" use="required" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="prefix" type="xsd:string" />
|
||||
<xsd:attribute name="name-prefix" type="xsd:string" />
|
||||
<xsd:attribute name="host" type="xsd:string" />
|
||||
<xsd:attribute name="schemes" type="xsd:string" />
|
||||
<xsd:attribute name="methods" type="xsd:string" />
|
||||
<xsd:attribute name="controller" type="xsd:string" />
|
||||
<xsd:attribute name="trailing-slash-on-root" type="xsd:boolean" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="default" mixed="true">
|
||||
|
@@ -1,159 +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;
|
||||
|
||||
/**
|
||||
* Collection of routes.
|
||||
*
|
||||
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class DumperCollection implements \IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* @var DumperCollection|null
|
||||
*/
|
||||
private $parent;
|
||||
|
||||
/**
|
||||
* @var DumperCollection[]|DumperRoute[]
|
||||
*/
|
||||
private $children = array();
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $attributes = array();
|
||||
|
||||
/**
|
||||
* Returns the children routes and collections.
|
||||
*
|
||||
* @return self[]|DumperRoute[]
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
return $this->children;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a route or collection.
|
||||
*
|
||||
* @param DumperRoute|DumperCollection The route or collection
|
||||
*/
|
||||
public function add($child)
|
||||
{
|
||||
if ($child instanceof self) {
|
||||
$child->setParent($this);
|
||||
}
|
||||
$this->children[] = $child;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets children.
|
||||
*
|
||||
* @param array $children The children
|
||||
*/
|
||||
public function setAll(array $children)
|
||||
{
|
||||
foreach ($children as $child) {
|
||||
if ($child instanceof self) {
|
||||
$child->setParent($this);
|
||||
}
|
||||
}
|
||||
$this->children = $children;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the children.
|
||||
*
|
||||
* @return \Iterator|DumperCollection[]|DumperRoute[] The iterator
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->children);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root of the collection.
|
||||
*
|
||||
* @return self The root collection
|
||||
*/
|
||||
public function getRoot()
|
||||
{
|
||||
return (null !== $this->parent) ? $this->parent->getRoot() : $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent collection.
|
||||
*
|
||||
* @return self|null The parent collection or null if the collection has no parent
|
||||
*/
|
||||
protected function getParent()
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parent collection.
|
||||
*/
|
||||
protected function setParent(self $parent)
|
||||
{
|
||||
$this->parent = $parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the attribute is defined.
|
||||
*
|
||||
* @param string $name The attribute name
|
||||
*
|
||||
* @return bool true if the attribute is defined, false otherwise
|
||||
*/
|
||||
public function hasAttribute($name)
|
||||
{
|
||||
return array_key_exists($name, $this->attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an attribute by name.
|
||||
*
|
||||
* @param string $name The attribute name
|
||||
* @param mixed $default Default value is the attribute doesn't exist
|
||||
*
|
||||
* @return mixed The attribute value
|
||||
*/
|
||||
public function getAttribute($name, $default = null)
|
||||
{
|
||||
return $this->hasAttribute($name) ? $this->attributes[$name] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an attribute by name.
|
||||
*
|
||||
* @param string $name The attribute name
|
||||
* @param mixed $value The attribute value
|
||||
*/
|
||||
public function setAttribute($name, $value)
|
||||
{
|
||||
$this->attributes[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets multiple attributes.
|
||||
*
|
||||
* @param array $attributes The attributes
|
||||
*/
|
||||
public function setAttributes($attributes)
|
||||
{
|
||||
$this->attributes = $attributes;
|
||||
}
|
||||
}
|
@@ -1,57 +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;
|
||||
|
||||
/**
|
||||
* Container for a Route.
|
||||
*
|
||||
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class DumperRoute
|
||||
{
|
||||
private $name;
|
||||
private $route;
|
||||
|
||||
/**
|
||||
* @param string $name The route name
|
||||
* @param Route $route The route
|
||||
*/
|
||||
public function __construct($name, Route $route)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->route = $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the route name.
|
||||
*
|
||||
* @return string The route name
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the route.
|
||||
*
|
||||
* @return Route The route
|
||||
*/
|
||||
public function getRoute()
|
||||
{
|
||||
return $this->route;
|
||||
}
|
||||
}
|
@@ -13,6 +13,7 @@ namespace Symfony\Component\Routing\Matcher\Dumper;
|
||||
|
||||
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
|
||||
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
||||
use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
@@ -22,10 +23,12 @@ use Symfony\Component\Routing\RouteCollection;
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Tobias Schultze <http://tobion.de>
|
||||
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class PhpMatcherDumper extends MatcherDumper
|
||||
{
|
||||
private $expressionLanguage;
|
||||
private $signalingException;
|
||||
|
||||
/**
|
||||
* @var ExpressionFunctionProviderInterface[]
|
||||
@@ -53,7 +56,7 @@ class PhpMatcherDumper extends MatcherDumper
|
||||
|
||||
// trailing slash support is only enabled if we know how to redirect the user
|
||||
$interfaces = class_implements($options['base_class']);
|
||||
$supportsRedirections = isset($interfaces['Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcherInterface']);
|
||||
$supportsRedirections = isset($interfaces[RedirectableUrlMatcherInterface::class]);
|
||||
|
||||
return <<<EOF
|
||||
<?php
|
||||
@@ -86,70 +89,107 @@ EOF;
|
||||
|
||||
/**
|
||||
* Generates the code for the match method implementing UrlMatcherInterface.
|
||||
*
|
||||
* @param bool $supportsRedirections Whether redirections are supported by the base class
|
||||
*
|
||||
* @return string Match method as PHP code
|
||||
*/
|
||||
private function generateMatchMethod($supportsRedirections)
|
||||
private function generateMatchMethod(bool $supportsRedirections): string
|
||||
{
|
||||
$code = rtrim($this->compileRoutes($this->getRoutes(), $supportsRedirections), "\n");
|
||||
// Group hosts by same-suffix, re-order when possible
|
||||
$matchHost = false;
|
||||
$routes = new StaticPrefixCollection();
|
||||
foreach ($this->getRoutes()->all() as $name => $route) {
|
||||
if ($host = $route->getHost()) {
|
||||
$matchHost = true;
|
||||
$host = '/'.strtr(strrev($host), '}.{', '(/)');
|
||||
}
|
||||
|
||||
return <<<EOF
|
||||
public function match(\$rawPathinfo)
|
||||
$routes->addRoute($host ?: '/(.*)', array($name, $route));
|
||||
}
|
||||
$routes = $matchHost ? $routes->populateCollection(new RouteCollection()) : $this->getRoutes();
|
||||
|
||||
$code = rtrim($this->compileRoutes($routes, $matchHost), "\n");
|
||||
$fetchHost = $matchHost ? " \$host = strtolower(\$context->getHost());\n" : '';
|
||||
|
||||
$code = <<<EOF
|
||||
{
|
||||
\$allow = array();
|
||||
\$allow = \$allowSchemes = array();
|
||||
\$pathinfo = rawurldecode(\$rawPathinfo);
|
||||
\$trimmedPathinfo = rtrim(\$pathinfo, '/');
|
||||
\$context = \$this->context;
|
||||
\$request = \$this->request ?: \$this->createRequest(\$pathinfo);
|
||||
\$requestMethod = \$canonicalMethod = \$context->getMethod();
|
||||
|
||||
{$fetchHost}
|
||||
if ('HEAD' === \$requestMethod) {
|
||||
\$canonicalMethod = 'GET';
|
||||
}
|
||||
|
||||
$code
|
||||
|
||||
throw 0 < count(\$allow) ? new MethodNotAllowedException(array_unique(\$allow)) : new ResourceNotFoundException();
|
||||
}
|
||||
EOF;
|
||||
|
||||
if ($supportsRedirections) {
|
||||
return <<<'EOF'
|
||||
public function match($pathinfo)
|
||||
{
|
||||
$allow = $allowSchemes = array();
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $ret;
|
||||
}
|
||||
if ($allow) {
|
||||
throw new MethodNotAllowedException(array_keys($allow));
|
||||
}
|
||||
if (!in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
|
||||
// no-op
|
||||
} elseif ($allowSchemes) {
|
||||
redirect_scheme:
|
||||
$scheme = $this->context->getScheme();
|
||||
$this->context->setScheme(key($allowSchemes));
|
||||
try {
|
||||
if ($ret = $this->doMatch($pathinfo)) {
|
||||
return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret;
|
||||
}
|
||||
} finally {
|
||||
$this->context->setScheme($scheme);
|
||||
}
|
||||
} elseif ('/' !== $pathinfo) {
|
||||
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $this->redirect($pathinfo, $ret['_route']) + $ret;
|
||||
}
|
||||
if ($allowSchemes) {
|
||||
goto redirect_scheme;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ResourceNotFoundException();
|
||||
}
|
||||
|
||||
private function doMatch(string $rawPathinfo, array &$allow = array(), array &$allowSchemes = array()): ?array
|
||||
|
||||
EOF
|
||||
.$code."\n return null;\n }";
|
||||
}
|
||||
|
||||
return " public function match(\$rawPathinfo)\n".$code."\n throw \$allow ? new MethodNotAllowedException(array_keys(\$allow)) : new ResourceNotFoundException();\n }";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates PHP code to match a RouteCollection with all its routes.
|
||||
*
|
||||
* @param RouteCollection $routes A RouteCollection instance
|
||||
* @param bool $supportsRedirections Whether redirections are supported by the base class
|
||||
*
|
||||
* @return string PHP code
|
||||
*/
|
||||
private function compileRoutes(RouteCollection $routes, $supportsRedirections)
|
||||
private function compileRoutes(RouteCollection $routes, bool $matchHost): string
|
||||
{
|
||||
$fetchedHost = false;
|
||||
$groups = $this->groupRoutesByHostRegex($routes);
|
||||
$code = '';
|
||||
list($staticRoutes, $dynamicRoutes) = $this->groupStaticRoutes($routes);
|
||||
|
||||
foreach ($groups as $collection) {
|
||||
if (null !== $regex = $collection->getAttribute('host_regex')) {
|
||||
if (!$fetchedHost) {
|
||||
$code .= " \$host = \$context->getHost();\n\n";
|
||||
$fetchedHost = true;
|
||||
$code = $this->compileStaticRoutes($staticRoutes, $matchHost);
|
||||
$chunkLimit = \count($dynamicRoutes);
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
$this->signalingException = new \RuntimeException('preg_match(): Compilation failed: regular expression is too large');
|
||||
$code .= $this->compileDynamicRoutes($dynamicRoutes, $matchHost, $chunkLimit);
|
||||
break;
|
||||
} catch (\Exception $e) {
|
||||
if (1 < $chunkLimit && $this->signalingException === $e) {
|
||||
$chunkLimit = 1 + ($chunkLimit >> 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
$code .= sprintf(" if (preg_match(%s, \$host, \$hostMatches)) {\n", var_export($regex, true));
|
||||
}
|
||||
|
||||
$tree = $this->buildStaticPrefixCollection($collection);
|
||||
$groupCode = $this->compileStaticPrefixRoutes($tree, $supportsRedirections);
|
||||
|
||||
if (null !== $regex) {
|
||||
// apply extra indention at each line (except empty ones)
|
||||
$groupCode = preg_replace('/^.{2,}$/m', ' $0', $groupCode);
|
||||
$code .= $groupCode;
|
||||
$code .= " }\n\n";
|
||||
} else {
|
||||
$code .= $groupCode;
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,55 +201,383 @@ EOF;
|
||||
return $code;
|
||||
}
|
||||
|
||||
private function buildStaticPrefixCollection(DumperCollection $collection)
|
||||
{
|
||||
$prefixCollection = new StaticPrefixCollection();
|
||||
|
||||
foreach ($collection as $dumperRoute) {
|
||||
$prefix = $dumperRoute->getRoute()->compile()->getStaticPrefix();
|
||||
$prefixCollection->addRoute($prefix, $dumperRoute);
|
||||
}
|
||||
|
||||
$prefixCollection->optimizeGroups();
|
||||
|
||||
return $prefixCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates PHP code to match a tree of routes.
|
||||
*
|
||||
* @param StaticPrefixCollection $collection A StaticPrefixCollection instance
|
||||
* @param bool $supportsRedirections Whether redirections are supported by the base class
|
||||
* @param string $ifOrElseIf either "if" or "elseif" to influence chaining
|
||||
*
|
||||
* @return string PHP code
|
||||
* Splits static routes from dynamic routes, so that they can be matched first, using a simple switch.
|
||||
*/
|
||||
private function compileStaticPrefixRoutes(StaticPrefixCollection $collection, $supportsRedirections, $ifOrElseIf = 'if')
|
||||
private function groupStaticRoutes(RouteCollection $collection): array
|
||||
{
|
||||
$code = '';
|
||||
$prefix = $collection->getPrefix();
|
||||
$staticRoutes = $dynamicRegex = array();
|
||||
$dynamicRoutes = new RouteCollection();
|
||||
|
||||
if (!empty($prefix) && '/' !== $prefix) {
|
||||
$code .= sprintf(" %s (0 === strpos(\$pathinfo, %s)) {\n", $ifOrElseIf, var_export($prefix, true));
|
||||
}
|
||||
foreach ($collection->all() as $name => $route) {
|
||||
$compiledRoute = $route->compile();
|
||||
$hostRegex = $compiledRoute->getHostRegex();
|
||||
$regex = $compiledRoute->getRegex();
|
||||
if (!$compiledRoute->getPathVariables()) {
|
||||
$host = !$compiledRoute->getHostVariables() ? $route->getHost() : '';
|
||||
$url = $route->getPath();
|
||||
foreach ($dynamicRegex as list($hostRx, $rx)) {
|
||||
if (preg_match($rx, $url) && (!$host || !$hostRx || preg_match($hostRx, $host))) {
|
||||
$dynamicRegex[] = array($hostRegex, $regex);
|
||||
$dynamicRoutes->add($name, $route);
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
$ifOrElseIf = 'if';
|
||||
|
||||
foreach ($collection->getItems() as $route) {
|
||||
if ($route instanceof StaticPrefixCollection) {
|
||||
$code .= $this->compileStaticPrefixRoutes($route, $supportsRedirections, $ifOrElseIf);
|
||||
$ifOrElseIf = 'elseif';
|
||||
$staticRoutes[$url][$name] = $route;
|
||||
} else {
|
||||
$code .= $this->compileRoute($route[1]->getRoute(), $route[1]->getName(), $supportsRedirections, $prefix)."\n";
|
||||
$ifOrElseIf = 'if';
|
||||
$dynamicRegex[] = array($hostRegex, $regex);
|
||||
$dynamicRoutes->add($name, $route);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($prefix) && '/' !== $prefix) {
|
||||
$code .= " }\n\n";
|
||||
// apply extra indention at each line (except empty ones)
|
||||
$code = preg_replace('/^.{2,}$/m', ' $0', $code);
|
||||
return array($staticRoutes, $dynamicRoutes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles static routes in a switch statement.
|
||||
*
|
||||
* Condition-less paths are put in a static array in the switch's default, with generic matching logic.
|
||||
* Paths that can match two or more routes, or have user-specified conditions are put in separate switch's cases.
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
private function compileStaticRoutes(array $staticRoutes, bool $matchHost): string
|
||||
{
|
||||
if (!$staticRoutes) {
|
||||
return '';
|
||||
}
|
||||
$code = $default = '';
|
||||
|
||||
foreach ($staticRoutes as $url => $routes) {
|
||||
if (1 === \count($routes)) {
|
||||
foreach ($routes as $name => $route) {
|
||||
}
|
||||
|
||||
if (!$route->getCondition()) {
|
||||
$defaults = $route->getDefaults();
|
||||
if (isset($defaults['_canonical_route'])) {
|
||||
$name = $defaults['_canonical_route'];
|
||||
unset($defaults['_canonical_route']);
|
||||
}
|
||||
$default .= sprintf(
|
||||
"%s => array(%s, %s, %s, %s),\n",
|
||||
self::export($url),
|
||||
self::export(array('_route' => $name) + $defaults),
|
||||
self::export(!$route->compile()->getHostVariables() ? $route->getHost() : $route->compile()->getHostRegex() ?: null),
|
||||
self::export(array_flip($route->getMethods()) ?: null),
|
||||
self::export(array_flip($route->getSchemes()) ?: null)
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$code .= sprintf(" case %s:\n", self::export($url));
|
||||
foreach ($routes as $name => $route) {
|
||||
$code .= $this->compileRoute($route, $name, true);
|
||||
}
|
||||
$code .= " break;\n";
|
||||
}
|
||||
|
||||
if ($default) {
|
||||
$code .= <<<EOF
|
||||
default:
|
||||
\$routes = array(
|
||||
{$this->indent($default, 4)} );
|
||||
|
||||
if (!isset(\$routes[\$pathinfo])) {
|
||||
break;
|
||||
}
|
||||
list(\$ret, \$requiredHost, \$requiredMethods, \$requiredSchemes) = \$routes[\$pathinfo];
|
||||
{$this->compileSwitchDefault(false, $matchHost)}
|
||||
EOF;
|
||||
}
|
||||
|
||||
return sprintf(" switch (\$pathinfo) {\n%s }\n\n", $this->indent($code));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles a regular expression followed by a switch statement to match dynamic routes.
|
||||
*
|
||||
* The regular expression matches both the host and the pathinfo at the same time. For stellar performance,
|
||||
* it is built as a tree of patterns, with re-ordering logic to group same-prefix routes together when possible.
|
||||
*
|
||||
* Patterns are named so that we know which one matched (https://pcre.org/current/doc/html/pcre2syntax.html#SEC23).
|
||||
* This name is used to "switch" to the additional logic required to match the final route.
|
||||
*
|
||||
* Condition-less paths are put in a static array in the switch's default, with generic matching logic.
|
||||
* Paths that can match two or more routes, or have user-specified conditions are put in separate switch's cases.
|
||||
*
|
||||
* Last but not least:
|
||||
* - Because it is not possibe to mix unicode/non-unicode patterns in a single regexp, several of them can be generated.
|
||||
* - The same regexp can be used several times when the logic in the switch rejects the match. When this happens, the
|
||||
* matching-but-failing subpattern is blacklisted by replacing its name by "(*F)", which forces a failure-to-match.
|
||||
* To ease this backlisting operation, the name of subpatterns is also the string offset where the replacement should occur.
|
||||
*/
|
||||
private function compileDynamicRoutes(RouteCollection $collection, bool $matchHost, int $chunkLimit): string
|
||||
{
|
||||
if (!$collection->all()) {
|
||||
return '';
|
||||
}
|
||||
$code = '';
|
||||
$state = (object) array(
|
||||
'regex' => '',
|
||||
'switch' => '',
|
||||
'default' => '',
|
||||
'mark' => 0,
|
||||
'markTail' => 0,
|
||||
'hostVars' => array(),
|
||||
'vars' => array(),
|
||||
);
|
||||
$state->getVars = static function ($m) use ($state) {
|
||||
if ('_route' === $m[1]) {
|
||||
return '?:';
|
||||
}
|
||||
|
||||
$state->vars[] = $m[1];
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
$chunkSize = 0;
|
||||
$prev = null;
|
||||
$perModifiers = array();
|
||||
foreach ($collection->all() as $name => $route) {
|
||||
preg_match('#[a-zA-Z]*$#', $route->compile()->getRegex(), $rx);
|
||||
if ($chunkLimit < ++$chunkSize || $prev !== $rx[0] && $route->compile()->getPathVariables()) {
|
||||
$chunkSize = 1;
|
||||
$routes = new RouteCollection();
|
||||
$perModifiers[] = array($rx[0], $routes);
|
||||
$prev = $rx[0];
|
||||
}
|
||||
$routes->add($name, $route);
|
||||
}
|
||||
|
||||
foreach ($perModifiers as list($modifiers, $routes)) {
|
||||
$prev = false;
|
||||
$perHost = array();
|
||||
foreach ($routes->all() as $name => $route) {
|
||||
$regex = $route->compile()->getHostRegex();
|
||||
if ($prev !== $regex) {
|
||||
$routes = new RouteCollection();
|
||||
$perHost[] = array($regex, $routes);
|
||||
$prev = $regex;
|
||||
}
|
||||
$routes->add($name, $route);
|
||||
}
|
||||
$prev = false;
|
||||
$rx = '{^(?';
|
||||
$code .= "\n {$state->mark} => ".self::export($rx);
|
||||
$state->mark += \strlen($rx);
|
||||
$state->regex = $rx;
|
||||
|
||||
foreach ($perHost as list($hostRegex, $routes)) {
|
||||
if ($matchHost) {
|
||||
if ($hostRegex) {
|
||||
preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $hostRegex, $rx);
|
||||
$state->vars = array();
|
||||
$hostRegex = '(?i:'.preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]).')\.';
|
||||
$state->hostVars = $state->vars;
|
||||
} else {
|
||||
$hostRegex = '(?:(?:[^./]*+\.)++)';
|
||||
$state->hostVars = array();
|
||||
}
|
||||
$state->mark += \strlen($rx = ($prev ? ')' : '')."|{$hostRegex}(?");
|
||||
$code .= "\n .".self::export($rx);
|
||||
$state->regex .= $rx;
|
||||
$prev = true;
|
||||
}
|
||||
|
||||
$tree = new StaticPrefixCollection();
|
||||
foreach ($routes->all() as $name => $route) {
|
||||
preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $route->compile()->getRegex(), $rx);
|
||||
|
||||
$state->vars = array();
|
||||
$regex = preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]);
|
||||
$tree->addRoute($regex, array($name, $regex, $state->vars, $route));
|
||||
}
|
||||
|
||||
$code .= $this->compileStaticPrefixCollection($tree, $state);
|
||||
}
|
||||
if ($matchHost) {
|
||||
$code .= "\n .')'";
|
||||
$state->regex .= ')';
|
||||
}
|
||||
$rx = ")$}{$modifiers}";
|
||||
$code .= "\n .'{$rx}',";
|
||||
$state->regex .= $rx;
|
||||
$state->markTail = 0;
|
||||
|
||||
// if the regex is too large, throw a signaling exception to recompute with smaller chunk size
|
||||
set_error_handler(function ($type, $message) { throw 0 === strpos($message, $this->signalingException->getMessage()) ? $this->signalingException : new \ErrorException($message); });
|
||||
try {
|
||||
preg_match($state->regex, '');
|
||||
} finally {
|
||||
restore_error_handler();
|
||||
}
|
||||
}
|
||||
|
||||
if ($state->default) {
|
||||
$state->switch .= <<<EOF
|
||||
default:
|
||||
\$routes = array(
|
||||
{$this->indent($state->default, 4)} );
|
||||
|
||||
list(\$ret, \$vars, \$requiredMethods, \$requiredSchemes) = \$routes[\$m];
|
||||
{$this->compileSwitchDefault(true, $matchHost)}
|
||||
EOF;
|
||||
}
|
||||
|
||||
$matchedPathinfo = $matchHost ? '$host.\'.\'.$pathinfo' : '$pathinfo';
|
||||
unset($state->getVars);
|
||||
|
||||
return <<<EOF
|
||||
\$matchedPathinfo = {$matchedPathinfo};
|
||||
\$regexList = array({$code}
|
||||
);
|
||||
|
||||
foreach (\$regexList as \$offset => \$regex) {
|
||||
while (preg_match(\$regex, \$matchedPathinfo, \$matches)) {
|
||||
switch (\$m = (int) \$matches['MARK']) {
|
||||
{$this->indent($state->switch, 3)} }
|
||||
|
||||
if ({$state->mark} === \$m) {
|
||||
break;
|
||||
}
|
||||
\$regex = substr_replace(\$regex, 'F', \$m - \$offset, 1 + strlen(\$m));
|
||||
\$offset += strlen(\$m);
|
||||
}
|
||||
}
|
||||
|
||||
EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles a regexp tree of subpatterns that matches nested same-prefix routes.
|
||||
*
|
||||
* @param \stdClass $state A simple state object that keeps track of the progress of the compilation,
|
||||
* and gathers the generated switch's "case" and "default" statements
|
||||
*/
|
||||
private function compileStaticPrefixCollection(StaticPrefixCollection $tree, \stdClass $state, int $prefixLen = 0): string
|
||||
{
|
||||
$code = '';
|
||||
$prevRegex = null;
|
||||
$routes = $tree->getRoutes();
|
||||
|
||||
foreach ($routes as $i => $route) {
|
||||
if ($route instanceof StaticPrefixCollection) {
|
||||
$prevRegex = null;
|
||||
$prefix = substr($route->getPrefix(), $prefixLen);
|
||||
$state->mark += \strlen($rx = "|{$prefix}(?");
|
||||
$code .= "\n .".self::export($rx);
|
||||
$state->regex .= $rx;
|
||||
$code .= $this->indent($this->compileStaticPrefixCollection($route, $state, $prefixLen + \strlen($prefix)));
|
||||
$code .= "\n .')'";
|
||||
$state->regex .= ')';
|
||||
++$state->markTail;
|
||||
continue;
|
||||
}
|
||||
|
||||
list($name, $regex, $vars, $route) = $route;
|
||||
$compiledRoute = $route->compile();
|
||||
|
||||
if ($compiledRoute->getRegex() === $prevRegex) {
|
||||
$state->switch = substr_replace($state->switch, $this->compileRoute($route, $name, false)."\n", -19, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
$state->mark += 3 + $state->markTail + \strlen($regex) - $prefixLen;
|
||||
$state->markTail = 2 + \strlen($state->mark);
|
||||
$rx = sprintf('|%s(*:%s)', substr($regex, $prefixLen), $state->mark);
|
||||
$code .= "\n .".self::export($rx);
|
||||
$state->regex .= $rx;
|
||||
$vars = array_merge($state->hostVars, $vars);
|
||||
|
||||
if (!$route->getCondition() && (!\is_array($next = $routes[1 + $i] ?? null) || $regex !== $next[1])) {
|
||||
$prevRegex = null;
|
||||
$defaults = $route->getDefaults();
|
||||
if (isset($defaults['_canonical_route'])) {
|
||||
$name = $defaults['_canonical_route'];
|
||||
unset($defaults['_canonical_route']);
|
||||
}
|
||||
$state->default .= sprintf(
|
||||
"%s => array(%s, %s, %s, %s),\n",
|
||||
$state->mark,
|
||||
self::export(array('_route' => $name) + $defaults),
|
||||
self::export($vars),
|
||||
self::export(array_flip($route->getMethods()) ?: null),
|
||||
self::export(array_flip($route->getSchemes()) ?: null)
|
||||
);
|
||||
} else {
|
||||
$prevRegex = $compiledRoute->getRegex();
|
||||
$combine = ' $matches = array(';
|
||||
foreach ($vars as $j => $m) {
|
||||
$combine .= sprintf('%s => $matches[%d] ?? null, ', self::export($m), 1 + $j);
|
||||
}
|
||||
$combine = $vars ? substr_replace($combine, ");\n\n", -2) : '';
|
||||
|
||||
$state->switch .= <<<EOF
|
||||
case {$state->mark}:
|
||||
{$combine}{$this->compileRoute($route, $name, false)}
|
||||
break;
|
||||
|
||||
EOF;
|
||||
}
|
||||
}
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple helper to compiles the switch's "default" for both static and dynamic routes.
|
||||
*/
|
||||
private function compileSwitchDefault(bool $hasVars, bool $matchHost): string
|
||||
{
|
||||
if ($hasVars) {
|
||||
$code = <<<EOF
|
||||
|
||||
foreach (\$vars as \$i => \$v) {
|
||||
if (isset(\$matches[1 + \$i])) {
|
||||
\$ret[\$v] = \$matches[1 + \$i];
|
||||
}
|
||||
}
|
||||
|
||||
EOF;
|
||||
} elseif ($matchHost) {
|
||||
$code = <<<EOF
|
||||
|
||||
if (\$requiredHost) {
|
||||
if ('#' !== \$requiredHost[0] ? \$requiredHost !== \$host : !preg_match(\$requiredHost, \$host, \$hostMatches)) {
|
||||
break;
|
||||
}
|
||||
if ('#' === \$requiredHost[0] && \$hostMatches) {
|
||||
\$hostMatches['_route'] = \$ret['_route'];
|
||||
\$ret = \$this->mergeDefaults(\$hostMatches, \$ret);
|
||||
}
|
||||
}
|
||||
|
||||
EOF;
|
||||
} else {
|
||||
$code = '';
|
||||
}
|
||||
|
||||
$code .= <<<EOF
|
||||
|
||||
\$hasRequiredScheme = !\$requiredSchemes || isset(\$requiredSchemes[\$context->getScheme()]);
|
||||
if (\$requiredMethods && !isset(\$requiredMethods[\$canonicalMethod]) && !isset(\$requiredMethods[\$requestMethod])) {
|
||||
if (\$hasRequiredScheme) {
|
||||
\$allow += \$requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!\$hasRequiredScheme) {
|
||||
\$allowSchemes += \$requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return \$ret;
|
||||
|
||||
EOF;
|
||||
|
||||
return $code;
|
||||
}
|
||||
@@ -217,132 +585,97 @@ EOF;
|
||||
/**
|
||||
* Compiles a single Route to PHP code used to match it against the path info.
|
||||
*
|
||||
* @param Route $route A Route instance
|
||||
* @param string $name The name of the Route
|
||||
* @param bool $supportsRedirections Whether redirections are supported by the base class
|
||||
* @param string|null $parentPrefix The prefix of the parent collection used to optimize the code
|
||||
*
|
||||
* @return string PHP code
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
private function compileRoute(Route $route, $name, $supportsRedirections, $parentPrefix = null)
|
||||
private function compileRoute(Route $route, string $name, bool $checkHost): string
|
||||
{
|
||||
$code = '';
|
||||
$compiledRoute = $route->compile();
|
||||
$conditions = array();
|
||||
$hasTrailingSlash = false;
|
||||
$matches = false;
|
||||
$hostMatches = false;
|
||||
$methods = $route->getMethods();
|
||||
|
||||
$supportsTrailingSlash = $supportsRedirections && (!$methods || \in_array('GET', $methods));
|
||||
$regex = $compiledRoute->getRegex();
|
||||
|
||||
if (!\count($compiledRoute->getPathVariables()) && false !== preg_match('#^(.)\^(?P<url>.*?)\$\1#'.('u' === substr($regex, -1) ? 'u' : ''), $regex, $m)) {
|
||||
if ($supportsTrailingSlash && '/' === substr($m['url'], -1)) {
|
||||
$conditions[] = sprintf('%s === $trimmedPathinfo', var_export(rtrim(str_replace('\\', '', $m['url']), '/'), true));
|
||||
$hasTrailingSlash = true;
|
||||
} else {
|
||||
$conditions[] = sprintf('%s === $pathinfo', var_export(str_replace('\\', '', $m['url']), true));
|
||||
}
|
||||
} else {
|
||||
if ($compiledRoute->getStaticPrefix() && $compiledRoute->getStaticPrefix() !== $parentPrefix) {
|
||||
$conditions[] = sprintf('0 === strpos($pathinfo, %s)', var_export($compiledRoute->getStaticPrefix(), true));
|
||||
}
|
||||
|
||||
if ($supportsTrailingSlash && $pos = strpos($regex, '/$')) {
|
||||
$regex = substr($regex, 0, $pos).'/?$'.substr($regex, $pos + 2);
|
||||
$hasTrailingSlash = true;
|
||||
}
|
||||
$conditions[] = sprintf('preg_match(%s, $pathinfo, $matches)', var_export($regex, true));
|
||||
|
||||
$matches = true;
|
||||
}
|
||||
|
||||
if ($compiledRoute->getHostVariables()) {
|
||||
$hostMatches = true;
|
||||
}
|
||||
$matches = (bool) $compiledRoute->getPathVariables();
|
||||
$hostMatches = (bool) $compiledRoute->getHostVariables();
|
||||
$methods = array_flip($route->getMethods());
|
||||
|
||||
if ($route->getCondition()) {
|
||||
$conditions[] = $this->getExpressionLanguage()->compile($route->getCondition(), array('context', 'request'));
|
||||
$expression = $this->getExpressionLanguage()->compile($route->getCondition(), array('context', 'request'));
|
||||
|
||||
if (false !== strpos($expression, '$request')) {
|
||||
$conditions[] = '($request = $request ?? $this->request ?: $this->createRequest($pathinfo))';
|
||||
}
|
||||
$conditions[] = $expression;
|
||||
}
|
||||
|
||||
if (!$checkHost || !$compiledRoute->getHostRegex()) {
|
||||
// no-op
|
||||
} elseif ($hostMatches) {
|
||||
$conditions[] = sprintf('preg_match(%s, $host, $hostMatches)', self::export($compiledRoute->getHostRegex()));
|
||||
} else {
|
||||
$conditions[] = sprintf('%s === $host', self::export($route->getHost()));
|
||||
}
|
||||
|
||||
$conditions = implode(' && ', $conditions);
|
||||
|
||||
$code .= <<<EOF
|
||||
if ($conditions) {
|
||||
$code .= <<<EOF
|
||||
// $name
|
||||
if ($conditions) {
|
||||
|
||||
EOF;
|
||||
} else {
|
||||
$code .= " // {$name}\n";
|
||||
}
|
||||
|
||||
$gotoname = 'not_'.preg_replace('/[^A-Za-z0-9_]/', '', $name);
|
||||
|
||||
// the offset where the return value is appended below, with indendation
|
||||
$retOffset = 12 + \strlen($code);
|
||||
$defaults = $route->getDefaults();
|
||||
if (isset($defaults['_canonical_route'])) {
|
||||
$name = $defaults['_canonical_route'];
|
||||
unset($defaults['_canonical_route']);
|
||||
}
|
||||
|
||||
// optimize parameters array
|
||||
if ($matches || $hostMatches) {
|
||||
$vars = array();
|
||||
if ($hostMatches) {
|
||||
$vars[] = '$hostMatches';
|
||||
}
|
||||
if ($matches) {
|
||||
$vars = array("array('_route' => '$name')");
|
||||
if ($matches || ($hostMatches && !$checkHost)) {
|
||||
$vars[] = '$matches';
|
||||
}
|
||||
$vars[] = "array('_route' => '$name')";
|
||||
if ($hostMatches && $checkHost) {
|
||||
$vars[] = '$hostMatches';
|
||||
}
|
||||
|
||||
$code .= sprintf(
|
||||
" \$ret = \$this->mergeDefaults(array_replace(%s), %s);\n",
|
||||
implode(', ', $vars),
|
||||
str_replace("\n", '', var_export($route->getDefaults(), true))
|
||||
" \$ret = \$this->mergeDefaults(%s, %s);\n",
|
||||
implode(' + ', $vars),
|
||||
self::export($defaults)
|
||||
);
|
||||
} elseif ($route->getDefaults()) {
|
||||
$code .= sprintf(" \$ret = %s;\n", str_replace("\n", '', var_export(array_replace($route->getDefaults(), array('_route' => $name)), true)));
|
||||
} elseif ($defaults) {
|
||||
$code .= sprintf(" \$ret = %s;\n", self::export(array('_route' => $name) + $defaults));
|
||||
} else {
|
||||
$code .= sprintf(" \$ret = array('_route' => '%s');\n", $name);
|
||||
}
|
||||
|
||||
if ($hasTrailingSlash) {
|
||||
$code .= <<<EOF
|
||||
if ('/' === substr(\$pathinfo, -1)) {
|
||||
// no-op
|
||||
} elseif ('GET' !== \$canonicalMethod) {
|
||||
goto $gotoname;
|
||||
} else {
|
||||
return array_replace(\$ret, \$this->redirect(\$rawPathinfo.'/', '$name'));
|
||||
}
|
||||
|
||||
|
||||
EOF;
|
||||
}
|
||||
|
||||
if ($methods) {
|
||||
$methodVariable = \in_array('GET', $methods) ? '$canonicalMethod' : '$requestMethod';
|
||||
$methods = implode("', '", $methods);
|
||||
$methodVariable = isset($methods['GET']) ? '$canonicalMethod' : '$requestMethod';
|
||||
$methods = self::export($methods);
|
||||
}
|
||||
|
||||
if ($schemes = $route->getSchemes()) {
|
||||
if (!$supportsRedirections) {
|
||||
throw new \LogicException('The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.');
|
||||
}
|
||||
$schemes = str_replace("\n", '', var_export(array_flip($schemes), true));
|
||||
$schemes = self::export(array_flip($schemes));
|
||||
if ($methods) {
|
||||
$code .= <<<EOF
|
||||
\$requiredSchemes = $schemes;
|
||||
\$hasRequiredScheme = isset(\$requiredSchemes[\$context->getScheme()]);
|
||||
if (!in_array($methodVariable, array('$methods'))) {
|
||||
if (!isset((\$a = {$methods})[{$methodVariable}])) {
|
||||
if (\$hasRequiredScheme) {
|
||||
\$allow = array_merge(\$allow, array('$methods'));
|
||||
\$allow += \$a;
|
||||
}
|
||||
goto $gotoname;
|
||||
}
|
||||
if (!\$hasRequiredScheme) {
|
||||
if ('GET' !== \$canonicalMethod) {
|
||||
goto $gotoname;
|
||||
}
|
||||
|
||||
return array_replace(\$ret, \$this->redirect(\$rawPathinfo, '$name', key(\$requiredSchemes)));
|
||||
\$allowSchemes += \$requiredSchemes;
|
||||
goto $gotoname;
|
||||
}
|
||||
|
||||
|
||||
@@ -351,11 +684,8 @@ EOF;
|
||||
$code .= <<<EOF
|
||||
\$requiredSchemes = $schemes;
|
||||
if (!isset(\$requiredSchemes[\$context->getScheme()])) {
|
||||
if ('GET' !== \$canonicalMethod) {
|
||||
goto $gotoname;
|
||||
}
|
||||
|
||||
return array_replace(\$ret, \$this->redirect(\$rawPathinfo, '$name', key(\$requiredSchemes)));
|
||||
\$allowSchemes += \$requiredSchemes;
|
||||
goto $gotoname;
|
||||
}
|
||||
|
||||
|
||||
@@ -363,8 +693,8 @@ EOF;
|
||||
}
|
||||
} elseif ($methods) {
|
||||
$code .= <<<EOF
|
||||
if (!in_array($methodVariable, array('$methods'))) {
|
||||
\$allow = array_merge(\$allow, array('$methods'));
|
||||
if (!isset((\$a = {$methods})[{$methodVariable}])) {
|
||||
\$allow += \$a;
|
||||
goto $gotoname;
|
||||
}
|
||||
|
||||
@@ -372,47 +702,22 @@ EOF;
|
||||
EOF;
|
||||
}
|
||||
|
||||
if ($hasTrailingSlash || $schemes || $methods) {
|
||||
if ($schemes || $methods) {
|
||||
$code .= " return \$ret;\n";
|
||||
} else {
|
||||
$code = substr_replace($code, 'return', $retOffset, 6);
|
||||
}
|
||||
$code .= " }\n";
|
||||
if ($conditions) {
|
||||
$code .= " }\n";
|
||||
} elseif ($schemes || $methods) {
|
||||
$code .= ' ';
|
||||
}
|
||||
|
||||
if ($hasTrailingSlash || $schemes || $methods) {
|
||||
if ($schemes || $methods) {
|
||||
$code .= " $gotoname:\n";
|
||||
}
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Groups consecutive routes having the same host regex.
|
||||
*
|
||||
* The result is a collection of collections of routes having the same host regex.
|
||||
*
|
||||
* @param RouteCollection $routes A flat RouteCollection
|
||||
*
|
||||
* @return DumperCollection A collection with routes grouped by host regex in sub-collections
|
||||
*/
|
||||
private function groupRoutesByHostRegex(RouteCollection $routes)
|
||||
{
|
||||
$groups = new DumperCollection();
|
||||
$currentGroup = new DumperCollection();
|
||||
$currentGroup->setAttribute('host_regex', null);
|
||||
$groups->add($currentGroup);
|
||||
|
||||
foreach ($routes as $name => $route) {
|
||||
$hostRegex = $route->compile()->getHostRegex();
|
||||
if ($currentGroup->getAttribute('host_regex') !== $hostRegex) {
|
||||
$currentGroup = new DumperCollection();
|
||||
$currentGroup->setAttribute('host_regex', $hostRegex);
|
||||
$groups->add($currentGroup);
|
||||
}
|
||||
$currentGroup->add(new DumperRoute($name, $route));
|
||||
}
|
||||
|
||||
return $groups;
|
||||
return $conditions ? $this->indent($code) : $code;
|
||||
}
|
||||
|
||||
private function getExpressionLanguage()
|
||||
@@ -426,4 +731,48 @@ EOF;
|
||||
|
||||
return $this->expressionLanguage;
|
||||
}
|
||||
|
||||
private function indent($code, $level = 1)
|
||||
{
|
||||
return preg_replace('/^./m', str_repeat(' ', $level).'$0', $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public static function export($value): string
|
||||
{
|
||||
if (null === $value) {
|
||||
return 'null';
|
||||
}
|
||||
if (!\is_array($value)) {
|
||||
if (\is_object($value)) {
|
||||
throw new \InvalidArgumentException('Symfony\Component\Routing\Route cannot contain objects.');
|
||||
}
|
||||
|
||||
return str_replace("\n", '\'."\n".\'', var_export($value, true));
|
||||
}
|
||||
if (!$value) {
|
||||
return 'array()';
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
$export = 'array(';
|
||||
|
||||
foreach ($value as $k => $v) {
|
||||
if ($i === $k) {
|
||||
++$i;
|
||||
} else {
|
||||
$export .= self::export($k).' => ';
|
||||
|
||||
if (\is_int($k) && $i < $k) {
|
||||
$i = 1 + $k;
|
||||
}
|
||||
}
|
||||
|
||||
$export .= self::export($v).', ';
|
||||
}
|
||||
|
||||
return substr_replace($export, ')', -2);
|
||||
}
|
||||
}
|
||||
|
@@ -11,44 +11,49 @@
|
||||
|
||||
namespace Symfony\Component\Routing\Matcher\Dumper;
|
||||
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
/**
|
||||
* Prefix tree of routes preserving routes order.
|
||||
*
|
||||
* @author Frank de Jonge <info@frankdejonge.nl>
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class StaticPrefixCollection
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $prefix;
|
||||
|
||||
/**
|
||||
* @var array[]|StaticPrefixCollection[]
|
||||
* @var string[]
|
||||
*/
|
||||
private $staticPrefixes = array();
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $prefixes = array();
|
||||
|
||||
/**
|
||||
* @var array[]|self[]
|
||||
*/
|
||||
private $items = array();
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $matchStart = 0;
|
||||
|
||||
public function __construct($prefix = '')
|
||||
public function __construct(string $prefix = '/')
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
}
|
||||
|
||||
public function getPrefix()
|
||||
public function getPrefix(): string
|
||||
{
|
||||
return $this->prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]|StaticPrefixCollection[]
|
||||
* @return array[]|self[]
|
||||
*/
|
||||
public function getItems()
|
||||
public function getRoutes(): array
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
@@ -56,183 +61,142 @@ class StaticPrefixCollection
|
||||
/**
|
||||
* Adds a route to a group.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param mixed $route
|
||||
* @param array|self $route
|
||||
*/
|
||||
public function addRoute($prefix, $route)
|
||||
public function addRoute(string $prefix, $route)
|
||||
{
|
||||
$prefix = '/' === $prefix ? $prefix : rtrim($prefix, '/');
|
||||
$this->guardAgainstAddingNotAcceptedRoutes($prefix);
|
||||
list($prefix, $staticPrefix) = $this->getCommonPrefix($prefix, $prefix);
|
||||
|
||||
if ($this->prefix === $prefix) {
|
||||
// When a prefix is exactly the same as the base we move up the match start position.
|
||||
// This is needed because otherwise routes that come afterwards have higher precedence
|
||||
// than a possible regular expression, which goes against the input order sorting.
|
||||
$this->items[] = array($prefix, $route);
|
||||
$this->matchStart = \count($this->items);
|
||||
for ($i = \count($this->items) - 1; 0 <= $i; --$i) {
|
||||
$item = $this->items[$i];
|
||||
|
||||
return;
|
||||
}
|
||||
list($commonPrefix, $commonStaticPrefix) = $this->getCommonPrefix($prefix, $this->prefixes[$i]);
|
||||
|
||||
if ($this->prefix === $commonPrefix) {
|
||||
// the new route and a previous one have no common prefix, let's see if they are exclusive to each others
|
||||
|
||||
if ($this->prefix !== $staticPrefix && $this->prefix !== $this->staticPrefixes[$i]) {
|
||||
// the new route and the previous one have exclusive static prefixes
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->prefix === $staticPrefix && $this->prefix === $this->staticPrefixes[$i]) {
|
||||
// the new route and the previous one have no static prefix
|
||||
break;
|
||||
}
|
||||
|
||||
if ($this->prefixes[$i] !== $this->staticPrefixes[$i] && $this->prefix === $this->staticPrefixes[$i]) {
|
||||
// the previous route is non-static and has no static prefix
|
||||
break;
|
||||
}
|
||||
|
||||
if ($prefix !== $staticPrefix && $this->prefix === $staticPrefix) {
|
||||
// the new route is non-static and has no static prefix
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($this->items as $i => $item) {
|
||||
if ($i < $this->matchStart) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($item instanceof self && $item->accepts($prefix)) {
|
||||
if ($item instanceof self && $this->prefixes[$i] === $commonPrefix) {
|
||||
// the new route is a child of a previous one, let's nest it
|
||||
$item->addRoute($prefix, $route);
|
||||
} else {
|
||||
// the new route and a previous one have a common prefix, let's merge them
|
||||
$child = new self($commonPrefix);
|
||||
list($child->prefixes[0], $child->staticPrefixes[0]) = $child->getCommonPrefix($this->prefixes[$i], $this->prefixes[$i]);
|
||||
list($child->prefixes[1], $child->staticPrefixes[1]) = $child->getCommonPrefix($prefix, $prefix);
|
||||
$child->items = array($this->items[$i], $route);
|
||||
|
||||
return;
|
||||
$this->staticPrefixes[$i] = $commonStaticPrefix;
|
||||
$this->prefixes[$i] = $commonPrefix;
|
||||
$this->items[$i] = $child;
|
||||
}
|
||||
|
||||
$group = $this->groupWithItem($item, $prefix, $route);
|
||||
|
||||
if ($group instanceof self) {
|
||||
$this->items[$i] = $group;
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// No optimised case was found, in this case we simple add the route for possible
|
||||
// grouping when new routes are added.
|
||||
$this->items[] = array($prefix, $route);
|
||||
$this->staticPrefixes[] = $staticPrefix;
|
||||
$this->prefixes[] = $prefix;
|
||||
$this->items[] = $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to combine a route with another route or group.
|
||||
*
|
||||
* @param StaticPrefixCollection|array $item
|
||||
* @param string $prefix
|
||||
* @param mixed $route
|
||||
*
|
||||
* @return null|StaticPrefixCollection
|
||||
* Linearizes back a set of nested routes into a collection.
|
||||
*/
|
||||
private function groupWithItem($item, $prefix, $route)
|
||||
public function populateCollection(RouteCollection $routes): RouteCollection
|
||||
{
|
||||
$itemPrefix = $item instanceof self ? $item->prefix : $item[0];
|
||||
$commonPrefix = $this->detectCommonPrefix($prefix, $itemPrefix);
|
||||
|
||||
if (!$commonPrefix) {
|
||||
return;
|
||||
foreach ($this->items as $route) {
|
||||
if ($route instanceof self) {
|
||||
$route->populateCollection($routes);
|
||||
} else {
|
||||
$routes->add(...$route);
|
||||
}
|
||||
}
|
||||
|
||||
$child = new self($commonPrefix);
|
||||
|
||||
if ($item instanceof self) {
|
||||
$child->items = array($item);
|
||||
} else {
|
||||
$child->addRoute($item[0], $item[1]);
|
||||
}
|
||||
|
||||
$child->addRoute($prefix, $route);
|
||||
|
||||
return $child;
|
||||
return $routes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a prefix can be contained within the group.
|
||||
* Gets the full and static common prefixes between two route patterns.
|
||||
*
|
||||
* @param string $prefix
|
||||
*
|
||||
* @return bool Whether a prefix could belong in a given group
|
||||
* The static prefix stops at last at the first opening bracket.
|
||||
*/
|
||||
private function accepts($prefix)
|
||||
{
|
||||
return '' === $this->prefix || 0 === strpos($prefix, $this->prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects whether there's a common prefix relative to the group prefix and returns it.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param string $anotherPrefix
|
||||
*
|
||||
* @return false|string A common prefix, longer than the base/group prefix, or false when none available
|
||||
*/
|
||||
private function detectCommonPrefix($prefix, $anotherPrefix)
|
||||
private function getCommonPrefix(string $prefix, string $anotherPrefix): array
|
||||
{
|
||||
$baseLength = \strlen($this->prefix);
|
||||
$commonLength = $baseLength;
|
||||
$end = min(\strlen($prefix), \strlen($anotherPrefix));
|
||||
$staticLength = null;
|
||||
set_error_handler(array(__CLASS__, 'handleError'));
|
||||
|
||||
for ($i = $baseLength; $i <= $end; ++$i) {
|
||||
if (substr($prefix, 0, $i) !== substr($anotherPrefix, 0, $i)) {
|
||||
for ($i = $baseLength; $i < $end && $prefix[$i] === $anotherPrefix[$i]; ++$i) {
|
||||
if ('(' === $prefix[$i]) {
|
||||
$staticLength = $staticLength ?? $i;
|
||||
for ($j = 1 + $i, $n = 1; $j < $end && 0 < $n; ++$j) {
|
||||
if ($prefix[$j] !== $anotherPrefix[$j]) {
|
||||
break 2;
|
||||
}
|
||||
if ('(' === $prefix[$j]) {
|
||||
++$n;
|
||||
} elseif (')' === $prefix[$j]) {
|
||||
--$n;
|
||||
} elseif ('\\' === $prefix[$j] && (++$j === $end || $prefix[$j] !== $anotherPrefix[$j])) {
|
||||
--$j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (0 < $n) {
|
||||
break;
|
||||
}
|
||||
if (('?' === ($prefix[$j] ?? '') || '?' === ($anotherPrefix[$j] ?? '')) && ($prefix[$j] ?? '') !== ($anotherPrefix[$j] ?? '')) {
|
||||
break;
|
||||
}
|
||||
$subPattern = substr($prefix, $i, $j - $i);
|
||||
if ($prefix !== $anotherPrefix && !preg_match('/^\(\[[^\]]++\]\+\+\)$/', $subPattern) && !preg_match('{(?<!'.$subPattern.')}', '')) {
|
||||
// sub-patterns of variable length are not considered as common prefixes because their greediness would break in-order matching
|
||||
break;
|
||||
}
|
||||
$i = $j - 1;
|
||||
} elseif ('\\' === $prefix[$i] && (++$i === $end || $prefix[$i] !== $anotherPrefix[$i])) {
|
||||
--$i;
|
||||
break;
|
||||
}
|
||||
|
||||
$commonLength = $i;
|
||||
}
|
||||
restore_error_handler();
|
||||
if ($i < $end && 0b10 === (\ord($prefix[$i]) >> 6) && preg_match('//u', $prefix.' '.$anotherPrefix)) {
|
||||
do {
|
||||
// Prevent cutting in the middle of an UTF-8 characters
|
||||
--$i;
|
||||
} while (0b10 === (\ord($prefix[$i]) >> 6));
|
||||
}
|
||||
|
||||
$commonPrefix = rtrim(substr($prefix, 0, $commonLength), '/');
|
||||
|
||||
if (\strlen($commonPrefix) > $baseLength) {
|
||||
return $commonPrefix;
|
||||
}
|
||||
|
||||
return false;
|
||||
return array(substr($prefix, 0, $i), substr($prefix, 0, $staticLength ?? $i));
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimizes the tree by inlining items from groups with less than 3 items.
|
||||
*/
|
||||
public function optimizeGroups()
|
||||
public static function handleError($type, $msg)
|
||||
{
|
||||
$index = -1;
|
||||
|
||||
while (isset($this->items[++$index])) {
|
||||
$item = $this->items[$index];
|
||||
|
||||
if ($item instanceof self) {
|
||||
$item->optimizeGroups();
|
||||
|
||||
// When a group contains only two items there's no reason to optimize because at minimum
|
||||
// the amount of prefix check is 2. In this case inline the group.
|
||||
if ($item->shouldBeInlined()) {
|
||||
array_splice($this->items, $index, 1, $item->items);
|
||||
|
||||
// Lower index to pass through the same index again after optimizing.
|
||||
// The first item of the replacements might be a group needing optimization.
|
||||
--$index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function shouldBeInlined()
|
||||
{
|
||||
if (\count($this->items) >= 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($this->items as $item) {
|
||||
if ($item instanceof self) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->items as $item) {
|
||||
if (\is_array($item) && $item[0] === $this->prefix) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Guards against adding incompatible prefixes in a group.
|
||||
*
|
||||
* @param string $prefix
|
||||
*
|
||||
* @throws \LogicException when a prefix does not belong in a group
|
||||
*/
|
||||
private function guardAgainstAddingNotAcceptedRoutes($prefix)
|
||||
{
|
||||
if (!$this->accepts($prefix)) {
|
||||
$message = sprintf('Could not add route with prefix %s to collection with prefix %s', $prefix, $this->prefix);
|
||||
|
||||
throw new \LogicException($message);
|
||||
}
|
||||
return 0 === strpos($msg, 'preg_match(): Compilation failed: lookbehind assertion is not fixed length');
|
||||
}
|
||||
}
|
||||
|
@@ -11,8 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Routing\Matcher;
|
||||
|
||||
use Symfony\Component\Routing\Exception\ExceptionInterface;
|
||||
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
@@ -25,41 +25,40 @@ abstract class RedirectableUrlMatcher extends UrlMatcher implements Redirectable
|
||||
public function match($pathinfo)
|
||||
{
|
||||
try {
|
||||
$parameters = parent::match($pathinfo);
|
||||
return parent::match($pathinfo);
|
||||
} catch (ResourceNotFoundException $e) {
|
||||
if ('/' === substr($pathinfo, -1) || !\in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
|
||||
if (!\in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
try {
|
||||
$parameters = parent::match($pathinfo.'/');
|
||||
if ($this->allowSchemes) {
|
||||
redirect_scheme:
|
||||
$scheme = $this->context->getScheme();
|
||||
$this->context->setScheme(current($this->allowSchemes));
|
||||
try {
|
||||
$ret = parent::match($pathinfo);
|
||||
|
||||
return array_replace($parameters, $this->redirect($pathinfo.'/', isset($parameters['_route']) ? $parameters['_route'] : null));
|
||||
} catch (ResourceNotFoundException $e2) {
|
||||
return $this->redirect($pathinfo, $ret['_route'] ?? null, $this->context->getScheme()) + $ret;
|
||||
} catch (ExceptionInterface $e2) {
|
||||
throw $e;
|
||||
} finally {
|
||||
$this->context->setScheme($scheme);
|
||||
}
|
||||
} elseif ('/' === $pathinfo) {
|
||||
throw $e;
|
||||
} else {
|
||||
try {
|
||||
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
|
||||
$ret = parent::match($pathinfo);
|
||||
|
||||
return $this->redirect($pathinfo, $ret['_route'] ?? null) + $ret;
|
||||
} catch (ExceptionInterface $e2) {
|
||||
if ($this->allowSchemes) {
|
||||
goto redirect_scheme;
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function handleRouteRequirements($pathinfo, $name, Route $route)
|
||||
{
|
||||
// expression condition
|
||||
if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) {
|
||||
return array(self::REQUIREMENT_MISMATCH, null);
|
||||
}
|
||||
|
||||
// check HTTP scheme requirement
|
||||
$scheme = $this->context->getScheme();
|
||||
$schemes = $route->getSchemes();
|
||||
if ($schemes && !$route->hasScheme($scheme)) {
|
||||
return array(self::ROUTE_MATCH, $this->redirect($pathinfo, $name, current($schemes)));
|
||||
}
|
||||
|
||||
return array(self::REQUIREMENT_MATCH, null);
|
||||
}
|
||||
}
|
||||
|
39
vendor/symfony/routing/Matcher/UrlMatcher.php
vendored
39
vendor/symfony/routing/Matcher/UrlMatcher.php
vendored
@@ -33,7 +33,19 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
||||
const ROUTE_MATCH = 2;
|
||||
|
||||
protected $context;
|
||||
|
||||
/**
|
||||
* Collects HTTP methods that would be allowed for the request.
|
||||
*/
|
||||
protected $allow = array();
|
||||
|
||||
/**
|
||||
* Collects URI schemes that would be allowed for the request.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected $allowSchemes = array();
|
||||
|
||||
protected $routes;
|
||||
protected $request;
|
||||
protected $expressionLanguage;
|
||||
@@ -70,7 +82,7 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
||||
*/
|
||||
public function match($pathinfo)
|
||||
{
|
||||
$this->allow = array();
|
||||
$this->allow = $this->allowSchemes = array();
|
||||
|
||||
if ($ret = $this->matchCollection(rawurldecode($pathinfo), $this->routes)) {
|
||||
return $ret;
|
||||
@@ -141,7 +153,7 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
||||
continue;
|
||||
}
|
||||
|
||||
// check HTTP method requirement
|
||||
$hasRequiredScheme = !$route->getSchemes() || $route->hasScheme($this->context->getScheme());
|
||||
if ($requiredMethods = $route->getMethods()) {
|
||||
// HEAD and GET are equivalent as per RFC
|
||||
if ('HEAD' === $method = $this->context->getMethod()) {
|
||||
@@ -149,7 +161,7 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
||||
}
|
||||
|
||||
if (!\in_array($method, $requiredMethods)) {
|
||||
if (self::REQUIREMENT_MATCH === $status[0]) {
|
||||
if ($hasRequiredScheme) {
|
||||
$this->allow = array_merge($this->allow, $requiredMethods);
|
||||
}
|
||||
|
||||
@@ -157,6 +169,12 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
||||
}
|
||||
}
|
||||
|
||||
if (!$hasRequiredScheme) {
|
||||
$this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes());
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, isset($status[1]) ? $status[1] : array()));
|
||||
}
|
||||
}
|
||||
@@ -176,9 +194,14 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
||||
*/
|
||||
protected function getAttributes(Route $route, $name, array $attributes)
|
||||
{
|
||||
$defaults = $route->getDefaults();
|
||||
if (isset($defaults['_canonical_route'])) {
|
||||
$name = $defaults['_canonical_route'];
|
||||
unset($defaults['_canonical_route']);
|
||||
}
|
||||
$attributes['_route'] = $name;
|
||||
|
||||
return $this->mergeDefaults($attributes, $route->getDefaults());
|
||||
return $this->mergeDefaults($attributes, $defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,11 +220,7 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
||||
return array(self::REQUIREMENT_MISMATCH, null);
|
||||
}
|
||||
|
||||
// check HTTP scheme requirement
|
||||
$scheme = $this->context->getScheme();
|
||||
$status = $route->getSchemes() && !$route->hasScheme($scheme) ? self::REQUIREMENT_MISMATCH : self::REQUIREMENT_MATCH;
|
||||
|
||||
return array($status, null);
|
||||
return array(self::REQUIREMENT_MATCH, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,7 +234,7 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
||||
protected function mergeDefaults($params, $defaults)
|
||||
{
|
||||
foreach ($params as $key => $value) {
|
||||
if (!\is_int($key)) {
|
||||
if (!\is_int($key) && null !== $value) {
|
||||
$defaults[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
12
vendor/symfony/routing/RequestContext.php
vendored
12
vendor/symfony/routing/RequestContext.php
vendored
@@ -33,17 +33,7 @@ class RequestContext
|
||||
private $queryString;
|
||||
private $parameters = array();
|
||||
|
||||
/**
|
||||
* @param string $baseUrl The base URL
|
||||
* @param string $method The HTTP method
|
||||
* @param string $host The HTTP host name
|
||||
* @param string $scheme The HTTP scheme
|
||||
* @param int $httpPort The HTTP port
|
||||
* @param int $httpsPort The HTTPS port
|
||||
* @param string $path The path
|
||||
* @param string $queryString The query string
|
||||
*/
|
||||
public function __construct($baseUrl = '', $method = 'GET', $host = 'localhost', $scheme = 'http', $httpPort = 80, $httpsPort = 443, $path = '/', $queryString = '')
|
||||
public function __construct(string $baseUrl = '', string $method = 'GET', string $host = 'localhost', string $scheme = 'http', int $httpPort = 80, int $httpsPort = 443, string $path = '/', string $queryString = '')
|
||||
{
|
||||
$this->setBaseUrl($baseUrl);
|
||||
$this->setMethod($method);
|
||||
|
19
vendor/symfony/routing/Route.php
vendored
19
vendor/symfony/routing/Route.php
vendored
@@ -50,11 +50,11 @@ class Route implements \Serializable
|
||||
* @param string|string[] $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
|
||||
*/
|
||||
public function __construct($path, array $defaults = array(), array $requirements = array(), array $options = array(), $host = '', $schemes = array(), $methods = array(), $condition = '')
|
||||
public function __construct(string $path, array $defaults = array(), array $requirements = array(), array $options = array(), ?string $host = '', $schemes = array(), $methods = array(), ?string $condition = '')
|
||||
{
|
||||
$this->setPath($path);
|
||||
$this->setDefaults($defaults);
|
||||
$this->setRequirements($requirements);
|
||||
$this->addDefaults($defaults);
|
||||
$this->addRequirements($requirements);
|
||||
$this->setOptions($options);
|
||||
$this->setHost($host);
|
||||
$this->setSchemes($schemes);
|
||||
@@ -123,6 +123,19 @@ class Route implements \Serializable
|
||||
*/
|
||||
public function setPath($pattern)
|
||||
{
|
||||
if (false !== strpbrk($pattern, '?<')) {
|
||||
$pattern = preg_replace_callback('#\{(\w++)(<.*?>)?(\?[^\}]*+)?\}#', function ($m) {
|
||||
if (isset($m[3][0])) {
|
||||
$this->setDefault($m[1], '?' !== $m[3] ? substr($m[3], 1) : null);
|
||||
}
|
||||
if (isset($m[2][0])) {
|
||||
$this->setRequirement($m[1], substr($m[2], 1, -1));
|
||||
}
|
||||
|
||||
return '{'.$m[1].'}';
|
||||
}, $pattern);
|
||||
}
|
||||
|
||||
// A pattern must start with a slash and must not have multiple slashes at the beginning because the
|
||||
// generated path for this route would be confused with a network path, e.g. '//domain.com/path'.
|
||||
$this->path = '/'.ltrim(trim($pattern), '/');
|
||||
|
17
vendor/symfony/routing/RouteCollection.php
vendored
17
vendor/symfony/routing/RouteCollection.php
vendored
@@ -153,6 +153,23 @@ class RouteCollection implements \IteratorAggregate, \Countable
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a prefix to the name of all the routes within in the collection.
|
||||
*/
|
||||
public function addNamePrefix(string $prefix)
|
||||
{
|
||||
$prefixedRoutes = array();
|
||||
|
||||
foreach ($this->routes as $name => $route) {
|
||||
$prefixedRoutes[$prefix.$name] = $route;
|
||||
if (null !== $name = $route->getDefault('_canonical_route')) {
|
||||
$route->setDefault('_canonical_route', $prefix.$name);
|
||||
}
|
||||
}
|
||||
|
||||
$this->routes = $prefixedRoutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the host pattern on all routes.
|
||||
*
|
||||
|
@@ -58,7 +58,7 @@ class RouteCollectionBuilder
|
||||
*/
|
||||
public function import($resource, $prefix = '/', $type = null)
|
||||
{
|
||||
/** @var RouteCollection[] $collection */
|
||||
/** @var RouteCollection[] $collections */
|
||||
$collections = $this->load($resource, $type);
|
||||
|
||||
// create a builder from the RouteCollection
|
||||
@@ -253,7 +253,7 @@ class RouteCollectionBuilder
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function addResource(ResourceInterface $resource)
|
||||
private function addResource(ResourceInterface $resource): self
|
||||
{
|
||||
$this->resources[] = $resource;
|
||||
|
||||
@@ -324,10 +324,8 @@ class RouteCollectionBuilder
|
||||
|
||||
/**
|
||||
* Generates a route name based on details of this route.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function generateRouteName(Route $route)
|
||||
private function generateRouteName(Route $route): string
|
||||
{
|
||||
$methods = implode('_', $route->getMethods()).'_';
|
||||
|
||||
@@ -351,7 +349,7 @@ class RouteCollectionBuilder
|
||||
*
|
||||
* @throws FileLoaderLoadException If no loader is found
|
||||
*/
|
||||
private function load($resource, $type = null)
|
||||
private function load($resource, string $type = null): array
|
||||
{
|
||||
if (null === $this->loader) {
|
||||
throw new \BadMethodCallException('Cannot import other routing resources: you must pass a LoaderInterface when constructing RouteCollectionBuilder.');
|
||||
|
43
vendor/symfony/routing/RouteCompiler.php
vendored
43
vendor/symfony/routing/RouteCompiler.php
vendored
@@ -103,8 +103,7 @@ class RouteCompiler implements RouteCompilerInterface
|
||||
$needsUtf8 = $route->getOption('utf8');
|
||||
|
||||
if (!$needsUtf8 && $useUtf8 && preg_match('/[\x80-\xFF]/', $pattern)) {
|
||||
$needsUtf8 = true;
|
||||
@trigger_error(sprintf('Using UTF-8 route patterns without setting the "utf8" option is deprecated since Symfony 3.2 and will throw a LogicException in 4.0. Turn on the "utf8" route option for pattern "%s".', $pattern), E_USER_DEPRECATED);
|
||||
throw new \LogicException(sprintf('Cannot use UTF-8 route patterns without setting the "utf8" option for route "%s".', $route->getPath()));
|
||||
}
|
||||
if (!$useUtf8 && $needsUtf8) {
|
||||
throw new \LogicException(sprintf('Cannot mix UTF-8 requirements with non-UTF-8 pattern "%s".', $pattern));
|
||||
@@ -176,12 +175,12 @@ class RouteCompiler implements RouteCompilerInterface
|
||||
if (!preg_match('//u', $regexp)) {
|
||||
$useUtf8 = false;
|
||||
} elseif (!$needsUtf8 && preg_match('/[\x80-\xFF]|(?<!\\\\)\\\\(?:\\\\\\\\)*+(?-i:X|[pP][\{CLMNPSZ]|x\{[A-Fa-f0-9]{3})/', $regexp)) {
|
||||
$needsUtf8 = true;
|
||||
@trigger_error(sprintf('Using UTF-8 route requirements without setting the "utf8" option is deprecated since Symfony 3.2 and will throw a LogicException in 4.0. Turn on the "utf8" route option for variable "%s" in pattern "%s".', $varName, $pattern), E_USER_DEPRECATED);
|
||||
throw new \LogicException(sprintf('Cannot use UTF-8 route requirements without setting the "utf8" option for variable "%s" in pattern "%s".', $varName, $pattern));
|
||||
}
|
||||
if (!$useUtf8 && $needsUtf8) {
|
||||
throw new \LogicException(sprintf('Cannot mix UTF-8 requirement with non-UTF-8 charset for variable "%s" in pattern "%s".', $varName, $pattern));
|
||||
}
|
||||
$regexp = self::transformCapturingGroupsToNonCapturings($regexp);
|
||||
}
|
||||
|
||||
$tokens[] = array('variable', $isSeparator ? $precedingChar : '', $regexp, $varName);
|
||||
@@ -232,10 +231,8 @@ class RouteCompiler implements RouteCompilerInterface
|
||||
|
||||
/**
|
||||
* Determines the longest static prefix possible for a route.
|
||||
*
|
||||
* @return string The leading static part of a route's path
|
||||
*/
|
||||
private static function determineStaticPrefix(Route $route, array $tokens)
|
||||
private static function determineStaticPrefix(Route $route, array $tokens): string
|
||||
{
|
||||
if ('text' !== $tokens[0][0]) {
|
||||
return ($route->hasDefault($tokens[0][3]) || '/' === $tokens[0][1]) ? '' : $tokens[0][1];
|
||||
@@ -251,14 +248,9 @@ class RouteCompiler implements RouteCompilerInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next static character in the Route pattern that will serve as a separator.
|
||||
*
|
||||
* @param string $pattern The route pattern
|
||||
* @param bool $useUtf8 Whether the character is encoded in UTF-8 or not
|
||||
*
|
||||
* @return string The next static character that functions as separator (or empty string when none available)
|
||||
* Returns the next static character in the Route pattern that will serve as a separator (or the empty string when none available).
|
||||
*/
|
||||
private static function findNextSeparator($pattern, $useUtf8)
|
||||
private static function findNextSeparator(string $pattern, bool $useUtf8): string
|
||||
{
|
||||
if ('' == $pattern) {
|
||||
// return empty string if pattern is empty or false (false which can be returned by substr)
|
||||
@@ -284,7 +276,7 @@ class RouteCompiler implements RouteCompilerInterface
|
||||
*
|
||||
* @return string The regexp pattern for a single token
|
||||
*/
|
||||
private static function computeRegexp(array $tokens, $index, $firstOptional)
|
||||
private static function computeRegexp(array $tokens, int $index, int $firstOptional): string
|
||||
{
|
||||
$token = $tokens[$index];
|
||||
if ('text' === $token[0]) {
|
||||
@@ -313,4 +305,25 @@ class RouteCompiler implements RouteCompilerInterface
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function transformCapturingGroupsToNonCapturings(string $regexp): string
|
||||
{
|
||||
for ($i = 0; $i < \strlen($regexp); ++$i) {
|
||||
if ('\\' === $regexp[$i]) {
|
||||
++$i;
|
||||
continue;
|
||||
}
|
||||
if ('(' !== $regexp[$i] || !isset($regexp[$i + 2])) {
|
||||
continue;
|
||||
}
|
||||
if ('*' === $regexp[++$i] || '?' === $regexp[$i]) {
|
||||
++$i;
|
||||
continue;
|
||||
}
|
||||
$regexp = substr_replace($regexp, '?:', $i, 0);
|
||||
++$i;
|
||||
}
|
||||
|
||||
return $regexp;
|
||||
}
|
||||
}
|
||||
|
@@ -24,6 +24,14 @@ class RouteTest extends TestCase
|
||||
$route = new Route(array('foo' => 'bar'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \BadMethodCallException
|
||||
*/
|
||||
public function testTryingToSetLocalesDirectly()
|
||||
{
|
||||
$route = new Route(array('locales' => array('nl' => 'bar')));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getValidParameters
|
||||
*/
|
||||
@@ -45,6 +53,7 @@ class RouteTest extends TestCase
|
||||
array('methods', array('GET', 'POST'), 'getMethods'),
|
||||
array('host', '{locale}.example.com', 'getHost'),
|
||||
array('condition', 'context.getMethod() == "GET"', 'getCondition'),
|
||||
array('value', array('nl' => '/hier', 'en' => '/here'), 'getLocalizedPaths'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
7
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/AbstractClassController.php
vendored
Normal file
7
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/AbstractClassController.php
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||
|
||||
abstract class AbstractClassController
|
||||
{
|
||||
}
|
15
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/ActionPathController.php
vendored
Normal file
15
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/ActionPathController.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class ActionPathController
|
||||
{
|
||||
/**
|
||||
* @Route("/path", name="action")
|
||||
*/
|
||||
public function action()
|
||||
{
|
||||
}
|
||||
}
|
15
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/DefaultValueController.php
vendored
Normal file
15
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/DefaultValueController.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class DefaultValueController
|
||||
{
|
||||
/**
|
||||
* @Route("/{default}/path", name="action")
|
||||
*/
|
||||
public function action($default = 'value')
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class ExplicitLocalizedActionPathController
|
||||
{
|
||||
/**
|
||||
* @Route(path={"en": "/path", "nl": "/pad"}, name="action")
|
||||
*/
|
||||
public function action()
|
||||
{
|
||||
}
|
||||
}
|
15
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/InvokableController.php
vendored
Normal file
15
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/InvokableController.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* @Route("/here", name="lol")
|
||||
*/
|
||||
class InvokableController
|
||||
{
|
||||
public function __invoke()
|
||||
{
|
||||
}
|
||||
}
|
15
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/InvokableLocalizedController.php
vendored
Normal file
15
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/InvokableLocalizedController.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* @Route(path={"nl": "/hier", "en": "/here"}, name="action")
|
||||
*/
|
||||
class InvokableLocalizedController
|
||||
{
|
||||
public function __invoke()
|
||||
{
|
||||
}
|
||||
}
|
15
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedActionPathController.php
vendored
Normal file
15
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedActionPathController.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class LocalizedActionPathController
|
||||
{
|
||||
/**
|
||||
* @Route(path={"en": "/path", "nl": "/pad"}, name="action")
|
||||
*/
|
||||
public function action()
|
||||
{
|
||||
}
|
||||
}
|
25
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedMethodActionControllers.php
vendored
Normal file
25
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedMethodActionControllers.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* @Route(path={"en": "/the/path", "nl": "/het/pad"})
|
||||
*/
|
||||
class LocalizedMethodActionControllers
|
||||
{
|
||||
/**
|
||||
* @Route(name="post", methods={"POST"})
|
||||
*/
|
||||
public function post()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route(name="put", methods={"PUT"})
|
||||
*/
|
||||
public function put()
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* @Route(path={"nl": "/nl", "en": "/en"})
|
||||
*/
|
||||
class LocalizedPrefixLocalizedActionController
|
||||
{
|
||||
/**
|
||||
* @Route(path={"nl": "/actie", "en": "/action"}, name="action")
|
||||
*/
|
||||
public function action()
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* @Route(path={"nl": "/nl"})
|
||||
*/
|
||||
class LocalizedPrefixMissingLocaleActionController
|
||||
{
|
||||
/**
|
||||
* @Route(path={"nl": "/actie", "en": "/action"}, name="action")
|
||||
*/
|
||||
public function action()
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* @Route(path={"nl": "/nl", "en": "/en"})
|
||||
*/
|
||||
class LocalizedPrefixMissingRouteLocaleActionController
|
||||
{
|
||||
/**
|
||||
* @Route(path={"nl": "/actie"}, name="action")
|
||||
*/
|
||||
public function action()
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* @Route(path={"en": "/en", "nl": "/nl"})
|
||||
*/
|
||||
class LocalizedPrefixWithRouteWithoutLocale
|
||||
{
|
||||
/**
|
||||
* @Route("/suffix", name="action")
|
||||
*/
|
||||
public function action()
|
||||
{
|
||||
}
|
||||
}
|
25
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/MethodActionControllers.php
vendored
Normal file
25
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/MethodActionControllers.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* @Route("/the/path")
|
||||
*/
|
||||
class MethodActionControllers
|
||||
{
|
||||
/**
|
||||
* @Route(name="post", methods={"POST"})
|
||||
*/
|
||||
public function post()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route(name="put", methods={"PUT"})
|
||||
*/
|
||||
public function put()
|
||||
{
|
||||
}
|
||||
}
|
15
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/MissingRouteNameController.php
vendored
Normal file
15
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/MissingRouteNameController.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class MissingRouteNameController
|
||||
{
|
||||
/**
|
||||
* @Route("/path")
|
||||
*/
|
||||
public function action()
|
||||
{
|
||||
}
|
||||
}
|
15
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/NothingButNameController.php
vendored
Normal file
15
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/NothingButNameController.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class NothingButNameController
|
||||
{
|
||||
/**
|
||||
* @Route(name="action")
|
||||
*/
|
||||
public function action()
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* @Route("/prefix")
|
||||
*/
|
||||
class PrefixedActionLocalizedRouteController
|
||||
{
|
||||
/**
|
||||
* @Route(path={"en": "/path", "nl": "/pad"}, name="action")
|
||||
*/
|
||||
public function action()
|
||||
{
|
||||
}
|
||||
}
|
18
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/PrefixedActionPathController.php
vendored
Normal file
18
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/PrefixedActionPathController.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* @Route("/prefix", host="frankdejonge.nl", condition="lol=fun")
|
||||
*/
|
||||
class PrefixedActionPathController
|
||||
{
|
||||
/**
|
||||
* @Route("/path", name="action")
|
||||
*/
|
||||
public function action()
|
||||
{
|
||||
}
|
||||
}
|
18
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/RouteWithPrefixController.php
vendored
Normal file
18
vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/RouteWithPrefixController.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* @Route("/prefix")
|
||||
*/
|
||||
class RouteWithPrefixController
|
||||
{
|
||||
/**
|
||||
* @Route("/path", name="action")
|
||||
*/
|
||||
public function action()
|
||||
{
|
||||
}
|
||||
}
|
@@ -17,11 +17,9 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$trimmedPathinfo = rtrim($pathinfo, '/');
|
||||
$context = $this->context;
|
||||
$request = $this->request ?: $this->createRequest($pathinfo);
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
|
||||
if ('HEAD' === $requestMethod) {
|
||||
@@ -32,6 +30,6 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
|
||||
}
|
||||
|
||||
throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException();
|
||||
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
|
||||
}
|
||||
}
|
||||
|
@@ -17,302 +17,231 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$trimmedPathinfo = rtrim($pathinfo, '/');
|
||||
$context = $this->context;
|
||||
$request = $this->request ?: $this->createRequest($pathinfo);
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
$host = strtolower($context->getHost());
|
||||
|
||||
if ('HEAD' === $requestMethod) {
|
||||
$canonicalMethod = 'GET';
|
||||
}
|
||||
|
||||
if (0 === strpos($pathinfo, '/foo')) {
|
||||
// foo
|
||||
if (preg_match('#^/foo/(?P<bar>baz|symfony)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo')), array ( 'def' => 'test',));
|
||||
}
|
||||
switch ($pathinfo) {
|
||||
default:
|
||||
$routes = array(
|
||||
'/test/baz' => array(array('_route' => 'baz'), null, null, null),
|
||||
'/test/baz.html' => array(array('_route' => 'baz2'), null, null, null),
|
||||
'/test/baz3/' => array(array('_route' => 'baz3'), null, null, null),
|
||||
'/foofoo' => array(array('_route' => 'foofoo', 'def' => 'test'), null, null, null),
|
||||
'/spa ce' => array(array('_route' => 'space'), null, null, null),
|
||||
'/multi/new' => array(array('_route' => 'overridden2'), null, null, null),
|
||||
'/multi/hey/' => array(array('_route' => 'hey'), null, null, null),
|
||||
'/ababa' => array(array('_route' => 'ababa'), null, null, null),
|
||||
'/route1' => array(array('_route' => 'route1'), 'a.example.com', null, null),
|
||||
'/c2/route2' => array(array('_route' => 'route2'), 'a.example.com', null, null),
|
||||
'/route4' => array(array('_route' => 'route4'), 'a.example.com', null, null),
|
||||
'/c2/route3' => array(array('_route' => 'route3'), 'b.example.com', null, null),
|
||||
'/route5' => array(array('_route' => 'route5'), 'c.example.com', null, null),
|
||||
'/route6' => array(array('_route' => 'route6'), null, null, null),
|
||||
'/route11' => array(array('_route' => 'route11'), '#^(?P<var1>[^\\.]++)\\.example\\.com$#sDi', null, null),
|
||||
'/route12' => array(array('_route' => 'route12', 'var1' => 'val'), '#^(?P<var1>[^\\.]++)\\.example\\.com$#sDi', null, null),
|
||||
'/route17' => array(array('_route' => 'route17'), null, null, null),
|
||||
);
|
||||
|
||||
// foofoo
|
||||
if ('/foofoo' === $pathinfo) {
|
||||
return array ( 'def' => 'test', '_route' => 'foofoo',);
|
||||
}
|
||||
if (!isset($routes[$pathinfo])) {
|
||||
break;
|
||||
}
|
||||
list($ret, $requiredHost, $requiredMethods, $requiredSchemes) = $routes[$pathinfo];
|
||||
|
||||
}
|
||||
if ($requiredHost) {
|
||||
if ('#' !== $requiredHost[0] ? $requiredHost !== $host : !preg_match($requiredHost, $host, $hostMatches)) {
|
||||
break;
|
||||
}
|
||||
if ('#' === $requiredHost[0] && $hostMatches) {
|
||||
$hostMatches['_route'] = $ret['_route'];
|
||||
$ret = $this->mergeDefaults($hostMatches, $ret);
|
||||
}
|
||||
}
|
||||
|
||||
elseif (0 === strpos($pathinfo, '/bar')) {
|
||||
// bar
|
||||
if (preg_match('#^/bar/(?P<foo>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'bar')), array ());
|
||||
if (!in_array($canonicalMethod, array('GET', 'HEAD'))) {
|
||||
$allow = array_merge($allow, array('GET', 'HEAD'));
|
||||
goto not_bar;
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_bar:
|
||||
}
|
||||
|
||||
// barhead
|
||||
if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P<foo>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'barhead')), array ());
|
||||
if (!in_array($canonicalMethod, array('GET'))) {
|
||||
$allow = array_merge($allow, array('GET'));
|
||||
goto not_barhead;
|
||||
$matchedPathinfo = $host.'.'.$pathinfo;
|
||||
$regexList = array(
|
||||
0 => '{^(?'
|
||||
.'|(?:(?:[^./]*+\\.)++)(?'
|
||||
.'|/foo/(baz|symfony)(*:47)'
|
||||
.'|/bar(?'
|
||||
.'|/([^/]++)(*:70)'
|
||||
.'|head/([^/]++)(*:90)'
|
||||
.')'
|
||||
.'|/test/([^/]++)/(?'
|
||||
.'|(*:116)'
|
||||
.')'
|
||||
.'|/([\']+)(*:132)'
|
||||
.'|/a/(?'
|
||||
.'|b\'b/([^/]++)(?'
|
||||
.'|(*:161)'
|
||||
.'|(*:169)'
|
||||
.')'
|
||||
.'|(.*)(*:182)'
|
||||
.'|b\'b/([^/]++)(?'
|
||||
.'|(*:205)'
|
||||
.'|(*:213)'
|
||||
.')'
|
||||
.')'
|
||||
.'|/multi/hello(?:/([^/]++))?(*:249)'
|
||||
.'|/([^/]++)/b/([^/]++)(?'
|
||||
.'|(*:280)'
|
||||
.'|(*:288)'
|
||||
.')'
|
||||
.'|/aba/([^/]++)(*:310)'
|
||||
.')|(?i:([^\\.]++)\\.example\\.com)\\.(?'
|
||||
.'|/route1(?'
|
||||
.'|3/([^/]++)(*:372)'
|
||||
.'|4/([^/]++)(*:390)'
|
||||
.')'
|
||||
.')|(?i:c\\.example\\.com)\\.(?'
|
||||
.'|/route15/([^/]++)(*:442)'
|
||||
.')|(?:(?:[^./]*+\\.)++)(?'
|
||||
.'|/route16/([^/]++)(*:490)'
|
||||
.'|/a/(?'
|
||||
.'|a\\.\\.\\.(*:511)'
|
||||
.'|b/(?'
|
||||
.'|([^/]++)(*:532)'
|
||||
.'|c/([^/]++)(*:550)'
|
||||
.')'
|
||||
.')'
|
||||
.')'
|
||||
.')$}sD',
|
||||
);
|
||||
|
||||
foreach ($regexList as $offset => $regex) {
|
||||
while (preg_match($regex, $matchedPathinfo, $matches)) {
|
||||
switch ($m = (int) $matches['MARK']) {
|
||||
case 116:
|
||||
$matches = array('foo' => $matches[1] ?? null);
|
||||
|
||||
// baz4
|
||||
return $this->mergeDefaults(array('_route' => 'baz4') + $matches, array());
|
||||
|
||||
// baz5
|
||||
$ret = $this->mergeDefaults(array('_route' => 'baz5') + $matches, array());
|
||||
if (!isset(($a = array('POST' => 0))[$requestMethod])) {
|
||||
$allow += $a;
|
||||
goto not_baz5;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
not_baz5:
|
||||
|
||||
// baz.baz6
|
||||
$ret = $this->mergeDefaults(array('_route' => 'baz.baz6') + $matches, array());
|
||||
if (!isset(($a = array('PUT' => 0))[$requestMethod])) {
|
||||
$allow += $a;
|
||||
goto not_bazbaz6;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
not_bazbaz6:
|
||||
|
||||
break;
|
||||
case 161:
|
||||
$matches = array('foo' => $matches[1] ?? null);
|
||||
|
||||
// foo1
|
||||
$ret = $this->mergeDefaults(array('_route' => 'foo1') + $matches, array());
|
||||
if (!isset(($a = array('PUT' => 0))[$requestMethod])) {
|
||||
$allow += $a;
|
||||
goto not_foo1;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
not_foo1:
|
||||
|
||||
break;
|
||||
case 205:
|
||||
$matches = array('foo1' => $matches[1] ?? null);
|
||||
|
||||
// foo2
|
||||
return $this->mergeDefaults(array('_route' => 'foo2') + $matches, array());
|
||||
|
||||
break;
|
||||
case 280:
|
||||
$matches = array('_locale' => $matches[1] ?? null, 'foo' => $matches[2] ?? null);
|
||||
|
||||
// foo3
|
||||
return $this->mergeDefaults(array('_route' => 'foo3') + $matches, array());
|
||||
|
||||
break;
|
||||
default:
|
||||
$routes = array(
|
||||
47 => array(array('_route' => 'foo', 'def' => 'test'), array('bar'), null, null),
|
||||
70 => array(array('_route' => 'bar'), array('foo'), array('GET' => 0, 'HEAD' => 1), null),
|
||||
90 => array(array('_route' => 'barhead'), array('foo'), array('GET' => 0), null),
|
||||
132 => array(array('_route' => 'quoter'), array('quoter'), null, null),
|
||||
169 => array(array('_route' => 'bar1'), array('bar'), null, null),
|
||||
182 => array(array('_route' => 'overridden'), array('var'), null, null),
|
||||
213 => array(array('_route' => 'bar2'), array('bar1'), null, null),
|
||||
249 => array(array('_route' => 'helloWorld', 'who' => 'World!'), array('who'), null, null),
|
||||
288 => array(array('_route' => 'bar3'), array('_locale', 'bar'), null, null),
|
||||
310 => array(array('_route' => 'foo4'), array('foo'), null, null),
|
||||
372 => array(array('_route' => 'route13'), array('var1', 'name'), null, null),
|
||||
390 => array(array('_route' => 'route14', 'var1' => 'val'), array('var1', 'name'), null, null),
|
||||
442 => array(array('_route' => 'route15'), array('name'), null, null),
|
||||
490 => array(array('_route' => 'route16', 'var1' => 'val'), array('name'), null, null),
|
||||
511 => array(array('_route' => 'a'), array(), null, null),
|
||||
532 => array(array('_route' => 'b'), array('var'), null, null),
|
||||
550 => array(array('_route' => 'c'), array('var'), null, null),
|
||||
);
|
||||
|
||||
list($ret, $vars, $requiredMethods, $requiredSchemes) = $routes[$m];
|
||||
|
||||
foreach ($vars as $i => $v) {
|
||||
if (isset($matches[1 + $i])) {
|
||||
$ret[$v] = $matches[1 + $i];
|
||||
}
|
||||
}
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_barhead:
|
||||
|
||||
}
|
||||
|
||||
elseif (0 === strpos($pathinfo, '/test')) {
|
||||
if (0 === strpos($pathinfo, '/test/baz')) {
|
||||
// baz
|
||||
if ('/test/baz' === $pathinfo) {
|
||||
return array('_route' => 'baz');
|
||||
if (550 === $m) {
|
||||
break;
|
||||
}
|
||||
|
||||
// baz2
|
||||
if ('/test/baz.html' === $pathinfo) {
|
||||
return array('_route' => 'baz2');
|
||||
}
|
||||
|
||||
// baz3
|
||||
if ('/test/baz3/' === $pathinfo) {
|
||||
return array('_route' => 'baz3');
|
||||
}
|
||||
|
||||
$regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m));
|
||||
$offset += strlen($m);
|
||||
}
|
||||
|
||||
// baz4
|
||||
if (preg_match('#^/test/(?P<foo>[^/]++)/$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz4')), array ());
|
||||
}
|
||||
|
||||
// baz5
|
||||
if (preg_match('#^/test/(?P<foo>[^/]++)/$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'baz5')), array ());
|
||||
if (!in_array($requestMethod, array('POST'))) {
|
||||
$allow = array_merge($allow, array('POST'));
|
||||
goto not_baz5;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_baz5:
|
||||
|
||||
// baz.baz6
|
||||
if (preg_match('#^/test/(?P<foo>[^/]++)/$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'baz.baz6')), array ());
|
||||
if (!in_array($requestMethod, array('PUT'))) {
|
||||
$allow = array_merge($allow, array('PUT'));
|
||||
goto not_bazbaz6;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_bazbaz6:
|
||||
|
||||
}
|
||||
|
||||
// quoter
|
||||
if (preg_match('#^/(?P<quoter>[\']+)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'quoter')), array ());
|
||||
}
|
||||
|
||||
// space
|
||||
if ('/spa ce' === $pathinfo) {
|
||||
return array('_route' => 'space');
|
||||
}
|
||||
|
||||
if (0 === strpos($pathinfo, '/a')) {
|
||||
if (0 === strpos($pathinfo, '/a/b\'b')) {
|
||||
// foo1
|
||||
if (preg_match('#^/a/b\'b/(?P<foo>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo1')), array ());
|
||||
}
|
||||
|
||||
// bar1
|
||||
if (preg_match('#^/a/b\'b/(?P<bar>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar1')), array ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// overridden
|
||||
if (preg_match('#^/a/(?P<var>.*)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'overridden')), array ());
|
||||
}
|
||||
|
||||
if (0 === strpos($pathinfo, '/a/b\'b')) {
|
||||
// foo2
|
||||
if (preg_match('#^/a/b\'b/(?P<foo1>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo2')), array ());
|
||||
}
|
||||
|
||||
// bar2
|
||||
if (preg_match('#^/a/b\'b/(?P<bar1>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar2')), array ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
elseif (0 === strpos($pathinfo, '/multi')) {
|
||||
// helloWorld
|
||||
if (0 === strpos($pathinfo, '/multi/hello') && preg_match('#^/multi/hello(?:/(?P<who>[^/]++))?$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'helloWorld')), array ( 'who' => 'World!',));
|
||||
}
|
||||
|
||||
// hey
|
||||
if ('/multi/hey/' === $pathinfo) {
|
||||
return array('_route' => 'hey');
|
||||
}
|
||||
|
||||
// overridden2
|
||||
if ('/multi/new' === $pathinfo) {
|
||||
return array('_route' => 'overridden2');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// foo3
|
||||
if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P<foo>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo3')), array ());
|
||||
}
|
||||
|
||||
// bar3
|
||||
if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P<bar>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar3')), array ());
|
||||
}
|
||||
|
||||
if (0 === strpos($pathinfo, '/aba')) {
|
||||
// ababa
|
||||
if ('/ababa' === $pathinfo) {
|
||||
return array('_route' => 'ababa');
|
||||
}
|
||||
|
||||
// foo4
|
||||
if (preg_match('#^/aba/(?P<foo>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo4')), array ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$host = $context->getHost();
|
||||
|
||||
if (preg_match('#^a\\.example\\.com$#sDi', $host, $hostMatches)) {
|
||||
// route1
|
||||
if ('/route1' === $pathinfo) {
|
||||
return array('_route' => 'route1');
|
||||
}
|
||||
|
||||
// route2
|
||||
if ('/c2/route2' === $pathinfo) {
|
||||
return array('_route' => 'route2');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (preg_match('#^b\\.example\\.com$#sDi', $host, $hostMatches)) {
|
||||
// route3
|
||||
if ('/c2/route3' === $pathinfo) {
|
||||
return array('_route' => 'route3');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (preg_match('#^a\\.example\\.com$#sDi', $host, $hostMatches)) {
|
||||
// route4
|
||||
if ('/route4' === $pathinfo) {
|
||||
return array('_route' => 'route4');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (preg_match('#^c\\.example\\.com$#sDi', $host, $hostMatches)) {
|
||||
// route5
|
||||
if ('/route5' === $pathinfo) {
|
||||
return array('_route' => 'route5');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// route6
|
||||
if ('/route6' === $pathinfo) {
|
||||
return array('_route' => 'route6');
|
||||
}
|
||||
|
||||
if (preg_match('#^(?P<var1>[^\\.]++)\\.example\\.com$#sDi', $host, $hostMatches)) {
|
||||
if (0 === strpos($pathinfo, '/route1')) {
|
||||
// route11
|
||||
if ('/route11' === $pathinfo) {
|
||||
return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route11')), array ());
|
||||
}
|
||||
|
||||
// route12
|
||||
if ('/route12' === $pathinfo) {
|
||||
return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route12')), array ( 'var1' => 'val',));
|
||||
}
|
||||
|
||||
// route13
|
||||
if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?P<name>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route13')), array ());
|
||||
}
|
||||
|
||||
// route14
|
||||
if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?P<name>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route14')), array ( 'var1' => 'val',));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (preg_match('#^c\\.example\\.com$#sDi', $host, $hostMatches)) {
|
||||
// route15
|
||||
if (0 === strpos($pathinfo, '/route15') && preg_match('#^/route15/(?P<name>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'route15')), array ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// route16
|
||||
if (0 === strpos($pathinfo, '/route16') && preg_match('#^/route16/(?P<name>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'route16')), array ( 'var1' => 'val',));
|
||||
}
|
||||
|
||||
// route17
|
||||
if ('/route17' === $pathinfo) {
|
||||
return array('_route' => 'route17');
|
||||
}
|
||||
|
||||
// a
|
||||
if ('/a/a...' === $pathinfo) {
|
||||
return array('_route' => 'a');
|
||||
}
|
||||
|
||||
if (0 === strpos($pathinfo, '/a/b')) {
|
||||
// b
|
||||
if (preg_match('#^/a/b/(?P<var>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'b')), array ());
|
||||
}
|
||||
|
||||
// c
|
||||
if (0 === strpos($pathinfo, '/a/b/c') && preg_match('#^/a/b/c/(?P<var>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'c')), array ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ('/' === $pathinfo && !$allow) {
|
||||
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
|
||||
}
|
||||
|
||||
throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException();
|
||||
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
|
||||
}
|
||||
}
|
||||
|
2830
vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher10.php
vendored
Normal file
2830
vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher10.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
151
vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher11.php
vendored
Normal file
151
vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher11.php
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
|
||||
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
|
||||
use Symfony\Component\Routing\RequestContext;
|
||||
|
||||
/**
|
||||
* This class has been auto-generated
|
||||
* by the Symfony Routing Component.
|
||||
*/
|
||||
class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher
|
||||
{
|
||||
public function __construct(RequestContext $context)
|
||||
{
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function match($pathinfo)
|
||||
{
|
||||
$allow = $allowSchemes = array();
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $ret;
|
||||
}
|
||||
if ($allow) {
|
||||
throw new MethodNotAllowedException(array_keys($allow));
|
||||
}
|
||||
if (!in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
|
||||
// no-op
|
||||
} elseif ($allowSchemes) {
|
||||
redirect_scheme:
|
||||
$scheme = $this->context->getScheme();
|
||||
$this->context->setScheme(key($allowSchemes));
|
||||
try {
|
||||
if ($ret = $this->doMatch($pathinfo)) {
|
||||
return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret;
|
||||
}
|
||||
} finally {
|
||||
$this->context->setScheme($scheme);
|
||||
}
|
||||
} elseif ('/' !== $pathinfo) {
|
||||
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $this->redirect($pathinfo, $ret['_route']) + $ret;
|
||||
}
|
||||
if ($allowSchemes) {
|
||||
goto redirect_scheme;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ResourceNotFoundException();
|
||||
}
|
||||
|
||||
private function doMatch(string $rawPathinfo, array &$allow = array(), array &$allowSchemes = array()): ?array
|
||||
{
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
|
||||
if ('HEAD' === $requestMethod) {
|
||||
$canonicalMethod = 'GET';
|
||||
}
|
||||
|
||||
$matchedPathinfo = $pathinfo;
|
||||
$regexList = array(
|
||||
0 => '{^(?'
|
||||
.'|/(en|fr)/(?'
|
||||
.'|admin/post/(?'
|
||||
.'|(*:33)'
|
||||
.'|new(*:43)'
|
||||
.'|(\\d+)(*:55)'
|
||||
.'|(\\d+)/edit(*:72)'
|
||||
.'|(\\d+)/delete(*:91)'
|
||||
.')'
|
||||
.'|blog/(?'
|
||||
.'|(*:107)'
|
||||
.'|rss\\.xml(*:123)'
|
||||
.'|p(?'
|
||||
.'|age/([^/]++)(*:147)'
|
||||
.'|osts/([^/]++)(*:168)'
|
||||
.')'
|
||||
.'|comments/(\\d+)/new(*:195)'
|
||||
.'|search(*:209)'
|
||||
.')'
|
||||
.'|log(?'
|
||||
.'|in(*:226)'
|
||||
.'|out(*:237)'
|
||||
.')'
|
||||
.')'
|
||||
.'|/(en|fr)?(*:256)'
|
||||
.')$}sD',
|
||||
);
|
||||
|
||||
foreach ($regexList as $offset => $regex) {
|
||||
while (preg_match($regex, $matchedPathinfo, $matches)) {
|
||||
switch ($m = (int) $matches['MARK']) {
|
||||
default:
|
||||
$routes = array(
|
||||
33 => array(array('_route' => 'a', '_locale' => 'en'), array('_locale'), null, null),
|
||||
43 => array(array('_route' => 'b', '_locale' => 'en'), array('_locale'), null, null),
|
||||
55 => array(array('_route' => 'c', '_locale' => 'en'), array('_locale', 'id'), null, null),
|
||||
72 => array(array('_route' => 'd', '_locale' => 'en'), array('_locale', 'id'), null, null),
|
||||
91 => array(array('_route' => 'e', '_locale' => 'en'), array('_locale', 'id'), null, null),
|
||||
107 => array(array('_route' => 'f', '_locale' => 'en'), array('_locale'), null, null),
|
||||
123 => array(array('_route' => 'g', '_locale' => 'en'), array('_locale'), null, null),
|
||||
147 => array(array('_route' => 'h', '_locale' => 'en'), array('_locale', 'page'), null, null),
|
||||
168 => array(array('_route' => 'i', '_locale' => 'en'), array('_locale', 'page'), null, null),
|
||||
195 => array(array('_route' => 'j', '_locale' => 'en'), array('_locale', 'id'), null, null),
|
||||
209 => array(array('_route' => 'k', '_locale' => 'en'), array('_locale'), null, null),
|
||||
226 => array(array('_route' => 'l', '_locale' => 'en'), array('_locale'), null, null),
|
||||
237 => array(array('_route' => 'm', '_locale' => 'en'), array('_locale'), null, null),
|
||||
256 => array(array('_route' => 'n', '_locale' => 'en'), array('_locale'), null, null),
|
||||
);
|
||||
|
||||
list($ret, $vars, $requiredMethods, $requiredSchemes) = $routes[$m];
|
||||
|
||||
foreach ($vars as $i => $v) {
|
||||
if (isset($matches[1 + $i])) {
|
||||
$ret[$v] = $matches[1 + $i];
|
||||
}
|
||||
}
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if (256 === $m) {
|
||||
break;
|
||||
}
|
||||
$regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m));
|
||||
$offset += strlen($m);
|
||||
}
|
||||
}
|
||||
if ('/' === $pathinfo && !$allow) {
|
||||
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
100
vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher12.php
vendored
Normal file
100
vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher12.php
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
|
||||
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
|
||||
use Symfony\Component\Routing\RequestContext;
|
||||
|
||||
/**
|
||||
* This class has been auto-generated
|
||||
* by the Symfony Routing Component.
|
||||
*/
|
||||
class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
{
|
||||
public function __construct(RequestContext $context)
|
||||
{
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
|
||||
if ('HEAD' === $requestMethod) {
|
||||
$canonicalMethod = 'GET';
|
||||
}
|
||||
|
||||
$matchedPathinfo = $pathinfo;
|
||||
$regexList = array(
|
||||
0 => '{^(?'
|
||||
.'|/abc([^/]++)/(?'
|
||||
.'|1(?'
|
||||
.'|(*:27)'
|
||||
.'|0(?'
|
||||
.'|(*:38)'
|
||||
.'|0(*:46)'
|
||||
.')'
|
||||
.')'
|
||||
.'|2(?'
|
||||
.'|(*:59)'
|
||||
.'|0(?'
|
||||
.'|(*:70)'
|
||||
.'|0(*:78)'
|
||||
.')'
|
||||
.')'
|
||||
.')'
|
||||
.')$}sD',
|
||||
);
|
||||
|
||||
foreach ($regexList as $offset => $regex) {
|
||||
while (preg_match($regex, $matchedPathinfo, $matches)) {
|
||||
switch ($m = (int) $matches['MARK']) {
|
||||
default:
|
||||
$routes = array(
|
||||
27 => array(array('_route' => 'r1'), array('foo'), null, null),
|
||||
38 => array(array('_route' => 'r10'), array('foo'), null, null),
|
||||
46 => array(array('_route' => 'r100'), array('foo'), null, null),
|
||||
59 => array(array('_route' => 'r2'), array('foo'), null, null),
|
||||
70 => array(array('_route' => 'r20'), array('foo'), null, null),
|
||||
78 => array(array('_route' => 'r200'), array('foo'), null, null),
|
||||
);
|
||||
|
||||
list($ret, $vars, $requiredMethods, $requiredSchemes) = $routes[$m];
|
||||
|
||||
foreach ($vars as $i => $v) {
|
||||
if (isset($matches[1 + $i])) {
|
||||
$ret[$v] = $matches[1 + $i];
|
||||
}
|
||||
}
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if (78 === $m) {
|
||||
break;
|
||||
}
|
||||
$regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m));
|
||||
$offset += strlen($m);
|
||||
}
|
||||
}
|
||||
if ('/' === $pathinfo && !$allow) {
|
||||
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
|
||||
}
|
||||
|
||||
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
|
||||
}
|
||||
}
|
69
vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher13.php
vendored
Normal file
69
vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher13.php
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
|
||||
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
|
||||
use Symfony\Component\Routing\RequestContext;
|
||||
|
||||
/**
|
||||
* This class has been auto-generated
|
||||
* by the Symfony Routing Component.
|
||||
*/
|
||||
class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
{
|
||||
public function __construct(RequestContext $context)
|
||||
{
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
$host = strtolower($context->getHost());
|
||||
|
||||
if ('HEAD' === $requestMethod) {
|
||||
$canonicalMethod = 'GET';
|
||||
}
|
||||
|
||||
$matchedPathinfo = $host.'.'.$pathinfo;
|
||||
$regexList = array(
|
||||
0 => '{^(?'
|
||||
.'|(?i:([^\\.]++)\\.exampple\\.com)\\.(?'
|
||||
.'|/abc([^/]++)(?'
|
||||
.'|(*:56)'
|
||||
.')'
|
||||
.')'
|
||||
.')$}sD',
|
||||
);
|
||||
|
||||
foreach ($regexList as $offset => $regex) {
|
||||
while (preg_match($regex, $matchedPathinfo, $matches)) {
|
||||
switch ($m = (int) $matches['MARK']) {
|
||||
case 56:
|
||||
$matches = array('foo' => $matches[1] ?? null, 'foo' => $matches[2] ?? null);
|
||||
|
||||
// r1
|
||||
return $this->mergeDefaults(array('_route' => 'r1') + $matches, array());
|
||||
|
||||
// r2
|
||||
return $this->mergeDefaults(array('_route' => 'r2') + $matches, array());
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (56 === $m) {
|
||||
break;
|
||||
}
|
||||
$regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m));
|
||||
$offset += strlen($m);
|
||||
}
|
||||
}
|
||||
if ('/' === $pathinfo && !$allow) {
|
||||
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
|
||||
}
|
||||
|
||||
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
|
||||
}
|
||||
}
|
@@ -15,366 +15,270 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function match($rawPathinfo)
|
||||
public function match($pathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $ret;
|
||||
}
|
||||
if ($allow) {
|
||||
throw new MethodNotAllowedException(array_keys($allow));
|
||||
}
|
||||
if (!in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
|
||||
// no-op
|
||||
} elseif ($allowSchemes) {
|
||||
redirect_scheme:
|
||||
$scheme = $this->context->getScheme();
|
||||
$this->context->setScheme(key($allowSchemes));
|
||||
try {
|
||||
if ($ret = $this->doMatch($pathinfo)) {
|
||||
return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret;
|
||||
}
|
||||
} finally {
|
||||
$this->context->setScheme($scheme);
|
||||
}
|
||||
} elseif ('/' !== $pathinfo) {
|
||||
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $this->redirect($pathinfo, $ret['_route']) + $ret;
|
||||
}
|
||||
if ($allowSchemes) {
|
||||
goto redirect_scheme;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ResourceNotFoundException();
|
||||
}
|
||||
|
||||
private function doMatch(string $rawPathinfo, array &$allow = array(), array &$allowSchemes = array()): ?array
|
||||
{
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$trimmedPathinfo = rtrim($pathinfo, '/');
|
||||
$context = $this->context;
|
||||
$request = $this->request ?: $this->createRequest($pathinfo);
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
$host = strtolower($context->getHost());
|
||||
|
||||
if ('HEAD' === $requestMethod) {
|
||||
$canonicalMethod = 'GET';
|
||||
}
|
||||
|
||||
if (0 === strpos($pathinfo, '/foo')) {
|
||||
// foo
|
||||
if (preg_match('#^/foo/(?P<bar>baz|symfony)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo')), array ( 'def' => 'test',));
|
||||
}
|
||||
switch ($pathinfo) {
|
||||
default:
|
||||
$routes = array(
|
||||
'/test/baz' => array(array('_route' => 'baz'), null, null, null),
|
||||
'/test/baz.html' => array(array('_route' => 'baz2'), null, null, null),
|
||||
'/test/baz3/' => array(array('_route' => 'baz3'), null, null, null),
|
||||
'/foofoo' => array(array('_route' => 'foofoo', 'def' => 'test'), null, null, null),
|
||||
'/spa ce' => array(array('_route' => 'space'), null, null, null),
|
||||
'/multi/new' => array(array('_route' => 'overridden2'), null, null, null),
|
||||
'/multi/hey/' => array(array('_route' => 'hey'), null, null, null),
|
||||
'/ababa' => array(array('_route' => 'ababa'), null, null, null),
|
||||
'/route1' => array(array('_route' => 'route1'), 'a.example.com', null, null),
|
||||
'/c2/route2' => array(array('_route' => 'route2'), 'a.example.com', null, null),
|
||||
'/route4' => array(array('_route' => 'route4'), 'a.example.com', null, null),
|
||||
'/c2/route3' => array(array('_route' => 'route3'), 'b.example.com', null, null),
|
||||
'/route5' => array(array('_route' => 'route5'), 'c.example.com', null, null),
|
||||
'/route6' => array(array('_route' => 'route6'), null, null, null),
|
||||
'/route11' => array(array('_route' => 'route11'), '#^(?P<var1>[^\\.]++)\\.example\\.com$#sDi', null, null),
|
||||
'/route12' => array(array('_route' => 'route12', 'var1' => 'val'), '#^(?P<var1>[^\\.]++)\\.example\\.com$#sDi', null, null),
|
||||
'/route17' => array(array('_route' => 'route17'), null, null, null),
|
||||
'/secure' => array(array('_route' => 'secure'), null, null, array('https' => 0)),
|
||||
'/nonsecure' => array(array('_route' => 'nonsecure'), null, null, array('http' => 0)),
|
||||
);
|
||||
|
||||
// foofoo
|
||||
if ('/foofoo' === $pathinfo) {
|
||||
return array ( 'def' => 'test', '_route' => 'foofoo',);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
elseif (0 === strpos($pathinfo, '/bar')) {
|
||||
// bar
|
||||
if (preg_match('#^/bar/(?P<foo>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'bar')), array ());
|
||||
if (!in_array($canonicalMethod, array('GET', 'HEAD'))) {
|
||||
$allow = array_merge($allow, array('GET', 'HEAD'));
|
||||
goto not_bar;
|
||||
if (!isset($routes[$pathinfo])) {
|
||||
break;
|
||||
}
|
||||
list($ret, $requiredHost, $requiredMethods, $requiredSchemes) = $routes[$pathinfo];
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_bar:
|
||||
|
||||
// barhead
|
||||
if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P<foo>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'barhead')), array ());
|
||||
if (!in_array($canonicalMethod, array('GET'))) {
|
||||
$allow = array_merge($allow, array('GET'));
|
||||
goto not_barhead;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_barhead:
|
||||
|
||||
}
|
||||
|
||||
elseif (0 === strpos($pathinfo, '/test')) {
|
||||
if (0 === strpos($pathinfo, '/test/baz')) {
|
||||
// baz
|
||||
if ('/test/baz' === $pathinfo) {
|
||||
return array('_route' => 'baz');
|
||||
}
|
||||
|
||||
// baz2
|
||||
if ('/test/baz.html' === $pathinfo) {
|
||||
return array('_route' => 'baz2');
|
||||
}
|
||||
|
||||
// baz3
|
||||
if ('/test/baz3' === $trimmedPathinfo) {
|
||||
$ret = array('_route' => 'baz3');
|
||||
if ('/' === substr($pathinfo, -1)) {
|
||||
// no-op
|
||||
} elseif ('GET' !== $canonicalMethod) {
|
||||
goto not_baz3;
|
||||
} else {
|
||||
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'baz3'));
|
||||
if ($requiredHost) {
|
||||
if ('#' !== $requiredHost[0] ? $requiredHost !== $host : !preg_match($requiredHost, $host, $hostMatches)) {
|
||||
break;
|
||||
}
|
||||
if ('#' === $requiredHost[0] && $hostMatches) {
|
||||
$hostMatches['_route'] = $ret['_route'];
|
||||
$ret = $this->mergeDefaults($hostMatches, $ret);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_baz3:
|
||||
|
||||
}
|
||||
|
||||
// baz4
|
||||
if (preg_match('#^/test/(?P<foo>[^/]++)/?$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'baz4')), array ());
|
||||
if ('/' === substr($pathinfo, -1)) {
|
||||
// no-op
|
||||
} elseif ('GET' !== $canonicalMethod) {
|
||||
goto not_baz4;
|
||||
} else {
|
||||
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'baz4'));
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_baz4:
|
||||
}
|
||||
|
||||
// baz5
|
||||
if (preg_match('#^/test/(?P<foo>[^/]++)/$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'baz5')), array ());
|
||||
if (!in_array($requestMethod, array('POST'))) {
|
||||
$allow = array_merge($allow, array('POST'));
|
||||
goto not_baz5;
|
||||
$matchedPathinfo = $host.'.'.$pathinfo;
|
||||
$regexList = array(
|
||||
0 => '{^(?'
|
||||
.'|(?:(?:[^./]*+\\.)++)(?'
|
||||
.'|/foo/(baz|symfony)(*:47)'
|
||||
.'|/bar(?'
|
||||
.'|/([^/]++)(*:70)'
|
||||
.'|head/([^/]++)(*:90)'
|
||||
.')'
|
||||
.'|/test/([^/]++)/(?'
|
||||
.'|(*:116)'
|
||||
.')'
|
||||
.'|/([\']+)(*:132)'
|
||||
.'|/a/(?'
|
||||
.'|b\'b/([^/]++)(?'
|
||||
.'|(*:161)'
|
||||
.'|(*:169)'
|
||||
.')'
|
||||
.'|(.*)(*:182)'
|
||||
.'|b\'b/([^/]++)(?'
|
||||
.'|(*:205)'
|
||||
.'|(*:213)'
|
||||
.')'
|
||||
.')'
|
||||
.'|/multi/hello(?:/([^/]++))?(*:249)'
|
||||
.'|/([^/]++)/b/([^/]++)(?'
|
||||
.'|(*:280)'
|
||||
.'|(*:288)'
|
||||
.')'
|
||||
.'|/aba/([^/]++)(*:310)'
|
||||
.')|(?i:([^\\.]++)\\.example\\.com)\\.(?'
|
||||
.'|/route1(?'
|
||||
.'|3/([^/]++)(*:372)'
|
||||
.'|4/([^/]++)(*:390)'
|
||||
.')'
|
||||
.')|(?i:c\\.example\\.com)\\.(?'
|
||||
.'|/route15/([^/]++)(*:442)'
|
||||
.')|(?:(?:[^./]*+\\.)++)(?'
|
||||
.'|/route16/([^/]++)(*:490)'
|
||||
.'|/a/(?'
|
||||
.'|a\\.\\.\\.(*:511)'
|
||||
.'|b/(?'
|
||||
.'|([^/]++)(*:532)'
|
||||
.'|c/([^/]++)(*:550)'
|
||||
.')'
|
||||
.')'
|
||||
.')'
|
||||
.')$}sD',
|
||||
);
|
||||
|
||||
foreach ($regexList as $offset => $regex) {
|
||||
while (preg_match($regex, $matchedPathinfo, $matches)) {
|
||||
switch ($m = (int) $matches['MARK']) {
|
||||
case 116:
|
||||
$matches = array('foo' => $matches[1] ?? null);
|
||||
|
||||
// baz4
|
||||
return $this->mergeDefaults(array('_route' => 'baz4') + $matches, array());
|
||||
|
||||
// baz5
|
||||
$ret = $this->mergeDefaults(array('_route' => 'baz5') + $matches, array());
|
||||
if (!isset(($a = array('POST' => 0))[$requestMethod])) {
|
||||
$allow += $a;
|
||||
goto not_baz5;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
not_baz5:
|
||||
|
||||
// baz.baz6
|
||||
$ret = $this->mergeDefaults(array('_route' => 'baz.baz6') + $matches, array());
|
||||
if (!isset(($a = array('PUT' => 0))[$requestMethod])) {
|
||||
$allow += $a;
|
||||
goto not_bazbaz6;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
not_bazbaz6:
|
||||
|
||||
break;
|
||||
case 161:
|
||||
$matches = array('foo' => $matches[1] ?? null);
|
||||
|
||||
// foo1
|
||||
$ret = $this->mergeDefaults(array('_route' => 'foo1') + $matches, array());
|
||||
if (!isset(($a = array('PUT' => 0))[$requestMethod])) {
|
||||
$allow += $a;
|
||||
goto not_foo1;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
not_foo1:
|
||||
|
||||
break;
|
||||
case 205:
|
||||
$matches = array('foo1' => $matches[1] ?? null);
|
||||
|
||||
// foo2
|
||||
return $this->mergeDefaults(array('_route' => 'foo2') + $matches, array());
|
||||
|
||||
break;
|
||||
case 280:
|
||||
$matches = array('_locale' => $matches[1] ?? null, 'foo' => $matches[2] ?? null);
|
||||
|
||||
// foo3
|
||||
return $this->mergeDefaults(array('_route' => 'foo3') + $matches, array());
|
||||
|
||||
break;
|
||||
default:
|
||||
$routes = array(
|
||||
47 => array(array('_route' => 'foo', 'def' => 'test'), array('bar'), null, null),
|
||||
70 => array(array('_route' => 'bar'), array('foo'), array('GET' => 0, 'HEAD' => 1), null),
|
||||
90 => array(array('_route' => 'barhead'), array('foo'), array('GET' => 0), null),
|
||||
132 => array(array('_route' => 'quoter'), array('quoter'), null, null),
|
||||
169 => array(array('_route' => 'bar1'), array('bar'), null, null),
|
||||
182 => array(array('_route' => 'overridden'), array('var'), null, null),
|
||||
213 => array(array('_route' => 'bar2'), array('bar1'), null, null),
|
||||
249 => array(array('_route' => 'helloWorld', 'who' => 'World!'), array('who'), null, null),
|
||||
288 => array(array('_route' => 'bar3'), array('_locale', 'bar'), null, null),
|
||||
310 => array(array('_route' => 'foo4'), array('foo'), null, null),
|
||||
372 => array(array('_route' => 'route13'), array('var1', 'name'), null, null),
|
||||
390 => array(array('_route' => 'route14', 'var1' => 'val'), array('var1', 'name'), null, null),
|
||||
442 => array(array('_route' => 'route15'), array('name'), null, null),
|
||||
490 => array(array('_route' => 'route16', 'var1' => 'val'), array('name'), null, null),
|
||||
511 => array(array('_route' => 'a'), array(), null, null),
|
||||
532 => array(array('_route' => 'b'), array('var'), null, null),
|
||||
550 => array(array('_route' => 'c'), array('var'), null, null),
|
||||
);
|
||||
|
||||
list($ret, $vars, $requiredMethods, $requiredSchemes) = $routes[$m];
|
||||
|
||||
foreach ($vars as $i => $v) {
|
||||
if (isset($matches[1 + $i])) {
|
||||
$ret[$v] = $matches[1 + $i];
|
||||
}
|
||||
}
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_baz5:
|
||||
|
||||
// baz.baz6
|
||||
if (preg_match('#^/test/(?P<foo>[^/]++)/$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'baz.baz6')), array ());
|
||||
if (!in_array($requestMethod, array('PUT'))) {
|
||||
$allow = array_merge($allow, array('PUT'));
|
||||
goto not_bazbaz6;
|
||||
if (550 === $m) {
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
$regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m));
|
||||
$offset += strlen($m);
|
||||
}
|
||||
not_bazbaz6:
|
||||
|
||||
}
|
||||
|
||||
// quoter
|
||||
if (preg_match('#^/(?P<quoter>[\']+)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'quoter')), array ());
|
||||
}
|
||||
|
||||
// space
|
||||
if ('/spa ce' === $pathinfo) {
|
||||
return array('_route' => 'space');
|
||||
}
|
||||
|
||||
if (0 === strpos($pathinfo, '/a')) {
|
||||
if (0 === strpos($pathinfo, '/a/b\'b')) {
|
||||
// foo1
|
||||
if (preg_match('#^/a/b\'b/(?P<foo>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo1')), array ());
|
||||
}
|
||||
|
||||
// bar1
|
||||
if (preg_match('#^/a/b\'b/(?P<bar>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar1')), array ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// overridden
|
||||
if (preg_match('#^/a/(?P<var>.*)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'overridden')), array ());
|
||||
}
|
||||
|
||||
if (0 === strpos($pathinfo, '/a/b\'b')) {
|
||||
// foo2
|
||||
if (preg_match('#^/a/b\'b/(?P<foo1>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo2')), array ());
|
||||
}
|
||||
|
||||
// bar2
|
||||
if (preg_match('#^/a/b\'b/(?P<bar1>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar2')), array ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
elseif (0 === strpos($pathinfo, '/multi')) {
|
||||
// helloWorld
|
||||
if (0 === strpos($pathinfo, '/multi/hello') && preg_match('#^/multi/hello(?:/(?P<who>[^/]++))?$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'helloWorld')), array ( 'who' => 'World!',));
|
||||
}
|
||||
|
||||
// hey
|
||||
if ('/multi/hey' === $trimmedPathinfo) {
|
||||
$ret = array('_route' => 'hey');
|
||||
if ('/' === substr($pathinfo, -1)) {
|
||||
// no-op
|
||||
} elseif ('GET' !== $canonicalMethod) {
|
||||
goto not_hey;
|
||||
} else {
|
||||
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'hey'));
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_hey:
|
||||
|
||||
// overridden2
|
||||
if ('/multi/new' === $pathinfo) {
|
||||
return array('_route' => 'overridden2');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// foo3
|
||||
if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P<foo>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo3')), array ());
|
||||
}
|
||||
|
||||
// bar3
|
||||
if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P<bar>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar3')), array ());
|
||||
}
|
||||
|
||||
if (0 === strpos($pathinfo, '/aba')) {
|
||||
// ababa
|
||||
if ('/ababa' === $pathinfo) {
|
||||
return array('_route' => 'ababa');
|
||||
}
|
||||
|
||||
// foo4
|
||||
if (preg_match('#^/aba/(?P<foo>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo4')), array ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$host = $context->getHost();
|
||||
|
||||
if (preg_match('#^a\\.example\\.com$#sDi', $host, $hostMatches)) {
|
||||
// route1
|
||||
if ('/route1' === $pathinfo) {
|
||||
return array('_route' => 'route1');
|
||||
}
|
||||
|
||||
// route2
|
||||
if ('/c2/route2' === $pathinfo) {
|
||||
return array('_route' => 'route2');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (preg_match('#^b\\.example\\.com$#sDi', $host, $hostMatches)) {
|
||||
// route3
|
||||
if ('/c2/route3' === $pathinfo) {
|
||||
return array('_route' => 'route3');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (preg_match('#^a\\.example\\.com$#sDi', $host, $hostMatches)) {
|
||||
// route4
|
||||
if ('/route4' === $pathinfo) {
|
||||
return array('_route' => 'route4');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (preg_match('#^c\\.example\\.com$#sDi', $host, $hostMatches)) {
|
||||
// route5
|
||||
if ('/route5' === $pathinfo) {
|
||||
return array('_route' => 'route5');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// route6
|
||||
if ('/route6' === $pathinfo) {
|
||||
return array('_route' => 'route6');
|
||||
}
|
||||
|
||||
if (preg_match('#^(?P<var1>[^\\.]++)\\.example\\.com$#sDi', $host, $hostMatches)) {
|
||||
if (0 === strpos($pathinfo, '/route1')) {
|
||||
// route11
|
||||
if ('/route11' === $pathinfo) {
|
||||
return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route11')), array ());
|
||||
}
|
||||
|
||||
// route12
|
||||
if ('/route12' === $pathinfo) {
|
||||
return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route12')), array ( 'var1' => 'val',));
|
||||
}
|
||||
|
||||
// route13
|
||||
if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?P<name>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route13')), array ());
|
||||
}
|
||||
|
||||
// route14
|
||||
if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?P<name>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route14')), array ( 'var1' => 'val',));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (preg_match('#^c\\.example\\.com$#sDi', $host, $hostMatches)) {
|
||||
// route15
|
||||
if (0 === strpos($pathinfo, '/route15') && preg_match('#^/route15/(?P<name>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'route15')), array ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// route16
|
||||
if (0 === strpos($pathinfo, '/route16') && preg_match('#^/route16/(?P<name>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'route16')), array ( 'var1' => 'val',));
|
||||
}
|
||||
|
||||
// route17
|
||||
if ('/route17' === $pathinfo) {
|
||||
return array('_route' => 'route17');
|
||||
}
|
||||
|
||||
// a
|
||||
if ('/a/a...' === $pathinfo) {
|
||||
return array('_route' => 'a');
|
||||
}
|
||||
|
||||
if (0 === strpos($pathinfo, '/a/b')) {
|
||||
// b
|
||||
if (preg_match('#^/a/b/(?P<var>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'b')), array ());
|
||||
}
|
||||
|
||||
// c
|
||||
if (0 === strpos($pathinfo, '/a/b/c') && preg_match('#^/a/b/c/(?P<var>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'c')), array ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// secure
|
||||
if ('/secure' === $pathinfo) {
|
||||
$ret = array('_route' => 'secure');
|
||||
$requiredSchemes = array ( 'https' => 0,);
|
||||
if (!isset($requiredSchemes[$context->getScheme()])) {
|
||||
if ('GET' !== $canonicalMethod) {
|
||||
goto not_secure;
|
||||
}
|
||||
|
||||
return array_replace($ret, $this->redirect($rawPathinfo, 'secure', key($requiredSchemes)));
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_secure:
|
||||
|
||||
// nonsecure
|
||||
if ('/nonsecure' === $pathinfo) {
|
||||
$ret = array('_route' => 'nonsecure');
|
||||
$requiredSchemes = array ( 'http' => 0,);
|
||||
if (!isset($requiredSchemes[$context->getScheme()])) {
|
||||
if ('GET' !== $canonicalMethod) {
|
||||
goto not_nonsecure;
|
||||
}
|
||||
|
||||
return array_replace($ret, $this->redirect($rawPathinfo, 'nonsecure', key($requiredSchemes)));
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_nonsecure:
|
||||
|
||||
if ('/' === $pathinfo && !$allow) {
|
||||
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
|
||||
}
|
||||
|
||||
throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@@ -17,39 +17,96 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$trimmedPathinfo = rtrim($pathinfo, '/');
|
||||
$context = $this->context;
|
||||
$request = $this->request ?: $this->createRequest($pathinfo);
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
|
||||
if ('HEAD' === $requestMethod) {
|
||||
$canonicalMethod = 'GET';
|
||||
}
|
||||
|
||||
if (0 === strpos($pathinfo, '/rootprefix')) {
|
||||
// static
|
||||
if ('/rootprefix/test' === $pathinfo) {
|
||||
return array('_route' => 'static');
|
||||
}
|
||||
switch ($pathinfo) {
|
||||
case '/with-condition':
|
||||
// with-condition
|
||||
if (($context->getMethod() == "GET")) {
|
||||
return array('_route' => 'with-condition');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$routes = array(
|
||||
'/rootprefix/test' => array(array('_route' => 'static'), null, null, null),
|
||||
);
|
||||
|
||||
// dynamic
|
||||
if (preg_match('#^/rootprefix/(?P<var>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'dynamic')), array ());
|
||||
}
|
||||
if (!isset($routes[$pathinfo])) {
|
||||
break;
|
||||
}
|
||||
list($ret, $requiredHost, $requiredMethods, $requiredSchemes) = $routes[$pathinfo];
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
// with-condition
|
||||
if ('/with-condition' === $pathinfo && ($context->getMethod() == "GET")) {
|
||||
return array('_route' => 'with-condition');
|
||||
}
|
||||
$matchedPathinfo = $pathinfo;
|
||||
$regexList = array(
|
||||
0 => '{^(?'
|
||||
.'|/rootprefix/([^/]++)(*:27)'
|
||||
.')$}sD',
|
||||
);
|
||||
|
||||
foreach ($regexList as $offset => $regex) {
|
||||
while (preg_match($regex, $matchedPathinfo, $matches)) {
|
||||
switch ($m = (int) $matches['MARK']) {
|
||||
default:
|
||||
$routes = array(
|
||||
27 => array(array('_route' => 'dynamic'), array('var'), null, null),
|
||||
);
|
||||
|
||||
list($ret, $vars, $requiredMethods, $requiredSchemes) = $routes[$m];
|
||||
|
||||
foreach ($vars as $i => $v) {
|
||||
if (isset($matches[1 + $i])) {
|
||||
$ret[$v] = $matches[1 + $i];
|
||||
}
|
||||
}
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if (27 === $m) {
|
||||
break;
|
||||
}
|
||||
$regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m));
|
||||
$offset += strlen($m);
|
||||
}
|
||||
}
|
||||
if ('/' === $pathinfo && !$allow) {
|
||||
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
|
||||
}
|
||||
|
||||
throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException();
|
||||
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
|
||||
}
|
||||
}
|
||||
|
@@ -17,96 +17,68 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$trimmedPathinfo = rtrim($pathinfo, '/');
|
||||
$context = $this->context;
|
||||
$request = $this->request ?: $this->createRequest($pathinfo);
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
|
||||
if ('HEAD' === $requestMethod) {
|
||||
$canonicalMethod = 'GET';
|
||||
}
|
||||
|
||||
// just_head
|
||||
if ('/just_head' === $pathinfo) {
|
||||
$ret = array('_route' => 'just_head');
|
||||
if (!in_array($requestMethod, array('HEAD'))) {
|
||||
$allow = array_merge($allow, array('HEAD'));
|
||||
goto not_just_head;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_just_head:
|
||||
|
||||
// head_and_get
|
||||
if ('/head_and_get' === $pathinfo) {
|
||||
$ret = array('_route' => 'head_and_get');
|
||||
if (!in_array($canonicalMethod, array('HEAD', 'GET'))) {
|
||||
$allow = array_merge($allow, array('HEAD', 'GET'));
|
||||
goto not_head_and_get;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_head_and_get:
|
||||
|
||||
// get_and_head
|
||||
if ('/get_and_head' === $pathinfo) {
|
||||
$ret = array('_route' => 'get_and_head');
|
||||
if (!in_array($canonicalMethod, array('GET', 'HEAD'))) {
|
||||
$allow = array_merge($allow, array('GET', 'HEAD'));
|
||||
goto not_get_and_head;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_get_and_head:
|
||||
|
||||
// post_and_head
|
||||
if ('/post_and_head' === $pathinfo) {
|
||||
$ret = array('_route' => 'post_and_head');
|
||||
if (!in_array($requestMethod, array('POST', 'HEAD'))) {
|
||||
$allow = array_merge($allow, array('POST', 'HEAD'));
|
||||
goto not_post_and_head;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_post_and_head:
|
||||
|
||||
if (0 === strpos($pathinfo, '/put_and_post')) {
|
||||
// put_and_post
|
||||
if ('/put_and_post' === $pathinfo) {
|
||||
switch ($pathinfo) {
|
||||
case '/put_and_post':
|
||||
// put_and_post
|
||||
$ret = array('_route' => 'put_and_post');
|
||||
if (!in_array($requestMethod, array('PUT', 'POST'))) {
|
||||
$allow = array_merge($allow, array('PUT', 'POST'));
|
||||
if (!isset(($a = array('PUT' => 0, 'POST' => 1))[$requestMethod])) {
|
||||
$allow += $a;
|
||||
goto not_put_and_post;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_put_and_post:
|
||||
|
||||
// put_and_get_and_head
|
||||
if ('/put_and_post' === $pathinfo) {
|
||||
not_put_and_post:
|
||||
// put_and_get_and_head
|
||||
$ret = array('_route' => 'put_and_get_and_head');
|
||||
if (!in_array($canonicalMethod, array('PUT', 'GET', 'HEAD'))) {
|
||||
$allow = array_merge($allow, array('PUT', 'GET', 'HEAD'));
|
||||
if (!isset(($a = array('PUT' => 0, 'GET' => 1, 'HEAD' => 2))[$canonicalMethod])) {
|
||||
$allow += $a;
|
||||
goto not_put_and_get_and_head;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_put_and_get_and_head:
|
||||
not_put_and_get_and_head:
|
||||
break;
|
||||
default:
|
||||
$routes = array(
|
||||
'/just_head' => array(array('_route' => 'just_head'), null, array('HEAD' => 0), null),
|
||||
'/head_and_get' => array(array('_route' => 'head_and_get'), null, array('HEAD' => 0, 'GET' => 1), null),
|
||||
'/get_and_head' => array(array('_route' => 'get_and_head'), null, array('GET' => 0, 'HEAD' => 1), null),
|
||||
'/post_and_head' => array(array('_route' => 'post_and_head'), null, array('POST' => 0, 'HEAD' => 1), null),
|
||||
);
|
||||
|
||||
if (!isset($routes[$pathinfo])) {
|
||||
break;
|
||||
}
|
||||
list($ret, $requiredHost, $requiredMethods, $requiredSchemes) = $routes[$pathinfo];
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if ('/' === $pathinfo && !$allow) {
|
||||
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
|
||||
}
|
||||
|
||||
throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException();
|
||||
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
|
||||
}
|
||||
}
|
||||
|
@@ -15,195 +15,140 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function match($rawPathinfo)
|
||||
public function match($pathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $ret;
|
||||
}
|
||||
if ($allow) {
|
||||
throw new MethodNotAllowedException(array_keys($allow));
|
||||
}
|
||||
if (!in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
|
||||
// no-op
|
||||
} elseif ($allowSchemes) {
|
||||
redirect_scheme:
|
||||
$scheme = $this->context->getScheme();
|
||||
$this->context->setScheme(key($allowSchemes));
|
||||
try {
|
||||
if ($ret = $this->doMatch($pathinfo)) {
|
||||
return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret;
|
||||
}
|
||||
} finally {
|
||||
$this->context->setScheme($scheme);
|
||||
}
|
||||
} elseif ('/' !== $pathinfo) {
|
||||
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $this->redirect($pathinfo, $ret['_route']) + $ret;
|
||||
}
|
||||
if ($allowSchemes) {
|
||||
goto redirect_scheme;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ResourceNotFoundException();
|
||||
}
|
||||
|
||||
private function doMatch(string $rawPathinfo, array &$allow = array(), array &$allowSchemes = array()): ?array
|
||||
{
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$trimmedPathinfo = rtrim($pathinfo, '/');
|
||||
$context = $this->context;
|
||||
$request = $this->request ?: $this->createRequest($pathinfo);
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
|
||||
if ('HEAD' === $requestMethod) {
|
||||
$canonicalMethod = 'GET';
|
||||
}
|
||||
|
||||
if (0 === strpos($pathinfo, '/a')) {
|
||||
// a_first
|
||||
if ('/a/11' === $pathinfo) {
|
||||
return array('_route' => 'a_first');
|
||||
}
|
||||
switch ($pathinfo) {
|
||||
default:
|
||||
$routes = array(
|
||||
'/a/11' => array(array('_route' => 'a_first'), null, null, null),
|
||||
'/a/22' => array(array('_route' => 'a_second'), null, null, null),
|
||||
'/a/333' => array(array('_route' => 'a_third'), null, null, null),
|
||||
'/a/44/' => array(array('_route' => 'a_fourth'), null, null, null),
|
||||
'/a/55/' => array(array('_route' => 'a_fifth'), null, null, null),
|
||||
'/a/66/' => array(array('_route' => 'a_sixth'), null, null, null),
|
||||
'/nested/group/a/' => array(array('_route' => 'nested_a'), null, null, null),
|
||||
'/nested/group/b/' => array(array('_route' => 'nested_b'), null, null, null),
|
||||
'/nested/group/c/' => array(array('_route' => 'nested_c'), null, null, null),
|
||||
'/slashed/group/' => array(array('_route' => 'slashed_a'), null, null, null),
|
||||
'/slashed/group/b/' => array(array('_route' => 'slashed_b'), null, null, null),
|
||||
'/slashed/group/c/' => array(array('_route' => 'slashed_c'), null, null, null),
|
||||
);
|
||||
|
||||
// a_second
|
||||
if ('/a/22' === $pathinfo) {
|
||||
return array('_route' => 'a_second');
|
||||
}
|
||||
if (!isset($routes[$pathinfo])) {
|
||||
break;
|
||||
}
|
||||
list($ret, $requiredHost, $requiredMethods, $requiredSchemes) = $routes[$pathinfo];
|
||||
|
||||
// a_third
|
||||
if ('/a/333' === $pathinfo) {
|
||||
return array('_route' => 'a_third');
|
||||
}
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
// a_wildcard
|
||||
if (preg_match('#^/(?P<param>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'a_wildcard')), array ());
|
||||
$matchedPathinfo = $pathinfo;
|
||||
$regexList = array(
|
||||
0 => '{^(?'
|
||||
.'|/([^/]++)(*:16)'
|
||||
.'|/nested/([^/]++)(*:39)'
|
||||
.')$}sD',
|
||||
);
|
||||
|
||||
foreach ($regexList as $offset => $regex) {
|
||||
while (preg_match($regex, $matchedPathinfo, $matches)) {
|
||||
switch ($m = (int) $matches['MARK']) {
|
||||
default:
|
||||
$routes = array(
|
||||
16 => array(array('_route' => 'a_wildcard'), array('param'), null, null),
|
||||
39 => array(array('_route' => 'nested_wildcard'), array('param'), null, null),
|
||||
);
|
||||
|
||||
list($ret, $vars, $requiredMethods, $requiredSchemes) = $routes[$m];
|
||||
|
||||
foreach ($vars as $i => $v) {
|
||||
if (isset($matches[1 + $i])) {
|
||||
$ret[$v] = $matches[1 + $i];
|
||||
}
|
||||
}
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if (39 === $m) {
|
||||
break;
|
||||
}
|
||||
$regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m));
|
||||
$offset += strlen($m);
|
||||
}
|
||||
}
|
||||
|
||||
if (0 === strpos($pathinfo, '/a')) {
|
||||
// a_fourth
|
||||
if ('/a/44' === $trimmedPathinfo) {
|
||||
$ret = array('_route' => 'a_fourth');
|
||||
if ('/' === substr($pathinfo, -1)) {
|
||||
// no-op
|
||||
} elseif ('GET' !== $canonicalMethod) {
|
||||
goto not_a_fourth;
|
||||
} else {
|
||||
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'a_fourth'));
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_a_fourth:
|
||||
|
||||
// a_fifth
|
||||
if ('/a/55' === $trimmedPathinfo) {
|
||||
$ret = array('_route' => 'a_fifth');
|
||||
if ('/' === substr($pathinfo, -1)) {
|
||||
// no-op
|
||||
} elseif ('GET' !== $canonicalMethod) {
|
||||
goto not_a_fifth;
|
||||
} else {
|
||||
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'a_fifth'));
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_a_fifth:
|
||||
|
||||
// a_sixth
|
||||
if ('/a/66' === $trimmedPathinfo) {
|
||||
$ret = array('_route' => 'a_sixth');
|
||||
if ('/' === substr($pathinfo, -1)) {
|
||||
// no-op
|
||||
} elseif ('GET' !== $canonicalMethod) {
|
||||
goto not_a_sixth;
|
||||
} else {
|
||||
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'a_sixth'));
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_a_sixth:
|
||||
|
||||
}
|
||||
|
||||
// nested_wildcard
|
||||
if (0 === strpos($pathinfo, '/nested') && preg_match('#^/nested/(?P<param>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'nested_wildcard')), array ());
|
||||
}
|
||||
|
||||
if (0 === strpos($pathinfo, '/nested/group')) {
|
||||
// nested_a
|
||||
if ('/nested/group/a' === $trimmedPathinfo) {
|
||||
$ret = array('_route' => 'nested_a');
|
||||
if ('/' === substr($pathinfo, -1)) {
|
||||
// no-op
|
||||
} elseif ('GET' !== $canonicalMethod) {
|
||||
goto not_nested_a;
|
||||
} else {
|
||||
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'nested_a'));
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_nested_a:
|
||||
|
||||
// nested_b
|
||||
if ('/nested/group/b' === $trimmedPathinfo) {
|
||||
$ret = array('_route' => 'nested_b');
|
||||
if ('/' === substr($pathinfo, -1)) {
|
||||
// no-op
|
||||
} elseif ('GET' !== $canonicalMethod) {
|
||||
goto not_nested_b;
|
||||
} else {
|
||||
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'nested_b'));
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_nested_b:
|
||||
|
||||
// nested_c
|
||||
if ('/nested/group/c' === $trimmedPathinfo) {
|
||||
$ret = array('_route' => 'nested_c');
|
||||
if ('/' === substr($pathinfo, -1)) {
|
||||
// no-op
|
||||
} elseif ('GET' !== $canonicalMethod) {
|
||||
goto not_nested_c;
|
||||
} else {
|
||||
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'nested_c'));
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_nested_c:
|
||||
|
||||
}
|
||||
|
||||
elseif (0 === strpos($pathinfo, '/slashed/group')) {
|
||||
// slashed_a
|
||||
if ('/slashed/group' === $trimmedPathinfo) {
|
||||
$ret = array('_route' => 'slashed_a');
|
||||
if ('/' === substr($pathinfo, -1)) {
|
||||
// no-op
|
||||
} elseif ('GET' !== $canonicalMethod) {
|
||||
goto not_slashed_a;
|
||||
} else {
|
||||
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'slashed_a'));
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_slashed_a:
|
||||
|
||||
// slashed_b
|
||||
if ('/slashed/group/b' === $trimmedPathinfo) {
|
||||
$ret = array('_route' => 'slashed_b');
|
||||
if ('/' === substr($pathinfo, -1)) {
|
||||
// no-op
|
||||
} elseif ('GET' !== $canonicalMethod) {
|
||||
goto not_slashed_b;
|
||||
} else {
|
||||
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'slashed_b'));
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_slashed_b:
|
||||
|
||||
// slashed_c
|
||||
if ('/slashed/group/c' === $trimmedPathinfo) {
|
||||
$ret = array('_route' => 'slashed_c');
|
||||
if ('/' === substr($pathinfo, -1)) {
|
||||
// no-op
|
||||
} elseif ('GET' !== $canonicalMethod) {
|
||||
goto not_slashed_c;
|
||||
} else {
|
||||
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'slashed_c'));
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_slashed_c:
|
||||
|
||||
}
|
||||
|
||||
if ('/' === $pathinfo && !$allow) {
|
||||
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
|
||||
}
|
||||
|
||||
throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@@ -17,197 +17,115 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$trimmedPathinfo = rtrim($pathinfo, '/');
|
||||
$context = $this->context;
|
||||
$request = $this->request ?: $this->createRequest($pathinfo);
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
|
||||
if ('HEAD' === $requestMethod) {
|
||||
$canonicalMethod = 'GET';
|
||||
}
|
||||
|
||||
if (0 === strpos($pathinfo, '/trailing/simple')) {
|
||||
// simple_trailing_slash_no_methods
|
||||
if ('/trailing/simple/no-methods/' === $pathinfo) {
|
||||
return array('_route' => 'simple_trailing_slash_no_methods');
|
||||
}
|
||||
switch ($pathinfo) {
|
||||
default:
|
||||
$routes = array(
|
||||
'/trailing/simple/no-methods/' => array(array('_route' => 'simple_trailing_slash_no_methods'), null, null, null),
|
||||
'/trailing/simple/get-method/' => array(array('_route' => 'simple_trailing_slash_GET_method'), null, array('GET' => 0), null),
|
||||
'/trailing/simple/head-method/' => array(array('_route' => 'simple_trailing_slash_HEAD_method'), null, array('HEAD' => 0), null),
|
||||
'/trailing/simple/post-method/' => array(array('_route' => 'simple_trailing_slash_POST_method'), null, array('POST' => 0), null),
|
||||
'/not-trailing/simple/no-methods' => array(array('_route' => 'simple_not_trailing_slash_no_methods'), null, null, null),
|
||||
'/not-trailing/simple/get-method' => array(array('_route' => 'simple_not_trailing_slash_GET_method'), null, array('GET' => 0), null),
|
||||
'/not-trailing/simple/head-method' => array(array('_route' => 'simple_not_trailing_slash_HEAD_method'), null, array('HEAD' => 0), null),
|
||||
'/not-trailing/simple/post-method' => array(array('_route' => 'simple_not_trailing_slash_POST_method'), null, array('POST' => 0), null),
|
||||
);
|
||||
|
||||
// simple_trailing_slash_GET_method
|
||||
if ('/trailing/simple/get-method/' === $pathinfo) {
|
||||
$ret = array('_route' => 'simple_trailing_slash_GET_method');
|
||||
if (!in_array($canonicalMethod, array('GET'))) {
|
||||
$allow = array_merge($allow, array('GET'));
|
||||
goto not_simple_trailing_slash_GET_method;
|
||||
if (!isset($routes[$pathinfo])) {
|
||||
break;
|
||||
}
|
||||
list($ret, $requiredHost, $requiredMethods, $requiredSchemes) = $routes[$pathinfo];
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_simple_trailing_slash_GET_method:
|
||||
|
||||
// simple_trailing_slash_HEAD_method
|
||||
if ('/trailing/simple/head-method/' === $pathinfo) {
|
||||
$ret = array('_route' => 'simple_trailing_slash_HEAD_method');
|
||||
if (!in_array($requestMethod, array('HEAD'))) {
|
||||
$allow = array_merge($allow, array('HEAD'));
|
||||
goto not_simple_trailing_slash_HEAD_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_simple_trailing_slash_HEAD_method:
|
||||
|
||||
// simple_trailing_slash_POST_method
|
||||
if ('/trailing/simple/post-method/' === $pathinfo) {
|
||||
$ret = array('_route' => 'simple_trailing_slash_POST_method');
|
||||
if (!in_array($requestMethod, array('POST'))) {
|
||||
$allow = array_merge($allow, array('POST'));
|
||||
goto not_simple_trailing_slash_POST_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_simple_trailing_slash_POST_method:
|
||||
|
||||
}
|
||||
|
||||
elseif (0 === strpos($pathinfo, '/trailing/regex')) {
|
||||
// regex_trailing_slash_no_methods
|
||||
if (0 === strpos($pathinfo, '/trailing/regex/no-methods') && preg_match('#^/trailing/regex/no\\-methods/(?P<param>[^/]++)/$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_no_methods')), array ());
|
||||
}
|
||||
$matchedPathinfo = $pathinfo;
|
||||
$regexList = array(
|
||||
0 => '{^(?'
|
||||
.'|/trailing/regex/(?'
|
||||
.'|no\\-methods/([^/]++)/(*:47)'
|
||||
.'|get\\-method/([^/]++)/(*:75)'
|
||||
.'|head\\-method/([^/]++)/(*:104)'
|
||||
.'|post\\-method/([^/]++)/(*:134)'
|
||||
.')'
|
||||
.'|/not\\-trailing/regex/(?'
|
||||
.'|no\\-methods/([^/]++)(*:187)'
|
||||
.'|get\\-method/([^/]++)(*:215)'
|
||||
.'|head\\-method/([^/]++)(*:244)'
|
||||
.'|post\\-method/([^/]++)(*:273)'
|
||||
.')'
|
||||
.')$}sD',
|
||||
);
|
||||
|
||||
// regex_trailing_slash_GET_method
|
||||
if (0 === strpos($pathinfo, '/trailing/regex/get-method') && preg_match('#^/trailing/regex/get\\-method/(?P<param>[^/]++)/$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_GET_method')), array ());
|
||||
if (!in_array($canonicalMethod, array('GET'))) {
|
||||
$allow = array_merge($allow, array('GET'));
|
||||
goto not_regex_trailing_slash_GET_method;
|
||||
foreach ($regexList as $offset => $regex) {
|
||||
while (preg_match($regex, $matchedPathinfo, $matches)) {
|
||||
switch ($m = (int) $matches['MARK']) {
|
||||
default:
|
||||
$routes = array(
|
||||
47 => array(array('_route' => 'regex_trailing_slash_no_methods'), array('param'), null, null),
|
||||
75 => array(array('_route' => 'regex_trailing_slash_GET_method'), array('param'), array('GET' => 0), null),
|
||||
104 => array(array('_route' => 'regex_trailing_slash_HEAD_method'), array('param'), array('HEAD' => 0), null),
|
||||
134 => array(array('_route' => 'regex_trailing_slash_POST_method'), array('param'), array('POST' => 0), null),
|
||||
187 => array(array('_route' => 'regex_not_trailing_slash_no_methods'), array('param'), null, null),
|
||||
215 => array(array('_route' => 'regex_not_trailing_slash_GET_method'), array('param'), array('GET' => 0), null),
|
||||
244 => array(array('_route' => 'regex_not_trailing_slash_HEAD_method'), array('param'), array('HEAD' => 0), null),
|
||||
273 => array(array('_route' => 'regex_not_trailing_slash_POST_method'), array('param'), array('POST' => 0), null),
|
||||
);
|
||||
|
||||
list($ret, $vars, $requiredMethods, $requiredSchemes) = $routes[$m];
|
||||
|
||||
foreach ($vars as $i => $v) {
|
||||
if (isset($matches[1 + $i])) {
|
||||
$ret[$v] = $matches[1 + $i];
|
||||
}
|
||||
}
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_regex_trailing_slash_GET_method:
|
||||
|
||||
// regex_trailing_slash_HEAD_method
|
||||
if (0 === strpos($pathinfo, '/trailing/regex/head-method') && preg_match('#^/trailing/regex/head\\-method/(?P<param>[^/]++)/$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_HEAD_method')), array ());
|
||||
if (!in_array($requestMethod, array('HEAD'))) {
|
||||
$allow = array_merge($allow, array('HEAD'));
|
||||
goto not_regex_trailing_slash_HEAD_method;
|
||||
if (273 === $m) {
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
$regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m));
|
||||
$offset += strlen($m);
|
||||
}
|
||||
not_regex_trailing_slash_HEAD_method:
|
||||
|
||||
// regex_trailing_slash_POST_method
|
||||
if (0 === strpos($pathinfo, '/trailing/regex/post-method') && preg_match('#^/trailing/regex/post\\-method/(?P<param>[^/]++)/$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_POST_method')), array ());
|
||||
if (!in_array($requestMethod, array('POST'))) {
|
||||
$allow = array_merge($allow, array('POST'));
|
||||
goto not_regex_trailing_slash_POST_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_regex_trailing_slash_POST_method:
|
||||
|
||||
}
|
||||
|
||||
elseif (0 === strpos($pathinfo, '/not-trailing/simple')) {
|
||||
// simple_not_trailing_slash_no_methods
|
||||
if ('/not-trailing/simple/no-methods' === $pathinfo) {
|
||||
return array('_route' => 'simple_not_trailing_slash_no_methods');
|
||||
}
|
||||
|
||||
// simple_not_trailing_slash_GET_method
|
||||
if ('/not-trailing/simple/get-method' === $pathinfo) {
|
||||
$ret = array('_route' => 'simple_not_trailing_slash_GET_method');
|
||||
if (!in_array($canonicalMethod, array('GET'))) {
|
||||
$allow = array_merge($allow, array('GET'));
|
||||
goto not_simple_not_trailing_slash_GET_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_simple_not_trailing_slash_GET_method:
|
||||
|
||||
// simple_not_trailing_slash_HEAD_method
|
||||
if ('/not-trailing/simple/head-method' === $pathinfo) {
|
||||
$ret = array('_route' => 'simple_not_trailing_slash_HEAD_method');
|
||||
if (!in_array($requestMethod, array('HEAD'))) {
|
||||
$allow = array_merge($allow, array('HEAD'));
|
||||
goto not_simple_not_trailing_slash_HEAD_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_simple_not_trailing_slash_HEAD_method:
|
||||
|
||||
// simple_not_trailing_slash_POST_method
|
||||
if ('/not-trailing/simple/post-method' === $pathinfo) {
|
||||
$ret = array('_route' => 'simple_not_trailing_slash_POST_method');
|
||||
if (!in_array($requestMethod, array('POST'))) {
|
||||
$allow = array_merge($allow, array('POST'));
|
||||
goto not_simple_not_trailing_slash_POST_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_simple_not_trailing_slash_POST_method:
|
||||
|
||||
}
|
||||
|
||||
elseif (0 === strpos($pathinfo, '/not-trailing/regex')) {
|
||||
// regex_not_trailing_slash_no_methods
|
||||
if (0 === strpos($pathinfo, '/not-trailing/regex/no-methods') && preg_match('#^/not\\-trailing/regex/no\\-methods/(?P<param>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_no_methods')), array ());
|
||||
}
|
||||
|
||||
// regex_not_trailing_slash_GET_method
|
||||
if (0 === strpos($pathinfo, '/not-trailing/regex/get-method') && preg_match('#^/not\\-trailing/regex/get\\-method/(?P<param>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_GET_method')), array ());
|
||||
if (!in_array($canonicalMethod, array('GET'))) {
|
||||
$allow = array_merge($allow, array('GET'));
|
||||
goto not_regex_not_trailing_slash_GET_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_regex_not_trailing_slash_GET_method:
|
||||
|
||||
// regex_not_trailing_slash_HEAD_method
|
||||
if (0 === strpos($pathinfo, '/not-trailing/regex/head-method') && preg_match('#^/not\\-trailing/regex/head\\-method/(?P<param>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_HEAD_method')), array ());
|
||||
if (!in_array($requestMethod, array('HEAD'))) {
|
||||
$allow = array_merge($allow, array('HEAD'));
|
||||
goto not_regex_not_trailing_slash_HEAD_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_regex_not_trailing_slash_HEAD_method:
|
||||
|
||||
// regex_not_trailing_slash_POST_method
|
||||
if (0 === strpos($pathinfo, '/not-trailing/regex/post-method') && preg_match('#^/not\\-trailing/regex/post\\-method/(?P<param>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_POST_method')), array ());
|
||||
if (!in_array($requestMethod, array('POST'))) {
|
||||
$allow = array_merge($allow, array('POST'));
|
||||
goto not_regex_not_trailing_slash_POST_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_regex_not_trailing_slash_POST_method:
|
||||
|
||||
}
|
||||
|
||||
if ('/' === $pathinfo && !$allow) {
|
||||
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
|
||||
}
|
||||
|
||||
throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException();
|
||||
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
|
||||
}
|
||||
}
|
||||
|
@@ -15,235 +15,152 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function match($rawPathinfo)
|
||||
public function match($pathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $ret;
|
||||
}
|
||||
if ($allow) {
|
||||
throw new MethodNotAllowedException(array_keys($allow));
|
||||
}
|
||||
if (!in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
|
||||
// no-op
|
||||
} elseif ($allowSchemes) {
|
||||
redirect_scheme:
|
||||
$scheme = $this->context->getScheme();
|
||||
$this->context->setScheme(key($allowSchemes));
|
||||
try {
|
||||
if ($ret = $this->doMatch($pathinfo)) {
|
||||
return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret;
|
||||
}
|
||||
} finally {
|
||||
$this->context->setScheme($scheme);
|
||||
}
|
||||
} elseif ('/' !== $pathinfo) {
|
||||
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $this->redirect($pathinfo, $ret['_route']) + $ret;
|
||||
}
|
||||
if ($allowSchemes) {
|
||||
goto redirect_scheme;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ResourceNotFoundException();
|
||||
}
|
||||
|
||||
private function doMatch(string $rawPathinfo, array &$allow = array(), array &$allowSchemes = array()): ?array
|
||||
{
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$trimmedPathinfo = rtrim($pathinfo, '/');
|
||||
$context = $this->context;
|
||||
$request = $this->request ?: $this->createRequest($pathinfo);
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
|
||||
if ('HEAD' === $requestMethod) {
|
||||
$canonicalMethod = 'GET';
|
||||
}
|
||||
|
||||
if (0 === strpos($pathinfo, '/trailing/simple')) {
|
||||
// simple_trailing_slash_no_methods
|
||||
if ('/trailing/simple/no-methods' === $trimmedPathinfo) {
|
||||
$ret = array('_route' => 'simple_trailing_slash_no_methods');
|
||||
if ('/' === substr($pathinfo, -1)) {
|
||||
// no-op
|
||||
} elseif ('GET' !== $canonicalMethod) {
|
||||
goto not_simple_trailing_slash_no_methods;
|
||||
} else {
|
||||
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'simple_trailing_slash_no_methods'));
|
||||
switch ($pathinfo) {
|
||||
default:
|
||||
$routes = array(
|
||||
'/trailing/simple/no-methods/' => array(array('_route' => 'simple_trailing_slash_no_methods'), null, null, null),
|
||||
'/trailing/simple/get-method/' => array(array('_route' => 'simple_trailing_slash_GET_method'), null, array('GET' => 0), null),
|
||||
'/trailing/simple/head-method/' => array(array('_route' => 'simple_trailing_slash_HEAD_method'), null, array('HEAD' => 0), null),
|
||||
'/trailing/simple/post-method/' => array(array('_route' => 'simple_trailing_slash_POST_method'), null, array('POST' => 0), null),
|
||||
'/not-trailing/simple/no-methods' => array(array('_route' => 'simple_not_trailing_slash_no_methods'), null, null, null),
|
||||
'/not-trailing/simple/get-method' => array(array('_route' => 'simple_not_trailing_slash_GET_method'), null, array('GET' => 0), null),
|
||||
'/not-trailing/simple/head-method' => array(array('_route' => 'simple_not_trailing_slash_HEAD_method'), null, array('HEAD' => 0), null),
|
||||
'/not-trailing/simple/post-method' => array(array('_route' => 'simple_not_trailing_slash_POST_method'), null, array('POST' => 0), null),
|
||||
);
|
||||
|
||||
if (!isset($routes[$pathinfo])) {
|
||||
break;
|
||||
}
|
||||
list($ret, $requiredHost, $requiredMethods, $requiredSchemes) = $routes[$pathinfo];
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_simple_trailing_slash_no_methods:
|
||||
|
||||
// simple_trailing_slash_GET_method
|
||||
if ('/trailing/simple/get-method' === $trimmedPathinfo) {
|
||||
$ret = array('_route' => 'simple_trailing_slash_GET_method');
|
||||
if ('/' === substr($pathinfo, -1)) {
|
||||
// no-op
|
||||
} elseif ('GET' !== $canonicalMethod) {
|
||||
goto not_simple_trailing_slash_GET_method;
|
||||
} else {
|
||||
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'simple_trailing_slash_GET_method'));
|
||||
}
|
||||
|
||||
if (!in_array($canonicalMethod, array('GET'))) {
|
||||
$allow = array_merge($allow, array('GET'));
|
||||
goto not_simple_trailing_slash_GET_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_simple_trailing_slash_GET_method:
|
||||
|
||||
// simple_trailing_slash_HEAD_method
|
||||
if ('/trailing/simple/head-method/' === $pathinfo) {
|
||||
$ret = array('_route' => 'simple_trailing_slash_HEAD_method');
|
||||
if (!in_array($requestMethod, array('HEAD'))) {
|
||||
$allow = array_merge($allow, array('HEAD'));
|
||||
goto not_simple_trailing_slash_HEAD_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_simple_trailing_slash_HEAD_method:
|
||||
|
||||
// simple_trailing_slash_POST_method
|
||||
if ('/trailing/simple/post-method/' === $pathinfo) {
|
||||
$ret = array('_route' => 'simple_trailing_slash_POST_method');
|
||||
if (!in_array($requestMethod, array('POST'))) {
|
||||
$allow = array_merge($allow, array('POST'));
|
||||
goto not_simple_trailing_slash_POST_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_simple_trailing_slash_POST_method:
|
||||
|
||||
}
|
||||
|
||||
elseif (0 === strpos($pathinfo, '/trailing/regex')) {
|
||||
// regex_trailing_slash_no_methods
|
||||
if (0 === strpos($pathinfo, '/trailing/regex/no-methods') && preg_match('#^/trailing/regex/no\\-methods/(?P<param>[^/]++)/?$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_no_methods')), array ());
|
||||
if ('/' === substr($pathinfo, -1)) {
|
||||
// no-op
|
||||
} elseif ('GET' !== $canonicalMethod) {
|
||||
goto not_regex_trailing_slash_no_methods;
|
||||
} else {
|
||||
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'regex_trailing_slash_no_methods'));
|
||||
$matchedPathinfo = $pathinfo;
|
||||
$regexList = array(
|
||||
0 => '{^(?'
|
||||
.'|/trailing/regex/(?'
|
||||
.'|no\\-methods/([^/]++)/(*:47)'
|
||||
.'|get\\-method/([^/]++)/(*:75)'
|
||||
.'|head\\-method/([^/]++)/(*:104)'
|
||||
.'|post\\-method/([^/]++)/(*:134)'
|
||||
.')'
|
||||
.'|/not\\-trailing/regex/(?'
|
||||
.'|no\\-methods/([^/]++)(*:187)'
|
||||
.'|get\\-method/([^/]++)(*:215)'
|
||||
.'|head\\-method/([^/]++)(*:244)'
|
||||
.'|post\\-method/([^/]++)(*:273)'
|
||||
.')'
|
||||
.')$}sD',
|
||||
);
|
||||
|
||||
foreach ($regexList as $offset => $regex) {
|
||||
while (preg_match($regex, $matchedPathinfo, $matches)) {
|
||||
switch ($m = (int) $matches['MARK']) {
|
||||
default:
|
||||
$routes = array(
|
||||
47 => array(array('_route' => 'regex_trailing_slash_no_methods'), array('param'), null, null),
|
||||
75 => array(array('_route' => 'regex_trailing_slash_GET_method'), array('param'), array('GET' => 0), null),
|
||||
104 => array(array('_route' => 'regex_trailing_slash_HEAD_method'), array('param'), array('HEAD' => 0), null),
|
||||
134 => array(array('_route' => 'regex_trailing_slash_POST_method'), array('param'), array('POST' => 0), null),
|
||||
187 => array(array('_route' => 'regex_not_trailing_slash_no_methods'), array('param'), null, null),
|
||||
215 => array(array('_route' => 'regex_not_trailing_slash_GET_method'), array('param'), array('GET' => 0), null),
|
||||
244 => array(array('_route' => 'regex_not_trailing_slash_HEAD_method'), array('param'), array('HEAD' => 0), null),
|
||||
273 => array(array('_route' => 'regex_not_trailing_slash_POST_method'), array('param'), array('POST' => 0), null),
|
||||
);
|
||||
|
||||
list($ret, $vars, $requiredMethods, $requiredSchemes) = $routes[$m];
|
||||
|
||||
foreach ($vars as $i => $v) {
|
||||
if (isset($matches[1 + $i])) {
|
||||
$ret[$v] = $matches[1 + $i];
|
||||
}
|
||||
}
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
if (273 === $m) {
|
||||
break;
|
||||
}
|
||||
$regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m));
|
||||
$offset += strlen($m);
|
||||
}
|
||||
not_regex_trailing_slash_no_methods:
|
||||
|
||||
// regex_trailing_slash_GET_method
|
||||
if (0 === strpos($pathinfo, '/trailing/regex/get-method') && preg_match('#^/trailing/regex/get\\-method/(?P<param>[^/]++)/?$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_GET_method')), array ());
|
||||
if ('/' === substr($pathinfo, -1)) {
|
||||
// no-op
|
||||
} elseif ('GET' !== $canonicalMethod) {
|
||||
goto not_regex_trailing_slash_GET_method;
|
||||
} else {
|
||||
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'regex_trailing_slash_GET_method'));
|
||||
}
|
||||
|
||||
if (!in_array($canonicalMethod, array('GET'))) {
|
||||
$allow = array_merge($allow, array('GET'));
|
||||
goto not_regex_trailing_slash_GET_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_regex_trailing_slash_GET_method:
|
||||
|
||||
// regex_trailing_slash_HEAD_method
|
||||
if (0 === strpos($pathinfo, '/trailing/regex/head-method') && preg_match('#^/trailing/regex/head\\-method/(?P<param>[^/]++)/$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_HEAD_method')), array ());
|
||||
if (!in_array($requestMethod, array('HEAD'))) {
|
||||
$allow = array_merge($allow, array('HEAD'));
|
||||
goto not_regex_trailing_slash_HEAD_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_regex_trailing_slash_HEAD_method:
|
||||
|
||||
// regex_trailing_slash_POST_method
|
||||
if (0 === strpos($pathinfo, '/trailing/regex/post-method') && preg_match('#^/trailing/regex/post\\-method/(?P<param>[^/]++)/$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_POST_method')), array ());
|
||||
if (!in_array($requestMethod, array('POST'))) {
|
||||
$allow = array_merge($allow, array('POST'));
|
||||
goto not_regex_trailing_slash_POST_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_regex_trailing_slash_POST_method:
|
||||
|
||||
}
|
||||
|
||||
elseif (0 === strpos($pathinfo, '/not-trailing/simple')) {
|
||||
// simple_not_trailing_slash_no_methods
|
||||
if ('/not-trailing/simple/no-methods' === $pathinfo) {
|
||||
return array('_route' => 'simple_not_trailing_slash_no_methods');
|
||||
}
|
||||
|
||||
// simple_not_trailing_slash_GET_method
|
||||
if ('/not-trailing/simple/get-method' === $pathinfo) {
|
||||
$ret = array('_route' => 'simple_not_trailing_slash_GET_method');
|
||||
if (!in_array($canonicalMethod, array('GET'))) {
|
||||
$allow = array_merge($allow, array('GET'));
|
||||
goto not_simple_not_trailing_slash_GET_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_simple_not_trailing_slash_GET_method:
|
||||
|
||||
// simple_not_trailing_slash_HEAD_method
|
||||
if ('/not-trailing/simple/head-method' === $pathinfo) {
|
||||
$ret = array('_route' => 'simple_not_trailing_slash_HEAD_method');
|
||||
if (!in_array($requestMethod, array('HEAD'))) {
|
||||
$allow = array_merge($allow, array('HEAD'));
|
||||
goto not_simple_not_trailing_slash_HEAD_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_simple_not_trailing_slash_HEAD_method:
|
||||
|
||||
// simple_not_trailing_slash_POST_method
|
||||
if ('/not-trailing/simple/post-method' === $pathinfo) {
|
||||
$ret = array('_route' => 'simple_not_trailing_slash_POST_method');
|
||||
if (!in_array($requestMethod, array('POST'))) {
|
||||
$allow = array_merge($allow, array('POST'));
|
||||
goto not_simple_not_trailing_slash_POST_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_simple_not_trailing_slash_POST_method:
|
||||
|
||||
}
|
||||
|
||||
elseif (0 === strpos($pathinfo, '/not-trailing/regex')) {
|
||||
// regex_not_trailing_slash_no_methods
|
||||
if (0 === strpos($pathinfo, '/not-trailing/regex/no-methods') && preg_match('#^/not\\-trailing/regex/no\\-methods/(?P<param>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_no_methods')), array ());
|
||||
}
|
||||
|
||||
// regex_not_trailing_slash_GET_method
|
||||
if (0 === strpos($pathinfo, '/not-trailing/regex/get-method') && preg_match('#^/not\\-trailing/regex/get\\-method/(?P<param>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_GET_method')), array ());
|
||||
if (!in_array($canonicalMethod, array('GET'))) {
|
||||
$allow = array_merge($allow, array('GET'));
|
||||
goto not_regex_not_trailing_slash_GET_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_regex_not_trailing_slash_GET_method:
|
||||
|
||||
// regex_not_trailing_slash_HEAD_method
|
||||
if (0 === strpos($pathinfo, '/not-trailing/regex/head-method') && preg_match('#^/not\\-trailing/regex/head\\-method/(?P<param>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_HEAD_method')), array ());
|
||||
if (!in_array($requestMethod, array('HEAD'))) {
|
||||
$allow = array_merge($allow, array('HEAD'));
|
||||
goto not_regex_not_trailing_slash_HEAD_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_regex_not_trailing_slash_HEAD_method:
|
||||
|
||||
// regex_not_trailing_slash_POST_method
|
||||
if (0 === strpos($pathinfo, '/not-trailing/regex/post-method') && preg_match('#^/not\\-trailing/regex/post\\-method/(?P<param>[^/]++)$#sD', $pathinfo, $matches)) {
|
||||
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_POST_method')), array ());
|
||||
if (!in_array($requestMethod, array('POST'))) {
|
||||
$allow = array_merge($allow, array('POST'));
|
||||
goto not_regex_not_trailing_slash_POST_method;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
not_regex_not_trailing_slash_POST_method:
|
||||
|
||||
}
|
||||
|
||||
if ('/' === $pathinfo && !$allow) {
|
||||
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
|
||||
}
|
||||
|
||||
throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
88
vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher8.php
vendored
Normal file
88
vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher8.php
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
|
||||
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
|
||||
use Symfony\Component\Routing\RequestContext;
|
||||
|
||||
/**
|
||||
* This class has been auto-generated
|
||||
* by the Symfony Routing Component.
|
||||
*/
|
||||
class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
{
|
||||
public function __construct(RequestContext $context)
|
||||
{
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
|
||||
if ('HEAD' === $requestMethod) {
|
||||
$canonicalMethod = 'GET';
|
||||
}
|
||||
|
||||
$matchedPathinfo = $pathinfo;
|
||||
$regexList = array(
|
||||
0 => '{^(?'
|
||||
.'|/(a)(*:11)'
|
||||
.')$}sD',
|
||||
11 => '{^(?'
|
||||
.'|/(.)(*:22)'
|
||||
.')$}sDu',
|
||||
22 => '{^(?'
|
||||
.'|/(.)(*:33)'
|
||||
.')$}sD',
|
||||
);
|
||||
|
||||
foreach ($regexList as $offset => $regex) {
|
||||
while (preg_match($regex, $matchedPathinfo, $matches)) {
|
||||
switch ($m = (int) $matches['MARK']) {
|
||||
default:
|
||||
$routes = array(
|
||||
11 => array(array('_route' => 'a'), array('a'), null, null),
|
||||
22 => array(array('_route' => 'b'), array('a'), null, null),
|
||||
33 => array(array('_route' => 'c'), array('a'), null, null),
|
||||
);
|
||||
|
||||
list($ret, $vars, $requiredMethods, $requiredSchemes) = $routes[$m];
|
||||
|
||||
foreach ($vars as $i => $v) {
|
||||
if (isset($matches[1 + $i])) {
|
||||
$ret[$v] = $matches[1 + $i];
|
||||
}
|
||||
}
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if (33 === $m) {
|
||||
break;
|
||||
}
|
||||
$regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m));
|
||||
$offset += strlen($m);
|
||||
}
|
||||
}
|
||||
if ('/' === $pathinfo && !$allow) {
|
||||
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
|
||||
}
|
||||
|
||||
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
|
||||
}
|
||||
}
|
53
vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher9.php
vendored
Normal file
53
vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher9.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
|
||||
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
|
||||
use Symfony\Component\Routing\RequestContext;
|
||||
|
||||
/**
|
||||
* This class has been auto-generated
|
||||
* by the Symfony Routing Component.
|
||||
*/
|
||||
class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
{
|
||||
public function __construct(RequestContext $context)
|
||||
{
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
$host = strtolower($context->getHost());
|
||||
|
||||
if ('HEAD' === $requestMethod) {
|
||||
$canonicalMethod = 'GET';
|
||||
}
|
||||
|
||||
switch ($pathinfo) {
|
||||
case '/':
|
||||
// a
|
||||
if (preg_match('#^(?P<d>[^\\.]++)\\.e\\.c\\.b\\.a$#sDi', $host, $hostMatches)) {
|
||||
return $this->mergeDefaults(array('_route' => 'a') + $hostMatches, array());
|
||||
}
|
||||
// c
|
||||
if (preg_match('#^(?P<e>[^\\.]++)\\.e\\.c\\.b\\.a$#sDi', $host, $hostMatches)) {
|
||||
return $this->mergeDefaults(array('_route' => 'c') + $hostMatches, array());
|
||||
}
|
||||
// b
|
||||
if ('d.c.b.a' === $host) {
|
||||
return array('_route' => 'b');
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ('/' === $pathinfo && !$allow) {
|
||||
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
|
||||
}
|
||||
|
||||
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
|
||||
}
|
||||
}
|
10
vendor/symfony/routing/Tests/Fixtures/import_with_name_prefix/routing.xml
vendored
Normal file
10
vendor/symfony/routing/Tests/Fixtures/import_with_name_prefix/routing.xml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<routes xmlns="http://symfony.com/schema/routing"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/routing
|
||||
http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||
|
||||
<import resource="../controller/routing.xml" />
|
||||
<import resource="../controller/routing.xml" prefix="/api" name-prefix="api_" />
|
||||
|
||||
</routes>
|
7
vendor/symfony/routing/Tests/Fixtures/import_with_name_prefix/routing.yml
vendored
Normal file
7
vendor/symfony/routing/Tests/Fixtures/import_with_name_prefix/routing.yml
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
app:
|
||||
resource: ../controller/routing.yml
|
||||
|
||||
api:
|
||||
resource: ../controller/routing.yml
|
||||
name_prefix: api_
|
||||
prefix: /api
|
10
vendor/symfony/routing/Tests/Fixtures/import_with_no_trailing_slash/routing.xml
vendored
Normal file
10
vendor/symfony/routing/Tests/Fixtures/import_with_no_trailing_slash/routing.xml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<routes xmlns="http://symfony.com/schema/routing"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/routing
|
||||
http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||
|
||||
<import resource="../controller/routing.xml" prefix="/slash" name-prefix="a_" />
|
||||
<import resource="../controller/routing.xml" prefix="/no-slash" name-prefix="b_" trailing-slash-on-root="false" />
|
||||
|
||||
</routes>
|
10
vendor/symfony/routing/Tests/Fixtures/import_with_no_trailing_slash/routing.yml
vendored
Normal file
10
vendor/symfony/routing/Tests/Fixtures/import_with_no_trailing_slash/routing.yml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
app:
|
||||
resource: ../controller/routing.yml
|
||||
name_prefix: a_
|
||||
prefix: /slash
|
||||
|
||||
api:
|
||||
resource: ../controller/routing.yml
|
||||
name_prefix: b_
|
||||
prefix: /no-slash
|
||||
trailing_slash_on_root: false
|
13
vendor/symfony/routing/Tests/Fixtures/localized.xml
vendored
Normal file
13
vendor/symfony/routing/Tests/Fixtures/localized.xml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<routes xmlns="http://symfony.com/schema/routing"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||
|
||||
<route id="localized">
|
||||
<default key="_controller">MyBundle:Blog:show</default>
|
||||
<path locale="en">/path</path>
|
||||
<path locale="fr">/route</path>
|
||||
</route>
|
||||
|
||||
</routes>
|
9
vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale-but-not-localized.xml
vendored
Normal file
9
vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale-but-not-localized.xml
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<routes xmlns="http://symfony.com/schema/routing"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/routing
|
||||
http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||
<route id="imported" path="/suffix">
|
||||
<default key="_controller">MyBundle:Blog:show</default>
|
||||
</route>
|
||||
</routes>
|
4
vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale-but-not-localized.yml
vendored
Normal file
4
vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale-but-not-localized.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
imported:
|
||||
controller: ImportedController::someAction
|
||||
path: /imported
|
11
vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale.xml
vendored
Normal file
11
vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale.xml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<routes xmlns="http://symfony.com/schema/routing"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/routing
|
||||
http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||
<route id="imported">
|
||||
<default key="_controller">MyBundle:Blog:show</default>
|
||||
<path locale="en">/suffix</path>
|
||||
<path locale="fr">/le-suffix</path>
|
||||
</route>
|
||||
</routes>
|
6
vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale.yml
vendored
Normal file
6
vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale.yml
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
imported:
|
||||
controller: ImportedController::someAction
|
||||
path:
|
||||
nl: /voorbeeld
|
||||
en: /example
|
5
vendor/symfony/routing/Tests/Fixtures/localized/importer-with-controller-default.yml
vendored
Normal file
5
vendor/symfony/routing/Tests/Fixtures/localized/importer-with-controller-default.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
i_need:
|
||||
defaults:
|
||||
_controller: DefaultController::defaultAction
|
||||
resource: ./localized-route.yml
|
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<routes xmlns="http://symfony.com/schema/routing"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/routing
|
||||
http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||
<import resource="./imported-with-locale-but-not-localized.xml">
|
||||
<prefix locale="fr">/le-prefix</prefix>
|
||||
<prefix locale="en">/the-prefix</prefix>
|
||||
</import>
|
||||
</routes>
|
@@ -0,0 +1,6 @@
|
||||
---
|
||||
i_need:
|
||||
resource: ./imported-with-locale-but-not-localized.yml
|
||||
prefix:
|
||||
nl: /nl
|
||||
en: /en
|
10
vendor/symfony/routing/Tests/Fixtures/localized/importer-with-locale.xml
vendored
Normal file
10
vendor/symfony/routing/Tests/Fixtures/localized/importer-with-locale.xml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<routes xmlns="http://symfony.com/schema/routing"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/routing
|
||||
http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||
<import resource="./imported-with-locale.xml">
|
||||
<prefix locale="fr">/le-prefix</prefix>
|
||||
<prefix locale="en">/the-prefix</prefix>
|
||||
</import>
|
||||
</routes>
|
6
vendor/symfony/routing/Tests/Fixtures/localized/importer-with-locale.yml
vendored
Normal file
6
vendor/symfony/routing/Tests/Fixtures/localized/importer-with-locale.yml
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
i_need:
|
||||
resource: ./imported-with-locale.yml
|
||||
prefix:
|
||||
nl: /nl
|
||||
en: /en
|
3
vendor/symfony/routing/Tests/Fixtures/localized/importing-localized-route.yml
vendored
Normal file
3
vendor/symfony/routing/Tests/Fixtures/localized/importing-localized-route.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
i_need:
|
||||
resource: ./localized-route.yml
|
9
vendor/symfony/routing/Tests/Fixtures/localized/localized-route.yml
vendored
Normal file
9
vendor/symfony/routing/Tests/Fixtures/localized/localized-route.yml
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
home:
|
||||
path:
|
||||
nl: /nl
|
||||
en: /en
|
||||
|
||||
not_localized:
|
||||
controller: HomeController::otherAction
|
||||
path: /here
|
5
vendor/symfony/routing/Tests/Fixtures/localized/missing-locale-in-importer.yml
vendored
Normal file
5
vendor/symfony/routing/Tests/Fixtures/localized/missing-locale-in-importer.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
importing_with_missing_prefix:
|
||||
resource: ./localized-route.yml
|
||||
prefix:
|
||||
nl: /prefix
|
4
vendor/symfony/routing/Tests/Fixtures/localized/not-localized.yml
vendored
Normal file
4
vendor/symfony/routing/Tests/Fixtures/localized/not-localized.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
not_localized:
|
||||
controller: string
|
||||
path: /here
|
7
vendor/symfony/routing/Tests/Fixtures/localized/officially_formatted_locales.yml
vendored
Normal file
7
vendor/symfony/routing/Tests/Fixtures/localized/officially_formatted_locales.yml
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
official:
|
||||
controller: HomeController::someAction
|
||||
path:
|
||||
fr.UTF-8: /omelette-au-fromage
|
||||
pt-PT: /eu-não-sou-espanhol
|
||||
pt_BR: /churrasco
|
3
vendor/symfony/routing/Tests/Fixtures/localized/route-without-path-or-locales.yml
vendored
Normal file
3
vendor/symfony/routing/Tests/Fixtures/localized/route-without-path-or-locales.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
routename:
|
||||
controller: Here::here
|
@@ -1,3 +1,3 @@
|
||||
someroute:
|
||||
resource: path/to/some.yml
|
||||
name_prefix: test_
|
||||
not_valid_key: test_
|
||||
|
@@ -15,6 +15,13 @@ return function (RoutingConfigurator $routes) {
|
||||
->prefix('/sub')
|
||||
->requirements(array('id' => '\d+'));
|
||||
|
||||
$routes->import('php_dsl_sub.php')
|
||||
->namePrefix('z_')
|
||||
->prefix('/zub');
|
||||
|
||||
$routes->import('php_dsl_sub_root.php')
|
||||
->prefix('/bus', false);
|
||||
|
||||
$routes->add('ouf', '/ouf')
|
||||
->schemes(array('https'))
|
||||
->methods(array('GET'))
|
||||
|
17
vendor/symfony/routing/Tests/Fixtures/php_dsl_i18n.php
vendored
Normal file
17
vendor/symfony/routing/Tests/Fixtures/php_dsl_i18n.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Loader\Configurator;
|
||||
|
||||
return function (RoutingConfigurator $routes) {
|
||||
$routes
|
||||
->collection()
|
||||
->prefix(array('en' => '/glish'))
|
||||
->add('foo', '/foo')
|
||||
->add('bar', array('en' => '/bar'));
|
||||
|
||||
$routes
|
||||
->add('baz', array('en' => '/baz'));
|
||||
|
||||
$routes->import('php_dsl_sub_i18n.php')
|
||||
->prefix(array('fr' => '/ench'));
|
||||
};
|
@@ -6,6 +6,7 @@ return function (RoutingConfigurator $routes) {
|
||||
$add = $routes->collection('c_')
|
||||
->prefix('pub');
|
||||
|
||||
$add('root', '/');
|
||||
$add('bar', '/bar');
|
||||
|
||||
$add->collection('pub_')
|
||||
|
11
vendor/symfony/routing/Tests/Fixtures/php_dsl_sub_i18n.php
vendored
Normal file
11
vendor/symfony/routing/Tests/Fixtures/php_dsl_sub_i18n.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Loader\Configurator;
|
||||
|
||||
return function (RoutingConfigurator $routes) {
|
||||
$add = $routes->collection('c_')
|
||||
->prefix('pub');
|
||||
|
||||
$add('foo', array('fr' => '/foo'));
|
||||
$add('bar', array('fr' => '/bar'));
|
||||
};
|
10
vendor/symfony/routing/Tests/Fixtures/php_dsl_sub_root.php
vendored
Normal file
10
vendor/symfony/routing/Tests/Fixtures/php_dsl_sub_root.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Loader\Configurator;
|
||||
|
||||
return function (RoutingConfigurator $routes) {
|
||||
$add = $routes->collection('r_');
|
||||
|
||||
$add('root', '/');
|
||||
$add('bar', '/bar/');
|
||||
};
|
32
vendor/symfony/routing/Tests/Fixtures/php_object_dsl.php
vendored
Normal file
32
vendor/symfony/routing/Tests/Fixtures/php_object_dsl.php
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Loader\Configurator;
|
||||
|
||||
return new class() {
|
||||
public function __invoke(RoutingConfigurator $routes)
|
||||
{
|
||||
$routes
|
||||
->collection()
|
||||
->add('foo', '/foo')
|
||||
->condition('abc')
|
||||
->options(array('utf8' => true))
|
||||
->add('buz', 'zub')
|
||||
->controller('foo:act');
|
||||
|
||||
$routes->import('php_dsl_sub.php')
|
||||
->prefix('/sub')
|
||||
->requirements(array('id' => '\d+'));
|
||||
|
||||
$routes->import('php_dsl_sub.php')
|
||||
->namePrefix('z_')
|
||||
->prefix('/zub');
|
||||
|
||||
$routes->import('php_dsl_sub_root.php')
|
||||
->prefix('/bus', false);
|
||||
|
||||
$routes->add('ouf', '/ouf')
|
||||
->schemes(array('https'))
|
||||
->methods(array('GET'))
|
||||
->defaults(array('id' => 0));
|
||||
}
|
||||
};
|
@@ -84,12 +84,35 @@ class PhpGeneratorDumperTest extends TestCase
|
||||
$this->assertEquals('/app.php/testing2', $relativeUrlWithoutParameter);
|
||||
}
|
||||
|
||||
public function testDumpWithLocalizedRoutes()
|
||||
{
|
||||
$this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'test'));
|
||||
$this->routeCollection->add('test.nl', (new Route('/testen/is/leuk'))->setDefault('_locale', 'nl')->setDefault('_canonical_route', 'test'));
|
||||
|
||||
$code = $this->generatorDumper->dump(array(
|
||||
'class' => 'LocalizedProjectUrlGenerator',
|
||||
));
|
||||
file_put_contents($this->testTmpFilepath, $code);
|
||||
include $this->testTmpFilepath;
|
||||
|
||||
$context = new RequestContext('/app.php');
|
||||
$projectUrlGenerator = new \LocalizedProjectUrlGenerator($context, null, 'en');
|
||||
|
||||
$urlWithDefaultLocale = $projectUrlGenerator->generate('test');
|
||||
$urlWithSpecifiedLocale = $projectUrlGenerator->generate('test', array('_locale' => 'nl'));
|
||||
$context->setParameter('_locale', 'en');
|
||||
$urlWithEnglishContext = $projectUrlGenerator->generate('test');
|
||||
$context->setParameter('_locale', 'nl');
|
||||
$urlWithDutchContext = $projectUrlGenerator->generate('test');
|
||||
|
||||
$this->assertEquals('/app.php/testing/is/fun', $urlWithDefaultLocale);
|
||||
$this->assertEquals('/app.php/testen/is/leuk', $urlWithSpecifiedLocale);
|
||||
$this->assertEquals('/app.php/testing/is/fun', $urlWithEnglishContext);
|
||||
$this->assertEquals('/app.php/testen/is/leuk', $urlWithDutchContext);
|
||||
}
|
||||
|
||||
public function testDumpWithTooManyRoutes()
|
||||
{
|
||||
if (\defined('HHVM_VERSION_ID')) {
|
||||
$this->markTestSkipped('HHVM consumes too much memory on this test.');
|
||||
}
|
||||
|
||||
$this->routeCollection->add('Test', new Route('/testing/{foo}'));
|
||||
for ($i = 0; $i < 32769; ++$i) {
|
||||
$this->routeCollection->add('route_'.$i, new Route('/route_'.$i));
|
||||
|
@@ -11,35 +11,46 @@
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Loader;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Doctrine\Common\Annotations\AnnotationRegistry;
|
||||
use Symfony\Component\Routing\Annotation\Route as RouteAnnotation;
|
||||
use Symfony\Component\Routing\Loader\AnnotationClassLoader;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\AbstractClassController;
|
||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\ActionPathController;
|
||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\DefaultValueController;
|
||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\ExplicitLocalizedActionPathController;
|
||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\InvokableController;
|
||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\InvokableLocalizedController;
|
||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\LocalizedActionPathController;
|
||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\LocalizedMethodActionControllers;
|
||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\LocalizedPrefixLocalizedActionController;
|
||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\LocalizedPrefixMissingLocaleActionController;
|
||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\LocalizedPrefixMissingRouteLocaleActionController;
|
||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\LocalizedPrefixWithRouteWithoutLocale;
|
||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\MethodActionControllers;
|
||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\MissingRouteNameController;
|
||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\NothingButNameController;
|
||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\PrefixedActionLocalizedRouteController;
|
||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\PrefixedActionPathController;
|
||||
use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\RouteWithPrefixController;
|
||||
|
||||
class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
||||
{
|
||||
protected $loader;
|
||||
private $reader;
|
||||
/**
|
||||
* @var AnnotationClassLoader
|
||||
*/
|
||||
private $loader;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->reader = $this->getReader();
|
||||
$this->loader = $this->getClassLoader($this->reader);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testLoadMissingClass()
|
||||
{
|
||||
$this->loader->load('MissingClass');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testLoadAbstractClass()
|
||||
{
|
||||
$this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\AbstractClass');
|
||||
$reader = new AnnotationReader();
|
||||
$this->loader = new class($reader) extends AnnotationClassLoader {
|
||||
protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot)
|
||||
{
|
||||
}
|
||||
};
|
||||
AnnotationRegistry::registerLoader('class_exists');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,144 +80,92 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
||||
$this->assertFalse($this->loader->supports('class', 'foo'), '->supports() checks the resource type if specified');
|
||||
}
|
||||
|
||||
public function getLoadTests()
|
||||
public function testSimplePathRoute()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass',
|
||||
array('name' => 'route1', 'path' => '/path'),
|
||||
array('arg2' => 'defaultValue2', 'arg3' => 'defaultValue3'),
|
||||
),
|
||||
array(
|
||||
'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass',
|
||||
array('defaults' => array('arg2' => 'foo'), 'requirements' => array('arg3' => '\w+')),
|
||||
array('arg2' => 'defaultValue2', 'arg3' => 'defaultValue3'),
|
||||
),
|
||||
array(
|
||||
'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass',
|
||||
array('options' => array('foo' => 'bar')),
|
||||
array('arg2' => 'defaultValue2', 'arg3' => 'defaultValue3'),
|
||||
),
|
||||
array(
|
||||
'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass',
|
||||
array('schemes' => array('https'), 'methods' => array('GET')),
|
||||
array('arg2' => 'defaultValue2', 'arg3' => 'defaultValue3'),
|
||||
),
|
||||
array(
|
||||
'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass',
|
||||
array('condition' => 'context.getMethod() == "GET"'),
|
||||
array('arg2' => 'defaultValue2', 'arg3' => 'defaultValue3'),
|
||||
),
|
||||
);
|
||||
$routes = $this->loader->load(ActionPathController::class);
|
||||
$this->assertCount(1, $routes);
|
||||
$this->assertEquals('/path', $routes->get('action')->getPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getLoadTests
|
||||
*/
|
||||
public function testLoad($className, $routeData = array(), $methodArgs = array())
|
||||
public function testInvokableControllerLoader()
|
||||
{
|
||||
$routeData = array_replace(array(
|
||||
'name' => 'route',
|
||||
'path' => '/',
|
||||
'requirements' => array(),
|
||||
'options' => array(),
|
||||
'defaults' => array(),
|
||||
'schemes' => array(),
|
||||
'methods' => array(),
|
||||
'condition' => '',
|
||||
), $routeData);
|
||||
|
||||
$this->reader
|
||||
->expects($this->once())
|
||||
->method('getMethodAnnotations')
|
||||
->will($this->returnValue(array($this->getAnnotatedRoute($routeData))))
|
||||
;
|
||||
|
||||
$routeCollection = $this->loader->load($className);
|
||||
$route = $routeCollection->get($routeData['name']);
|
||||
|
||||
$this->assertSame($routeData['path'], $route->getPath(), '->load preserves path annotation');
|
||||
$this->assertCount(
|
||||
\count($routeData['requirements']),
|
||||
array_intersect_assoc($routeData['requirements'], $route->getRequirements()),
|
||||
'->load preserves requirements annotation'
|
||||
);
|
||||
$this->assertCount(
|
||||
\count($routeData['options']),
|
||||
array_intersect_assoc($routeData['options'], $route->getOptions()),
|
||||
'->load preserves options annotation'
|
||||
);
|
||||
$this->assertCount(
|
||||
\count($routeData['defaults']),
|
||||
$route->getDefaults(),
|
||||
'->load preserves defaults annotation'
|
||||
);
|
||||
$this->assertEquals($routeData['schemes'], $route->getSchemes(), '->load preserves schemes annotation');
|
||||
$this->assertEquals($routeData['methods'], $route->getMethods(), '->load preserves methods annotation');
|
||||
$this->assertSame($routeData['condition'], $route->getCondition(), '->load preserves condition annotation');
|
||||
$routes = $this->loader->load(InvokableController::class);
|
||||
$this->assertCount(1, $routes);
|
||||
$this->assertEquals('/here', $routes->get('lol')->getPath());
|
||||
}
|
||||
|
||||
public function testClassRouteLoad()
|
||||
public function testInvokableLocalizedControllerLoading()
|
||||
{
|
||||
$classRouteData = array(
|
||||
'name' => 'prefix_',
|
||||
'path' => '/prefix',
|
||||
'schemes' => array('https'),
|
||||
'methods' => array('GET'),
|
||||
);
|
||||
|
||||
$methodRouteData = array(
|
||||
'name' => 'route1',
|
||||
'path' => '/path',
|
||||
'schemes' => array('http'),
|
||||
'methods' => array('POST', 'PUT'),
|
||||
);
|
||||
|
||||
$this->reader
|
||||
->expects($this->once())
|
||||
->method('getClassAnnotation')
|
||||
->will($this->returnValue($this->getAnnotatedRoute($classRouteData)))
|
||||
;
|
||||
$this->reader
|
||||
->expects($this->once())
|
||||
->method('getMethodAnnotations')
|
||||
->will($this->returnValue(array($this->getAnnotatedRoute($methodRouteData))))
|
||||
;
|
||||
|
||||
$routeCollection = $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass');
|
||||
$route = $routeCollection->get($classRouteData['name'].$methodRouteData['name']);
|
||||
|
||||
$this->assertSame($classRouteData['path'].$methodRouteData['path'], $route->getPath(), '->load concatenates class and method route path');
|
||||
$this->assertEquals(array_merge($classRouteData['schemes'], $methodRouteData['schemes']), $route->getSchemes(), '->load merges class and method route schemes');
|
||||
$this->assertEquals(array_merge($classRouteData['methods'], $methodRouteData['methods']), $route->getMethods(), '->load merges class and method route methods');
|
||||
$routes = $this->loader->load(InvokableLocalizedController::class);
|
||||
$this->assertCount(2, $routes);
|
||||
$this->assertEquals('/here', $routes->get('action.en')->getPath());
|
||||
$this->assertEquals('/hier', $routes->get('action.nl')->getPath());
|
||||
}
|
||||
|
||||
public function testInvokableClassRouteLoad()
|
||||
public function testLocalizedPathRoutes()
|
||||
{
|
||||
$classRouteData = array(
|
||||
'name' => 'route1',
|
||||
'path' => '/',
|
||||
'schemes' => array('https'),
|
||||
'methods' => array('GET'),
|
||||
);
|
||||
$routes = $this->loader->load(LocalizedActionPathController::class);
|
||||
$this->assertCount(2, $routes);
|
||||
$this->assertEquals('/path', $routes->get('action.en')->getPath());
|
||||
$this->assertEquals('/pad', $routes->get('action.nl')->getPath());
|
||||
}
|
||||
|
||||
$this->reader
|
||||
->expects($this->exactly(1))
|
||||
->method('getClassAnnotations')
|
||||
->will($this->returnValue(array($this->getAnnotatedRoute($classRouteData))))
|
||||
;
|
||||
$this->reader
|
||||
->expects($this->once())
|
||||
->method('getMethodAnnotations')
|
||||
->will($this->returnValue(array()))
|
||||
;
|
||||
public function testLocalizedPathRoutesWithExplicitPathPropety()
|
||||
{
|
||||
$routes = $this->loader->load(ExplicitLocalizedActionPathController::class);
|
||||
$this->assertCount(2, $routes);
|
||||
$this->assertEquals('/path', $routes->get('action.en')->getPath());
|
||||
$this->assertEquals('/pad', $routes->get('action.nl')->getPath());
|
||||
}
|
||||
|
||||
$routeCollection = $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass');
|
||||
$route = $routeCollection->get($classRouteData['name']);
|
||||
public function testDefaultValuesForMethods()
|
||||
{
|
||||
$routes = $this->loader->load(DefaultValueController::class);
|
||||
$this->assertCount(1, $routes);
|
||||
$this->assertEquals('/{default}/path', $routes->get('action')->getPath());
|
||||
$this->assertEquals('value', $routes->get('action')->getDefault('default'));
|
||||
}
|
||||
|
||||
$this->assertSame($classRouteData['path'], $route->getPath(), '->load preserves class route path');
|
||||
$this->assertEquals($classRouteData['schemes'], $route->getSchemes(), '->load preserves class route schemes');
|
||||
$this->assertEquals($classRouteData['methods'], $route->getMethods(), '->load preserves class route methods');
|
||||
public function testMethodActionControllers()
|
||||
{
|
||||
$routes = $this->loader->load(MethodActionControllers::class);
|
||||
$this->assertCount(2, $routes);
|
||||
$this->assertEquals('/the/path', $routes->get('put')->getPath());
|
||||
$this->assertEquals('/the/path', $routes->get('post')->getPath());
|
||||
}
|
||||
|
||||
public function testLocalizedMethodActionControllers()
|
||||
{
|
||||
$routes = $this->loader->load(LocalizedMethodActionControllers::class);
|
||||
$this->assertCount(4, $routes);
|
||||
$this->assertEquals('/the/path', $routes->get('put.en')->getPath());
|
||||
$this->assertEquals('/the/path', $routes->get('post.en')->getPath());
|
||||
}
|
||||
|
||||
public function testRouteWithPathWithPrefix()
|
||||
{
|
||||
$routes = $this->loader->load(PrefixedActionPathController::class);
|
||||
$this->assertCount(1, $routes);
|
||||
$route = $routes->get('action');
|
||||
$this->assertEquals('/prefix/path', $route->getPath());
|
||||
$this->assertEquals('lol=fun', $route->getCondition());
|
||||
$this->assertEquals('frankdejonge.nl', $route->getHost());
|
||||
}
|
||||
|
||||
public function testLocalizedRouteWithPathWithPrefix()
|
||||
{
|
||||
$routes = $this->loader->load(PrefixedActionLocalizedRouteController::class);
|
||||
$this->assertCount(2, $routes);
|
||||
$this->assertEquals('/prefix/path', $routes->get('action.en')->getPath());
|
||||
$this->assertEquals('/prefix/pad', $routes->get('action.nl')->getPath());
|
||||
}
|
||||
|
||||
public function testLocalizedPrefixLocalizedRoute()
|
||||
{
|
||||
$routes = $this->loader->load(LocalizedPrefixLocalizedActionController::class);
|
||||
$this->assertCount(2, $routes);
|
||||
$this->assertEquals('/nl/actie', $routes->get('action.nl')->getPath());
|
||||
$this->assertEquals('/en/action', $routes->get('action.en')->getPath());
|
||||
}
|
||||
|
||||
public function testInvokableClassMultipleRouteLoad()
|
||||
@@ -225,18 +184,24 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
||||
'methods' => array('GET'),
|
||||
);
|
||||
|
||||
$this->reader
|
||||
$reader = $this->getReader();
|
||||
$reader
|
||||
->expects($this->exactly(1))
|
||||
->method('getClassAnnotations')
|
||||
->will($this->returnValue(array($this->getAnnotatedRoute($classRouteData1), $this->getAnnotatedRoute($classRouteData2))))
|
||||
->will($this->returnValue(array(new RouteAnnotation($classRouteData1), new RouteAnnotation($classRouteData2))))
|
||||
;
|
||||
$this->reader
|
||||
$reader
|
||||
->expects($this->once())
|
||||
->method('getMethodAnnotations')
|
||||
->will($this->returnValue(array()))
|
||||
;
|
||||
$loader = new class($reader) extends AnnotationClassLoader {
|
||||
protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
$routeCollection = $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass');
|
||||
$routeCollection = $loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass');
|
||||
$route = $routeCollection->get($classRouteData1['name']);
|
||||
|
||||
$this->assertSame($classRouteData1['path'], $route->getPath(), '->load preserves class route path');
|
||||
@@ -250,47 +215,56 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest
|
||||
$this->assertEquals($classRouteData2['methods'], $route->getMethods(), '->load preserves class route methods');
|
||||
}
|
||||
|
||||
public function testInvokableClassWithMethodRouteLoad()
|
||||
public function testMissingPrefixLocale()
|
||||
{
|
||||
$classRouteData = array(
|
||||
'name' => 'route1',
|
||||
'path' => '/prefix',
|
||||
'schemes' => array('https'),
|
||||
'methods' => array('GET'),
|
||||
);
|
||||
|
||||
$methodRouteData = array(
|
||||
'name' => 'route2',
|
||||
'path' => '/path',
|
||||
'schemes' => array('http'),
|
||||
'methods' => array('POST', 'PUT'),
|
||||
);
|
||||
|
||||
$this->reader
|
||||
->expects($this->once())
|
||||
->method('getClassAnnotation')
|
||||
->will($this->returnValue($this->getAnnotatedRoute($classRouteData)))
|
||||
;
|
||||
$this->reader
|
||||
->expects($this->once())
|
||||
->method('getMethodAnnotations')
|
||||
->will($this->returnValue(array($this->getAnnotatedRoute($methodRouteData))))
|
||||
;
|
||||
|
||||
$routeCollection = $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass');
|
||||
$route = $routeCollection->get($classRouteData['name']);
|
||||
|
||||
$this->assertNull($route, '->load ignores class route');
|
||||
|
||||
$route = $routeCollection->get($classRouteData['name'].$methodRouteData['name']);
|
||||
|
||||
$this->assertSame($classRouteData['path'].$methodRouteData['path'], $route->getPath(), '->load concatenates class and method route path');
|
||||
$this->assertEquals(array_merge($classRouteData['schemes'], $methodRouteData['schemes']), $route->getSchemes(), '->load merges class and method route schemes');
|
||||
$this->assertEquals(array_merge($classRouteData['methods'], $methodRouteData['methods']), $route->getMethods(), '->load merges class and method route methods');
|
||||
$this->expectException(\LogicException::class);
|
||||
$this->loader->load(LocalizedPrefixMissingLocaleActionController::class);
|
||||
}
|
||||
|
||||
private function getAnnotatedRoute($data)
|
||||
public function testMissingRouteLocale()
|
||||
{
|
||||
return new Route($data);
|
||||
$this->expectException(\LogicException::class);
|
||||
$this->loader->load(LocalizedPrefixMissingRouteLocaleActionController::class);
|
||||
}
|
||||
|
||||
public function testRouteWithoutName()
|
||||
{
|
||||
$routes = $this->loader->load(MissingRouteNameController::class)->all();
|
||||
$this->assertCount(1, $routes);
|
||||
$this->assertEquals('/path', reset($routes)->getPath());
|
||||
}
|
||||
|
||||
public function testNothingButName()
|
||||
{
|
||||
$routes = $this->loader->load(NothingButNameController::class)->all();
|
||||
$this->assertCount(1, $routes);
|
||||
$this->assertEquals('/', reset($routes)->getPath());
|
||||
}
|
||||
|
||||
public function testNonExistingClass()
|
||||
{
|
||||
$this->expectException(\LogicException::class);
|
||||
$this->loader->load('ClassThatDoesNotExist');
|
||||
}
|
||||
|
||||
public function testLoadingAbstractClass()
|
||||
{
|
||||
$this->expectException(\LogicException::class);
|
||||
$this->loader->load(AbstractClassController::class);
|
||||
}
|
||||
|
||||
public function testLocalizedPrefixWithoutRouteLocale()
|
||||
{
|
||||
$routes = $this->loader->load(LocalizedPrefixWithRouteWithoutLocale::class);
|
||||
$this->assertCount(2, $routes);
|
||||
$this->assertEquals('/en/suffix', $routes->get('action.en')->getPath());
|
||||
$this->assertEquals('/nl/suffix', $routes->get('action.nl')->getPath());
|
||||
}
|
||||
|
||||
public function testLoadingRouteWithPrefix()
|
||||
{
|
||||
$routes = $this->loader->load(RouteWithPrefixController::class);
|
||||
$this->assertCount(1, $routes);
|
||||
$this->assertEquals('/prefix/path', $routes->get('action')->getPath());
|
||||
}
|
||||
}
|
||||
|
@@ -35,9 +35,6 @@ class AnnotationFileLoaderTest extends AbstractAnnotationLoaderTest
|
||||
$this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses/FooClass.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 5.4
|
||||
*/
|
||||
public function testLoadTraitWithClassConstant()
|
||||
{
|
||||
$this->reader->expects($this->never())->method('getClassAnnotation');
|
||||
@@ -54,9 +51,6 @@ class AnnotationFileLoaderTest extends AbstractAnnotationLoaderTest
|
||||
$this->loader->load(__DIR__.'/../Fixtures/OtherAnnotatedClasses/NoStartTagClass.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 5.6
|
||||
*/
|
||||
public function testLoadVariadic()
|
||||
{
|
||||
$route = new Route(array('path' => '/path/to/{id}'));
|
||||
|
17
vendor/symfony/routing/Tests/Loader/FileLocatorStub.php
vendored
Normal file
17
vendor/symfony/routing/Tests/Loader/FileLocatorStub.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Loader;
|
||||
|
||||
use Symfony\Component\Config\FileLocatorInterface;
|
||||
|
||||
class FileLocatorStub implements FileLocatorInterface
|
||||
{
|
||||
public function locate($name, $currentPath = null, $first = true)
|
||||
{
|
||||
if (0 === strpos($name, 'http')) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
return rtrim($currentPath, '/').'/'.$name;
|
||||
}
|
||||
}
|
@@ -18,7 +18,11 @@ use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
class ObjectRouteLoaderTest extends TestCase
|
||||
{
|
||||
public function testLoadCallsServiceAndReturnsCollection()
|
||||
/**
|
||||
* @group legacy
|
||||
* @expectedDeprecation Referencing service route loaders with a single colon is deprecated since Symfony 4.1. Use my_route_provider_service::loadRoutes instead.
|
||||
*/
|
||||
public function testLoadCallsServiceAndReturnsCollectionWithLegacyNotation()
|
||||
{
|
||||
$loader = new ObjectRouteLoaderForTest();
|
||||
|
||||
@@ -40,6 +44,28 @@ class ObjectRouteLoaderTest extends TestCase
|
||||
$this->assertNotEmpty($actualRoutes->getResources());
|
||||
}
|
||||
|
||||
public function testLoadCallsServiceAndReturnsCollection()
|
||||
{
|
||||
$loader = new ObjectRouteLoaderForTest();
|
||||
|
||||
// create a basic collection that will be returned
|
||||
$collection = new RouteCollection();
|
||||
$collection->add('foo', new Route('/foo'));
|
||||
|
||||
$loader->loaderMap = array(
|
||||
'my_route_provider_service' => new RouteService($collection),
|
||||
);
|
||||
|
||||
$actualRoutes = $loader->load(
|
||||
'my_route_provider_service::loadRoutes',
|
||||
'service'
|
||||
);
|
||||
|
||||
$this->assertSame($collection, $actualRoutes);
|
||||
// the service file should be listed as a resource
|
||||
$this->assertNotEmpty($actualRoutes->getResources());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @dataProvider getBadResourceStrings
|
||||
@@ -54,7 +80,6 @@ class ObjectRouteLoaderTest extends TestCase
|
||||
{
|
||||
return array(
|
||||
array('Foo'),
|
||||
array('Bar::baz'),
|
||||
array('Foo:Bar:baz'),
|
||||
);
|
||||
}
|
||||
@@ -66,7 +91,7 @@ class ObjectRouteLoaderTest extends TestCase
|
||||
{
|
||||
$loader = new ObjectRouteLoaderForTest();
|
||||
$loader->loaderMap = array('my_service' => 'NOT_AN_OBJECT');
|
||||
$loader->load('my_service:method');
|
||||
$loader->load('my_service::method');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,7 +101,7 @@ class ObjectRouteLoaderTest extends TestCase
|
||||
{
|
||||
$loader = new ObjectRouteLoaderForTest();
|
||||
$loader->loaderMap = array('my_service' => new \stdClass());
|
||||
$loader->load('my_service:method');
|
||||
$loader->load('my_service::method');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,7 +118,7 @@ class ObjectRouteLoaderTest extends TestCase
|
||||
|
||||
$loader = new ObjectRouteLoaderForTest();
|
||||
$loader->loaderMap = array('my_service' => $service);
|
||||
$loader->load('my_service:loadRoutes');
|
||||
$loader->load('my_service::loadRoutes');
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -88,7 +88,8 @@ class PhpFileLoaderTest extends TestCase
|
||||
{
|
||||
$locator = new FileLocator(array(__DIR__.'/../Fixtures'));
|
||||
$loader = new PhpFileLoader($locator);
|
||||
$routeCollection = $loader->load('php_dsl.php');
|
||||
$routeCollectionClosure = $loader->load('php_dsl.php');
|
||||
$routeCollectionObject = $loader->load('php_object_dsl.php');
|
||||
|
||||
$expectedCollection = new RouteCollection();
|
||||
|
||||
@@ -99,6 +100,9 @@ class PhpFileLoaderTest extends TestCase
|
||||
$expectedCollection->add('buz', (new Route('/zub'))
|
||||
->setDefaults(array('_controller' => 'foo:act'))
|
||||
);
|
||||
$expectedCollection->add('c_root', (new Route('/sub/pub/'))
|
||||
->setRequirements(array('id' => '\d+'))
|
||||
);
|
||||
$expectedCollection->add('c_bar', (new Route('/sub/pub/bar'))
|
||||
->setRequirements(array('id' => '\d+'))
|
||||
);
|
||||
@@ -106,6 +110,11 @@ class PhpFileLoaderTest extends TestCase
|
||||
->setHost('host')
|
||||
->setRequirements(array('id' => '\d+'))
|
||||
);
|
||||
$expectedCollection->add('z_c_root', new Route('/zub/pub/'));
|
||||
$expectedCollection->add('z_c_bar', new Route('/zub/pub/bar'));
|
||||
$expectedCollection->add('z_c_pub_buz', (new Route('/zub/pub/buz'))->setHost('host'));
|
||||
$expectedCollection->add('r_root', new Route('/bus'));
|
||||
$expectedCollection->add('r_bar', new Route('/bus/bar/'));
|
||||
$expectedCollection->add('ouf', (new Route('/ouf'))
|
||||
->setSchemes(array('https'))
|
||||
->setMethods(array('GET'))
|
||||
@@ -113,9 +122,16 @@ class PhpFileLoaderTest extends TestCase
|
||||
);
|
||||
|
||||
$expectedCollection->addResource(new FileResource(realpath(__DIR__.'/../Fixtures/php_dsl_sub.php')));
|
||||
$expectedCollection->addResource(new FileResource(realpath(__DIR__.'/../Fixtures/php_dsl.php')));
|
||||
$expectedCollection->addResource(new FileResource(realpath(__DIR__.'/../Fixtures/php_dsl_sub_root.php')));
|
||||
|
||||
$this->assertEquals($expectedCollection, $routeCollection);
|
||||
$expectedCollectionClosure = $expectedCollection;
|
||||
$expectedCollectionObject = clone $expectedCollection;
|
||||
|
||||
$expectedCollectionClosure->addResource(new FileResource(realpath(__DIR__.'/../Fixtures/php_dsl.php')));
|
||||
$expectedCollectionObject->addResource(new FileResource(realpath(__DIR__.'/../Fixtures/php_object_dsl.php')));
|
||||
|
||||
$this->assertEquals($expectedCollectionClosure, $routeCollectionClosure);
|
||||
$this->assertEquals($expectedCollectionObject, $routeCollectionObject);
|
||||
}
|
||||
|
||||
public function testRoutingConfiguratorCanImportGlobPatterns()
|
||||
@@ -130,4 +146,24 @@ class PhpFileLoaderTest extends TestCase
|
||||
$route = $routeCollection->get('baz_route');
|
||||
$this->assertSame('AppBundle:Baz:view', $route->getDefault('_controller'));
|
||||
}
|
||||
|
||||
public function testRoutingI18nConfigurator()
|
||||
{
|
||||
$locator = new FileLocator(array(__DIR__.'/../Fixtures'));
|
||||
$loader = new PhpFileLoader($locator);
|
||||
$routeCollection = $loader->load('php_dsl_i18n.php');
|
||||
|
||||
$expectedCollection = new RouteCollection();
|
||||
|
||||
$expectedCollection->add('foo.en', (new Route('/glish/foo'))->setDefaults(array('_locale' => 'en', '_canonical_route' => 'foo')));
|
||||
$expectedCollection->add('bar.en', (new Route('/glish/bar'))->setDefaults(array('_locale' => 'en', '_canonical_route' => 'bar')));
|
||||
$expectedCollection->add('baz.en', (new Route('/baz'))->setDefaults(array('_locale' => 'en', '_canonical_route' => 'baz')));
|
||||
$expectedCollection->add('c_foo.fr', (new Route('/ench/pub/foo'))->setDefaults(array('_locale' => 'fr', '_canonical_route' => 'c_foo')));
|
||||
$expectedCollection->add('c_bar.fr', (new Route('/ench/pub/bar'))->setDefaults(array('_locale' => 'fr', '_canonical_route' => 'c_bar')));
|
||||
|
||||
$expectedCollection->addResource(new FileResource(realpath(__DIR__.'/../Fixtures/php_dsl_sub_i18n.php')));
|
||||
$expectedCollection->addResource(new FileResource(realpath(__DIR__.'/../Fixtures/php_dsl_i18n.php')));
|
||||
|
||||
$this->assertEquals($expectedCollection, $routeCollection);
|
||||
}
|
||||
}
|
||||
|
@@ -83,6 +83,45 @@ class XmlFileLoaderTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function testLoadLocalized()
|
||||
{
|
||||
$loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures')));
|
||||
$routeCollection = $loader->load('localized.xml');
|
||||
$routes = $routeCollection->all();
|
||||
|
||||
$this->assertCount(2, $routes, 'Two routes are loaded');
|
||||
$this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);
|
||||
|
||||
$this->assertEquals('/route', $routeCollection->get('localized.fr')->getPath());
|
||||
$this->assertEquals('/path', $routeCollection->get('localized.en')->getPath());
|
||||
}
|
||||
|
||||
public function testLocalizedImports()
|
||||
{
|
||||
$loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/localized')));
|
||||
$routeCollection = $loader->load('importer-with-locale.xml');
|
||||
$routes = $routeCollection->all();
|
||||
|
||||
$this->assertCount(2, $routes, 'Two routes are loaded');
|
||||
$this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);
|
||||
|
||||
$this->assertEquals('/le-prefix/le-suffix', $routeCollection->get('imported.fr')->getPath());
|
||||
$this->assertEquals('/the-prefix/suffix', $routeCollection->get('imported.en')->getPath());
|
||||
}
|
||||
|
||||
public function testLocalizedImportsOfNotLocalizedRoutes()
|
||||
{
|
||||
$loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/localized')));
|
||||
$routeCollection = $loader->load('importer-with-locale-imports-non-localized-route.xml');
|
||||
$routes = $routeCollection->all();
|
||||
|
||||
$this->assertCount(2, $routes, 'Two routes are loaded');
|
||||
$this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);
|
||||
|
||||
$this->assertEquals('/le-prefix/suffix', $routeCollection->get('imported.fr')->getPath());
|
||||
$this->assertEquals('/the-prefix/suffix', $routeCollection->get('imported.en')->getPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @dataProvider getPathsToInvalidFiles
|
||||
@@ -382,4 +421,24 @@ class XmlFileLoaderTest extends TestCase
|
||||
$route = $routeCollection->get('baz_route');
|
||||
$this->assertSame('AppBundle:Baz:view', $route->getDefault('_controller'));
|
||||
}
|
||||
|
||||
public function testImportRouteWithNamePrefix()
|
||||
{
|
||||
$loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/import_with_name_prefix')));
|
||||
$routeCollection = $loader->load('routing.xml');
|
||||
|
||||
$this->assertNotNull($routeCollection->get('app_blog'));
|
||||
$this->assertEquals('/blog', $routeCollection->get('app_blog')->getPath());
|
||||
$this->assertNotNull($routeCollection->get('api_app_blog'));
|
||||
$this->assertEquals('/api/blog', $routeCollection->get('api_app_blog')->getPath());
|
||||
}
|
||||
|
||||
public function testImportRouteWithNoTrailingSlash()
|
||||
{
|
||||
$loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/import_with_no_trailing_slash')));
|
||||
$routeCollection = $loader->load('routing.xml');
|
||||
|
||||
$this->assertEquals('/slash/', $routeCollection->get('a_app_homepage')->getPath());
|
||||
$this->assertEquals('/no-slash', $routeCollection->get('b_app_homepage')->getPath());
|
||||
}
|
||||
}
|
||||
|
@@ -203,4 +203,105 @@ class YamlFileLoaderTest extends TestCase
|
||||
$route = $routeCollection->get('baz_route');
|
||||
$this->assertSame('AppBundle:Baz:view', $route->getDefault('_controller'));
|
||||
}
|
||||
|
||||
public function testImportRouteWithNamePrefix()
|
||||
{
|
||||
$loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/import_with_name_prefix')));
|
||||
$routeCollection = $loader->load('routing.yml');
|
||||
|
||||
$this->assertNotNull($routeCollection->get('app_blog'));
|
||||
$this->assertEquals('/blog', $routeCollection->get('app_blog')->getPath());
|
||||
$this->assertNotNull($routeCollection->get('api_app_blog'));
|
||||
$this->assertEquals('/api/blog', $routeCollection->get('api_app_blog')->getPath());
|
||||
}
|
||||
|
||||
public function testRemoteSourcesAreNotAccepted()
|
||||
{
|
||||
$loader = new YamlFileLoader(new FileLocatorStub());
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$loader->load('http://remote.com/here.yml');
|
||||
}
|
||||
|
||||
public function testLoadingLocalizedRoute()
|
||||
{
|
||||
$loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/localized')));
|
||||
$routes = $loader->load('localized-route.yml');
|
||||
|
||||
$this->assertCount(3, $routes);
|
||||
}
|
||||
|
||||
public function testImportingRoutesFromDefinition()
|
||||
{
|
||||
$loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/localized')));
|
||||
$routes = $loader->load('importing-localized-route.yml');
|
||||
|
||||
$this->assertCount(3, $routes);
|
||||
$this->assertEquals('/nl', $routes->get('home.nl')->getPath());
|
||||
$this->assertEquals('/en', $routes->get('home.en')->getPath());
|
||||
$this->assertEquals('/here', $routes->get('not_localized')->getPath());
|
||||
}
|
||||
|
||||
public function testImportingRoutesWithLocales()
|
||||
{
|
||||
$loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/localized')));
|
||||
$routes = $loader->load('importer-with-locale.yml');
|
||||
|
||||
$this->assertCount(2, $routes);
|
||||
$this->assertEquals('/nl/voorbeeld', $routes->get('imported.nl')->getPath());
|
||||
$this->assertEquals('/en/example', $routes->get('imported.en')->getPath());
|
||||
}
|
||||
|
||||
public function testImportingNonLocalizedRoutesWithLocales()
|
||||
{
|
||||
$loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/localized')));
|
||||
$routes = $loader->load('importer-with-locale-imports-non-localized-route.yml');
|
||||
|
||||
$this->assertCount(2, $routes);
|
||||
$this->assertEquals('/nl/imported', $routes->get('imported.nl')->getPath());
|
||||
$this->assertEquals('/en/imported', $routes->get('imported.en')->getPath());
|
||||
}
|
||||
|
||||
public function testImportingRoutesWithOfficialLocales()
|
||||
{
|
||||
$loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/localized')));
|
||||
$routes = $loader->load('officially_formatted_locales.yml');
|
||||
|
||||
$this->assertCount(3, $routes);
|
||||
$this->assertEquals('/omelette-au-fromage', $routes->get('official.fr.UTF-8')->getPath());
|
||||
$this->assertEquals('/eu-não-sou-espanhol', $routes->get('official.pt-PT')->getPath());
|
||||
$this->assertEquals('/churrasco', $routes->get('official.pt_BR')->getPath());
|
||||
}
|
||||
|
||||
public function testImportingRoutesFromDefinitionMissingLocalePrefix()
|
||||
{
|
||||
$loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/localized')));
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$loader->load('missing-locale-in-importer.yml');
|
||||
}
|
||||
|
||||
public function testImportingRouteWithoutPathOrLocales()
|
||||
{
|
||||
$loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/localized')));
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$loader->load('route-without-path-or-locales.yml');
|
||||
}
|
||||
|
||||
public function testImportingWithControllerDefault()
|
||||
{
|
||||
$loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/localized')));
|
||||
$routes = $loader->load('importer-with-controller-default.yml');
|
||||
$this->assertCount(3, $routes);
|
||||
$this->assertEquals('DefaultController::defaultAction', $routes->get('home.en')->getDefault('_controller'));
|
||||
$this->assertEquals('DefaultController::defaultAction', $routes->get('home.nl')->getDefault('_controller'));
|
||||
$this->assertEquals('DefaultController::defaultAction', $routes->get('not_localized')->getDefault('_controller'));
|
||||
}
|
||||
|
||||
public function testImportRouteWithNoTrailingSlash()
|
||||
{
|
||||
$loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/import_with_no_trailing_slash')));
|
||||
$routeCollection = $loader->load('routing.yml');
|
||||
|
||||
$this->assertEquals('/slash/', $routeCollection->get('a_app_homepage')->getPath());
|
||||
$this->assertEquals('/no-slash', $routeCollection->get('b_app_homepage')->getPath());
|
||||
}
|
||||
}
|
||||
|
@@ -17,24 +17,6 @@ use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
class DumpedUrlMatcherTest extends UrlMatcherTest
|
||||
{
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @expectedExceptionMessage The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.
|
||||
*/
|
||||
public function testSchemeRequirement()
|
||||
{
|
||||
parent::testSchemeRequirement();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @expectedExceptionMessage The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.
|
||||
*/
|
||||
public function testSchemeAndMethodMismatch()
|
||||
{
|
||||
parent::testSchemeRequirement();
|
||||
}
|
||||
|
||||
protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null)
|
||||
{
|
||||
static $i = 0;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user