diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 8a1ec7bb5cd4..d022e02c4bc5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -82,8 +82,11 @@ use Symfony\Component\PropertyInfo\PropertyInitializableExtractorInterface; use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; +use Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper; use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader; use Symfony\Component\Routing\Loader\AnnotationFileLoader; +use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; +use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Serializer\Encoder\DecoderInterface; @@ -754,6 +757,12 @@ private function registerRouterConfiguration(array $config, ContainerBuilder $co if (isset($config['type'])) { $argument['resource_type'] = $config['type']; } + if (!class_exists(CompiledUrlMatcher::class)) { + $argument['matcher_class'] = $argument['matcher_base_class']; + $argument['matcher_dumper_class'] = PhpMatcherDumper::class; + $argument['generator_class'] = $argument['generator_base_class']; + $argument['generator_dumper_class'] = PhpGeneratorDumper::class; + } $router->replaceArgument(2, $argument); $container->setParameter('request_listener.http_port', $config['http_port']); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml index 03bac811b255..bdce1956a301 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml @@ -59,13 +59,13 @@ %kernel.cache_dir% %kernel.debug% - Symfony\Component\Routing\Generator\UrlGenerator + Symfony\Component\Routing\Generator\CompiledUrlGenerator Symfony\Component\Routing\Generator\UrlGenerator - Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper + Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper %router.cache_class_prefix%UrlGenerator - Symfony\Bundle\FrameworkBundle\Routing\RedirectableUrlMatcher + Symfony\Bundle\FrameworkBundle\Routing\RedirectableCompiledUrlMatcher Symfony\Bundle\FrameworkBundle\Routing\RedirectableUrlMatcher - Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper + Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper %router.cache_class_prefix%UrlMatcher diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/RedirectableCompiledUrlMatcher.php b/src/Symfony/Bundle/FrameworkBundle/Routing/RedirectableCompiledUrlMatcher.php new file mode 100644 index 000000000000..2a6c6b843062 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Routing/RedirectableCompiledUrlMatcher.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Routing; + +use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; +use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; + +/** + * @author Fabien Potencier + * + * @internal + */ +class RedirectableCompiledUrlMatcher extends CompiledUrlMatcher implements RedirectableUrlMatcherInterface +{ + /** + * {@inheritdoc} + */ + public function redirect($path, $route, $scheme = null) + { + return [ + '_controller' => 'Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController::urlRedirectAction', + 'path' => $path, + 'permanent' => true, + 'scheme' => $scheme, + 'httpPort' => $this->context->getHttpPort(), + 'httpsPort' => $this->context->getHttpsPort(), + '_route' => $route, + ]; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/RedirectableUrlMatcher.php b/src/Symfony/Bundle/FrameworkBundle/Routing/RedirectableUrlMatcher.php index fd1594c8833f..13ad12dccf86 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Routing/RedirectableUrlMatcher.php +++ b/src/Symfony/Bundle/FrameworkBundle/Routing/RedirectableUrlMatcher.php @@ -11,10 +11,14 @@ namespace Symfony\Bundle\FrameworkBundle\Routing; +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3.', RedirectableUrlMatcher::class), E_USER_DEPRECATED); + use Symfony\Component\Routing\Matcher\RedirectableUrlMatcher as BaseMatcher; /** * @author Fabien Potencier + * + * @deprecated since Symfony 4.3 */ class RedirectableUrlMatcher extends BaseMatcher { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableCompiledUrlMatcherTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableCompiledUrlMatcherTest.php new file mode 100644 index 000000000000..bf61409d4ee2 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableCompiledUrlMatcherTest.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Routing; + +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\FrameworkBundle\Routing\RedirectableCompiledUrlMatcher; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * @requires function \Symfony\Component\Routing\Matcher\CompiledUrlMatcher::match + */ +class RedirectableCompiledUrlMatcherTest extends TestCase +{ + public function testRedirectWhenNoSlash() + { + $routes = new RouteCollection(); + $routes->add('foo', new Route('/foo/')); + + $matcher = $this->getMatcher($routes, $context = new RequestContext()); + + $this->assertEquals([ + '_controller' => 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction', + 'path' => '/foo/', + 'permanent' => true, + 'scheme' => null, + 'httpPort' => $context->getHttpPort(), + 'httpsPort' => $context->getHttpsPort(), + '_route' => 'foo', + ], + $matcher->match('/foo') + ); + } + + public function testSchemeRedirect() + { + $routes = new RouteCollection(); + $routes->add('foo', new Route('/foo', [], [], [], '', ['https'])); + + $matcher = $this->getMatcher($routes, $context = new RequestContext()); + + $this->assertEquals([ + '_controller' => 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction', + 'path' => '/foo', + 'permanent' => true, + 'scheme' => 'https', + 'httpPort' => $context->getHttpPort(), + 'httpsPort' => $context->getHttpsPort(), + '_route' => 'foo', + ], + $matcher->match('/foo') + ); + } + + private function getMatcher(RouteCollection $routes, RequestContext $context) + { + $dumper = new CompiledUrlMatcherDumper($routes); + + return new RedirectableCompiledUrlMatcher($dumper->getCompiledRoutes(), $context); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php index d87eee58ccb4..1c11cf9e0902 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php @@ -17,6 +17,9 @@ use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; +/** + * @group legacy + */ class RedirectableUrlMatcherTest extends TestCase { public function testRedirectWhenNoSlash() diff --git a/src/Symfony/Component/Routing/CHANGELOG.md b/src/Symfony/Component/Routing/CHANGELOG.md index 4d97d4060ec8..5e8a998cd74f 100644 --- a/src/Symfony/Component/Routing/CHANGELOG.md +++ b/src/Symfony/Component/Routing/CHANGELOG.md @@ -1,6 +1,13 @@ CHANGELOG ========= +4.3.0 +----- + + * added `CompiledUrlMatcher` and `CompiledUrlMatcherDumper` + * added `CompiledUrlGenerator` and `CompiledUrlGeneratorDumper` + * deprecated `PhpUrlGeneratorDumped` and `PhpMatcherDumper` + 4.2.0 ----- diff --git a/src/Symfony/Component/Routing/Generator/CompiledUrlGenerator.php b/src/Symfony/Component/Routing/Generator/CompiledUrlGenerator.php new file mode 100644 index 000000000000..41cd5893ae2f --- /dev/null +++ b/src/Symfony/Component/Routing/Generator/CompiledUrlGenerator.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Generator; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Routing\Exception\RouteNotFoundException; +use Symfony\Component\Routing\RequestContext; + +/** + * Generates URLs based on rules dumped by CompiledUrlGeneratorDumper. + */ +class CompiledUrlGenerator extends UrlGenerator +{ + private $compiledRoutes = []; + private $defaultLocale; + + public function __construct(array $compiledRoutes, RequestContext $context, LoggerInterface $logger = null, string $defaultLocale = null) + { + $this->compiledRoutes = $compiledRoutes; + $this->context = $context; + $this->logger = $logger; + $this->defaultLocale = $defaultLocale; + } + + public function generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH) + { + $locale = $parameters['_locale'] + ?? $this->context->getParameter('_locale') + ?: $this->defaultLocale; + + if (null !== $locale) { + do { + if (($this->compiledRoutes[$name.'.'.$locale][1]['_canonical_route'] ?? null) === $name) { + unset($parameters['_locale']); + $name .= '.'.$locale; + break; + } + } while (false !== $locale = strstr($locale, '_', true)); + } + + if (!isset($this->compiledRoutes[$name])) { + throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); + } + + list($variables, $defaults, $requirements, $tokens, $hostTokens, $requiredSchemes) = $this->compiledRoutes[$name]; + + return $this->doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes); + } +} diff --git a/src/Symfony/Component/Routing/Generator/Dumper/CompiledUrlGeneratorDumper.php b/src/Symfony/Component/Routing/Generator/Dumper/CompiledUrlGeneratorDumper.php new file mode 100644 index 000000000000..e90a40a26f0f --- /dev/null +++ b/src/Symfony/Component/Routing/Generator/Dumper/CompiledUrlGeneratorDumper.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Generator\Dumper; + +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; + +/** + * CompiledUrlGeneratorDumper creates a PHP array to be used with CompiledUrlGenerator. + * + * @author Fabien Potencier + * @author Tobias Schultze + * @author Nicolas Grekas + */ +class CompiledUrlGeneratorDumper extends GeneratorDumper +{ + public function getCompiledRoutes(): array + { + $compiledRoutes = []; + foreach ($this->getRoutes()->all() as $name => $route) { + $compiledRoute = $route->compile(); + + $compiledRoutes[$name] = [ + $compiledRoute->getVariables(), + $route->getDefaults(), + $route->getRequirements(), + $compiledRoute->getTokens(), + $compiledRoute->getHostTokens(), + $route->getSchemes(), + ]; + } + + return $compiledRoutes; + } + + /** + * {@inheritdoc} + */ + public function dump(array $options = []) + { + return <<generateDeclaredRoutes()} +]; + +EOF; + } + + /** + * Generates PHP code representing an array of defined routes + * together with the routes properties (e.g. requirements). + */ + private function generateDeclaredRoutes(): string + { + $routes = ''; + foreach ($this->getCompiledRoutes() as $name => $properties) { + $routes .= sprintf("\n '%s' => %s,", $name, CompiledUrlMatcherDumper::export($properties)); + } + + return $routes; + } +} diff --git a/src/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php b/src/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php index 7af8f69fb7df..3869ffda4eeb 100644 --- a/src/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php +++ b/src/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php @@ -11,13 +11,17 @@ namespace Symfony\Component\Routing\Generator\Dumper; -use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "CompiledUrlGeneratorDumper" instead.', PhpGeneratorDumper::class), E_USER_DEPRECATED); + +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; /** * PhpGeneratorDumper creates a PHP class able to generate URLs for a given set of routes. * * @author Fabien Potencier * @author Tobias Schultze + * + * @deprecated since Symfony 4.3, use CompiledUrlGeneratorDumper instead. */ class PhpGeneratorDumper extends GeneratorDumper { @@ -92,7 +96,7 @@ private function generateDeclaredRoutes() $properties[] = $compiledRoute->getHostTokens(); $properties[] = $route->getSchemes(); - $routes .= sprintf(" '%s' => %s,\n", $name, PhpMatcherDumper::export($properties)); + $routes .= sprintf(" '%s' => %s,\n", $name, CompiledUrlMatcherDumper::export($properties)); } $routes .= ' ]'; diff --git a/src/Symfony/Component/Routing/Matcher/CompiledUrlMatcher.php b/src/Symfony/Component/Routing/Matcher/CompiledUrlMatcher.php new file mode 100644 index 000000000000..e15cda778658 --- /dev/null +++ b/src/Symfony/Component/Routing/Matcher/CompiledUrlMatcher.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher; + +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; +use Symfony\Component\Routing\RequestContext; + +/** + * Matches URLs based on rules dumped by CompiledUrlMatcherDumper. + * + * @author Nicolas Grekas + */ +class CompiledUrlMatcher extends UrlMatcher +{ + use CompiledUrlMatcherTrait; + + public function __construct(array $compiledRoutes, RequestContext $context) + { + $this->context = $context; + list($this->matchHost, $this->staticRoutes, $this->regexpList, $this->dynamicRoutes, $this->checkCondition) = $compiledRoutes; + } +} diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/CompiledUrlMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/CompiledUrlMatcherDumper.php new file mode 100644 index 000000000000..367ad70cd47d --- /dev/null +++ b/src/Symfony/Component/Routing/Matcher/Dumper/CompiledUrlMatcherDumper.php @@ -0,0 +1,500 @@ + + * + * 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\ExpressionLanguage\ExpressionFunctionProviderInterface; +use Symfony\Component\ExpressionLanguage\ExpressionLanguage; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * CompiledUrlMatcherDumper creates PHP arrays to be used with CompiledUrlMatcher. + * + * @author Fabien Potencier + * @author Tobias Schultze + * @author Arnaud Le Blanc + * @author Nicolas Grekas + */ +class CompiledUrlMatcherDumper extends MatcherDumper +{ + private $expressionLanguage; + private $signalingException; + + /** + * @var ExpressionFunctionProviderInterface[] + */ + private $expressionLanguageProviders = []; + + /** + * {@inheritdoc} + */ + public function dump(array $options = []) + { + return <<generateCompiledRoutes()}]; + +EOF; + } + + public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) + { + $this->expressionLanguageProviders[] = $provider; + } + + /** + * Generates the arrays for CompiledUrlMatcher's constructor. + */ + public function getCompiledRoutes(bool $forDump = false): array + { + // 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), '}.{', '(/)'); + } + + $routes->addRoute($host ?: '/(.*)', [$name, $route]); + } + + if ($matchHost) { + $compiledRoutes = [true]; + $routes = $routes->populateCollection(new RouteCollection()); + } else { + $compiledRoutes = [false]; + $routes = $this->getRoutes(); + } + + list($staticRoutes, $dynamicRoutes) = $this->groupStaticRoutes($routes); + + $conditions = [null]; + $compiledRoutes[] = $this->compileStaticRoutes($staticRoutes, $conditions); + $chunkLimit = \count($dynamicRoutes); + + while (true) { + try { + $this->signalingException = new \RuntimeException('preg_match(): Compilation failed: regular expression is too large'); + $compiledRoutes = array_merge($compiledRoutes, $this->compileDynamicRoutes($dynamicRoutes, $matchHost, $chunkLimit, $conditions)); + + break; + } catch (\Exception $e) { + if (1 < $chunkLimit && $this->signalingException === $e) { + $chunkLimit = 1 + ($chunkLimit >> 1); + continue; + } + throw $e; + } + } + + if ($forDump) { + $compiledRoutes[2] = $compiledRoutes[4]; + } + unset($conditions[0]); + + if ($conditions) { + foreach ($conditions as $expression => $condition) { + $conditions[$expression] = "case {$condition}: return {$expression};"; + } + + $checkConditionCode = <<indent(implode("\n", $conditions), 3)} + } + } +EOF; + $compiledRoutes[4] = $forDump ? $checkConditionCode .= ",\n" : eval('return '.$checkConditionCode.';'); + } else { + $compiledRoutes[4] = $forDump ? " null, // \$checkCondition\n" : null; + } + + return $compiledRoutes; + } + + private function generateCompiledRoutes(): string + { + list($matchHost, $staticRoutes, $regexpCode, $dynamicRoutes, $checkConditionCode) = $this->getCompiledRoutes(true); + + $code = self::export($matchHost).', // $matchHost'."\n"; + + $code .= '[ // $staticRoutes'."\n"; + foreach ($staticRoutes as $path => $routes) { + $code .= sprintf(" %s => [\n", self::export($path)); + foreach ($routes as $route) { + $code .= sprintf(" [%s, %s, %s, %s, %s, %s, %s],\n", ...array_map([__CLASS__, 'export'], $route)); + } + $code .= " ],\n"; + } + $code .= "],\n"; + + $code .= sprintf("[ // \$regexpList%s\n],\n", $regexpCode); + + $code .= '[ // $dynamicRoutes'."\n"; + foreach ($dynamicRoutes as $path => $routes) { + $code .= sprintf(" %s => [\n", self::export($path)); + foreach ($routes as $route) { + $code .= sprintf(" [%s, %s, %s, %s, %s, %s, %s],\n", ...array_map([__CLASS__, 'export'], $route)); + } + $code .= " ],\n"; + } + $code .= "],\n"; + $code = preg_replace('/ => \[\n (\[.+?),\n \],/', ' => [$1],', $code); + + return $this->indent($code, 1).$checkConditionCode; + } + + /** + * Splits static routes from dynamic routes, so that they can be matched first, using a simple switch. + */ + private function groupStaticRoutes(RouteCollection $collection): array + { + $staticRoutes = $dynamicRegex = []; + $dynamicRoutes = new RouteCollection(); + + foreach ($collection->all() as $name => $route) { + $compiledRoute = $route->compile(); + $hostRegex = $compiledRoute->getHostRegex(); + $regex = $compiledRoute->getRegex(); + if ($hasTrailingSlash = '/' !== $route->getPath()) { + $pos = strrpos($regex, '$'); + $hasTrailingSlash = '/' === $regex[$pos - 1]; + $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); + } + + if (!$compiledRoute->getPathVariables()) { + $host = !$compiledRoute->getHostVariables() ? $route->getHost() : ''; + $url = $route->getPath(); + if ($hasTrailingSlash) { + $url = substr($url, 0, -1); + } + foreach ($dynamicRegex as list($hostRx, $rx)) { + if (preg_match($rx, $url) && (!$host || !$hostRx || preg_match($hostRx, $host))) { + $dynamicRegex[] = [$hostRegex, $regex]; + $dynamicRoutes->add($name, $route); + continue 2; + } + } + + $staticRoutes[$url][$name] = [$route, $hasTrailingSlash]; + } else { + $dynamicRegex[] = [$hostRegex, $regex]; + $dynamicRoutes->add($name, $route); + } + } + + return [$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, array &$conditions): array + { + if (!$staticRoutes) { + return []; + } + $compiledRoutes = []; + + foreach ($staticRoutes as $url => $routes) { + $compiledRoutes[$url] = []; + foreach ($routes as $name => list($route, $hasTrailingSlash)) { + $compiledRoutes[$url][] = $this->compileRoute($route, $name, !$route->compile()->getHostVariables() ? $route->getHost() : $route->compile()->getHostRegex() ?: null, $hasTrailingSlash, false, $conditions); + } + } + + return $compiledRoutes; + } + + /** + * 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, array &$conditions): array + { + if (!$collection->all()) { + return [[], [], '']; + } + $regexpList = []; + $code = ''; + $state = (object) [ + 'regexMark' => 0, + 'regex' => [], + 'routes' => [], + 'mark' => 0, + 'markTail' => 0, + 'hostVars' => [], + 'vars' => [], + ]; + $state->getVars = static function ($m) use ($state) { + if ('_route' === $m[1]) { + return '?:'; + } + + $state->vars[] = $m[1]; + + return ''; + }; + + $chunkSize = 0; + $prev = null; + $perModifiers = []; + 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[] = [$rx[0], $routes]; + $prev = $rx[0]; + } + $routes->add($name, $route); + } + + foreach ($perModifiers as list($modifiers, $routes)) { + $prev = false; + $perHost = []; + foreach ($routes->all() as $name => $route) { + $regex = $route->compile()->getHostRegex(); + if ($prev !== $regex) { + $routes = new RouteCollection(); + $perHost[] = [$regex, $routes]; + $prev = $regex; + } + $routes->add($name, $route); + } + $prev = false; + $rx = '{^(?'; + $code .= "\n {$state->mark} => ".self::export($rx); + $startingMark = $state->mark; + $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 = []; + $hostRegex = '(?i:'.preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]).')\.'; + $state->hostVars = $state->vars; + } else { + $hostRegex = '(?:(?:[^./]*+\.)++)'; + $state->hostVars = []; + } + $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 = []; + $regex = preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]); + if ($hasTrailingSlash = '/' !== $regex && '/' === $regex[-1]) { + $regex = substr($regex, 0, -1); + } + $hasTrailingVar = (bool) preg_match('#\{\w+\}/?$#', $route->getPath()); + + $tree->addRoute($regex, [$name, $regex, $state->vars, $route, $hasTrailingSlash, $hasTrailingVar]); + } + + $code .= $this->compileStaticPrefixCollection($tree, $state, 0, $conditions); + } + 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(); + } + + $regexpList[$startingMark] = $state->regex; + } + + $state->routes[$state->mark][] = [null, null, null, null, false, false, 0]; + unset($state->getVars); + + return [$regexpList, $state->routes, $code]; + } + + /** + * 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, array &$conditions): 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), $conditions)); + $code .= "\n .')'"; + $state->regex .= ')'; + ++$state->markTail; + continue; + } + + list($name, $regex, $vars, $route, $hasTrailingSlash, $hasTrailingVar) = $route; + $compiledRoute = $route->compile(); + $vars = array_merge($state->hostVars, $vars); + + if ($compiledRoute->getRegex() === $prevRegex) { + $state->routes[$state->mark][] = $this->compileRoute($route, $name, $vars, $hasTrailingSlash, $hasTrailingVar, $conditions); + 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; + + $prevRegex = $compiledRoute->getRegex(); + $state->routes[$state->mark] = [$this->compileRoute($route, $name, $vars, $hasTrailingSlash, $hasTrailingVar, $conditions)]; + } + + return $code; + } + + /** + * Compiles a single Route to PHP code used to match it against the path info. + */ + private function compileRoute(Route $route, string $name, $vars, bool $hasTrailingSlash, bool $hasTrailingVar, array &$conditions): array + { + $defaults = $route->getDefaults(); + + if (isset($defaults['_canonical_route'])) { + $name = $defaults['_canonical_route']; + unset($defaults['_canonical_route']); + } + + if ($condition = $route->getCondition()) { + $condition = $this->getExpressionLanguage()->compile($condition, ['context', 'request']); + $condition = $conditions[$condition] ?? $conditions[$condition] = (false !== strpos($condition, '$request') ? 1 : -1) * \count($conditions); + } else { + $condition = null; + } + + return [ + ['_route' => $name] + $defaults, + $vars, + array_flip($route->getMethods()) ?: null, + array_flip($route->getSchemes()) ?: null, + $hasTrailingSlash, + $hasTrailingVar, + $condition, + ]; + } + + private function getExpressionLanguage() + { + if (null === $this->expressionLanguage) { + if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { + throw new \LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); + } + $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); + } + + 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 '[]'; + } + + $i = 0; + $export = '['; + + 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); + } +} diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherTrait.php b/src/Symfony/Component/Routing/Matcher/Dumper/CompiledUrlMatcherTrait.php similarity index 93% rename from src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherTrait.php rename to src/Symfony/Component/Routing/Matcher/Dumper/CompiledUrlMatcherTrait.php index 7e370b9d20a4..2ad68d3a3d70 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherTrait.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/CompiledUrlMatcherTrait.php @@ -21,7 +21,7 @@ * * @internal */ -trait PhpMatcherTrait +trait CompiledUrlMatcherTrait { private $matchHost = false; private $staticRoutes = []; @@ -126,8 +126,13 @@ private function doMatch(string $pathinfo, array &$allow = [], array &$allowSche foreach ($this->regexpList as $offset => $regex) { while (preg_match($regex, $matchedPathinfo, $matches)) { foreach ($this->dynamicRoutes[$m = (int) $matches['MARK']] as list($ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar, $condition)) { - if ($condition && !($this->checkCondition)($condition, $context, 0 < $condition ? $request ?? $request = $this->request ?: $this->createRequest($pathinfo) : null)) { - continue; + if (null !== $condition) { + if (0 === $condition) { // marks the last route in the regexp + continue 3; + } + if (!($this->checkCondition)($condition, $context, 0 < $condition ? $request ?? $request = $this->request ?: $this->createRequest($pathinfo) : null)) { + continue; + } } if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) { diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php index 61b2ed320a22..2177180f4d5c 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php @@ -11,10 +11,7 @@ namespace Symfony\Component\Routing\Matcher\Dumper; -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.2, use "CompiledUrlMatcherDumper" instead.', PhpMatcherDumper::class), E_USER_DEPRECATED); /** * PhpMatcherDumper creates a PHP class able to match URLs for a given set of routes. @@ -23,17 +20,11 @@ * @author Tobias Schultze * @author Arnaud Le Blanc * @author Nicolas Grekas + * + * @deprecated since Symfony 4.2, use CompiledUrlMatcherDumper instead. */ -class PhpMatcherDumper extends MatcherDumper +class PhpMatcherDumper extends CompiledUrlMatcherDumper { - private $expressionLanguage; - private $signalingException; - - /** - * @var ExpressionFunctionProviderInterface[] - */ - private $expressionLanguageProviders = []; - /** * Dumps a set of routes to a PHP class. * @@ -53,13 +44,17 @@ public function dump(array $options = []) 'base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', ], $options); - // trailing slash support is only enabled if we know how to redirect the user - $interfaces = class_implements($options['base_class']); + $code = parent::dump(); + $code = preg_replace('#\n ([^ ].*?) // \$(\w++)$#m', "\n \$this->$2 = $1", $code); + $code = str_replace(",\n $", ";\n $", $code); + $code = substr($code, strpos($code, '$this') - 4, -5).";\n"; + $code = preg_replace('/^ \$this->\w++ = (?:null|false|\[\n \]);\n/m', '', $code); + $code = str_replace("\n ", "\n ", "\n".$code); return <<context = \$context; -{$this->generateProperties()} } + \$this->context = \$context;{$code} } } EOF; } - - public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) - { - $this->expressionLanguageProviders[] = $provider; - } - - /** - * Generates the code for the match method implementing UrlMatcherInterface. - */ - private function generateProperties(): string - { - // 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), '}.{', '(/)'); - } - - $routes->addRoute($host ?: '/(.*)', [$name, $route]); - } - - if ($matchHost) { - $code = '$this->matchHost = true;'."\n"; - $routes = $routes->populateCollection(new RouteCollection()); - } else { - $code = ''; - $routes = $this->getRoutes(); - } - - list($staticRoutes, $dynamicRoutes) = $this->groupStaticRoutes($routes); - - $conditions = [null]; - $code .= $this->compileStaticRoutes($staticRoutes, $conditions); - $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, $conditions); - break; - } catch (\Exception $e) { - if (1 < $chunkLimit && $this->signalingException === $e) { - $chunkLimit = 1 + ($chunkLimit >> 1); - continue; - } - throw $e; - } - } - - unset($conditions[0]); - - if (!$conditions) { - return $this->indent($code, 2); - } - - foreach ($conditions as $expression => $condition) { - $conditions[$expression] = "case {$condition}: return {$expression};"; - } - - return $this->indent($code, 2).<<checkCondition = static function (\$condition, \$context, \$request) { - switch (\$condition) { -{$this->indent(implode("\n", $conditions), 4)} - } - }; - -EOF; - } - - /** - * Splits static routes from dynamic routes, so that they can be matched first, using a simple switch. - */ - private function groupStaticRoutes(RouteCollection $collection): array - { - $staticRoutes = $dynamicRegex = []; - $dynamicRoutes = new RouteCollection(); - - foreach ($collection->all() as $name => $route) { - $compiledRoute = $route->compile(); - $hostRegex = $compiledRoute->getHostRegex(); - $regex = $compiledRoute->getRegex(); - if ($hasTrailingSlash = '/' !== $route->getPath()) { - $pos = strrpos($regex, '$'); - $hasTrailingSlash = '/' === $regex[$pos - 1]; - $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); - } - - if (!$compiledRoute->getPathVariables()) { - $host = !$compiledRoute->getHostVariables() ? $route->getHost() : ''; - $url = $route->getPath(); - if ($hasTrailingSlash) { - $url = substr($url, 0, -1); - } - foreach ($dynamicRegex as list($hostRx, $rx)) { - if (preg_match($rx, $url) && (!$host || !$hostRx || preg_match($hostRx, $host))) { - $dynamicRegex[] = [$hostRegex, $regex]; - $dynamicRoutes->add($name, $route); - continue 2; - } - } - - $staticRoutes[$url][$name] = [$route, $hasTrailingSlash]; - } else { - $dynamicRegex[] = [$hostRegex, $regex]; - $dynamicRoutes->add($name, $route); - } - } - - return [$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, array &$conditions): string - { - if (!$staticRoutes) { - return ''; - } - $code = ''; - - foreach ($staticRoutes as $url => $routes) { - $code .= self::export($url)." => [\n"; - foreach ($routes as $name => list($route, $hasTrailingSlash)) { - $code .= $this->compileRoute($route, $name, !$route->compile()->getHostVariables() ? $route->getHost() : $route->compile()->getHostRegex() ?: null, $hasTrailingSlash, false, $conditions); - } - $code .= "],\n"; - } - - if ($code) { - return "\$this->staticRoutes = [\n{$this->indent($code, 1)}];\n"; - } - - return $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, array &$conditions): string - { - if (!$collection->all()) { - return ''; - } - $code = ''; - $state = (object) [ - 'regex' => '', - 'routes' => '', - 'mark' => 0, - 'markTail' => 0, - 'hostVars' => [], - 'vars' => [], - ]; - $state->getVars = static function ($m) use ($state) { - if ('_route' === $m[1]) { - return '?:'; - } - - $state->vars[] = $m[1]; - - return ''; - }; - - $chunkSize = 0; - $prev = null; - $perModifiers = []; - 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[] = [$rx[0], $routes]; - $prev = $rx[0]; - } - $routes->add($name, $route); - } - - foreach ($perModifiers as list($modifiers, $routes)) { - $prev = false; - $perHost = []; - foreach ($routes->all() as $name => $route) { - $regex = $route->compile()->getHostRegex(); - if ($prev !== $regex) { - $routes = new RouteCollection(); - $perHost[] = [$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 = []; - $hostRegex = '(?i:'.preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]).')\.'; - $state->hostVars = $state->vars; - } else { - $hostRegex = '(?:(?:[^./]*+\.)++)'; - $state->hostVars = []; - } - $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 = []; - $regex = preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]); - if ($hasTrailingSlash = '/' !== $regex && '/' === $regex[-1]) { - $regex = substr($regex, 0, -1); - } - $hasTrailingVar = (bool) preg_match('#\{\w+\}/?$#', $route->getPath()); - - $tree->addRoute($regex, [$name, $regex, $state->vars, $route, $hasTrailingSlash, $hasTrailingVar]); - } - - $code .= $this->compileStaticPrefixCollection($tree, $state, 0, $conditions); - } - 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(); - } - } - - unset($state->getVars); - - return "\$this->regexpList = [{$code}\n];\n" - ."\$this->dynamicRoutes = [\n{$this->indent($state->routes, 1)}];\n"; - } - - /** - * 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, array &$conditions): 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), $conditions)); - $code .= "\n .')'"; - $state->regex .= ')'; - ++$state->markTail; - continue; - } - - list($name, $regex, $vars, $route, $hasTrailingSlash, $hasTrailingVar) = $route; - $compiledRoute = $route->compile(); - $vars = array_merge($state->hostVars, $vars); - - if ($compiledRoute->getRegex() === $prevRegex) { - $state->routes = substr_replace($state->routes, $this->compileRoute($route, $name, $vars, $hasTrailingSlash, $hasTrailingVar, $conditions), -3, 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; - - $prevRegex = $compiledRoute->getRegex(); - $state->routes .= sprintf("%s => [\n%s],\n", $state->mark, $this->compileRoute($route, $name, $vars, $hasTrailingSlash, $hasTrailingVar, $conditions)); - } - - return $code; - } - - /** - * Compiles a single Route to PHP code used to match it against the path info. - */ - private function compileRoute(Route $route, string $name, $vars, bool $hasTrailingSlash, bool $hasTrailingVar, array &$conditions): string - { - $defaults = $route->getDefaults(); - - if (isset($defaults['_canonical_route'])) { - $name = $defaults['_canonical_route']; - unset($defaults['_canonical_route']); - } - - if ($condition = $route->getCondition()) { - $condition = $this->getExpressionLanguage()->compile($condition, ['context', 'request']); - $condition = $conditions[$condition] ?? $conditions[$condition] = (false !== strpos($condition, '$request') ? 1 : -1) * \count($conditions); - } else { - $condition = 'null'; - } - - return sprintf( - " [%s, %s, %s, %s, %s, %s, %s],\n", - self::export(['_route' => $name] + $defaults), - self::export($vars), - self::export(array_flip($route->getMethods()) ?: null), - self::export(array_flip($route->getSchemes()) ?: null), - self::export($hasTrailingSlash), - self::export($hasTrailingVar), - $condition - ); - } - - private function getExpressionLanguage() - { - if (null === $this->expressionLanguage) { - if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { - throw new \LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); - } - $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); - } - - return $this->expressionLanguage; - } - - private function indent($code, $level = 1) - { - $code = preg_replace('/ => \[\n (\[.+),\n\],/', ' => [$1],', $code); - - 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 '[]'; - } - - $i = 0; - $export = '['; - - 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); - } } diff --git a/src/Symfony/Component/Routing/Router.php b/src/Symfony/Component/Routing/Router.php index 5fa85a538acc..35c2cf679d21 100644 --- a/src/Symfony/Component/Routing/Router.php +++ b/src/Symfony/Component/Routing/Router.php @@ -18,11 +18,17 @@ use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Generator\CompiledUrlGenerator; use Symfony\Component\Routing\Generator\ConfigurableRequirementsInterface; +use Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper; use Symfony\Component\Routing\Generator\Dumper\GeneratorDumperInterface; +use Symfony\Component\Routing\Generator\UrlGenerator; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; use Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface; use Symfony\Component\Routing\Matcher\RequestMatcherInterface; +use Symfony\Component\Routing\Matcher\UrlMatcher; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; /** @@ -127,14 +133,14 @@ public function setOptions(array $options) $this->options = [ 'cache_dir' => null, 'debug' => false, - 'generator_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', - 'generator_base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', - 'generator_dumper_class' => 'Symfony\\Component\\Routing\\Generator\\Dumper\\PhpGeneratorDumper', - 'generator_cache_class' => 'ProjectUrlGenerator', - 'matcher_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', - 'matcher_base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', - 'matcher_dumper_class' => 'Symfony\\Component\\Routing\\Matcher\\Dumper\\PhpMatcherDumper', - 'matcher_cache_class' => 'ProjectUrlMatcher', + 'generator_class' => CompiledUrlGenerator::class, + 'generator_base_class' => UrlGenerator::class, + 'generator_dumper_class' => CompiledUrlGeneratorDumper::class, + 'generator_cache_class' => 'UrlGenerator', + 'matcher_class' => CompiledUrlMatcher::class, + 'matcher_base_class' => UrlMatcher::class, + 'matcher_dumper_class' => CompiledUrlMatcherDumper::class, + 'matcher_cache_class' => 'UrlMatcher', 'resource_type' => null, 'strict_requirements' => true, ]; @@ -273,8 +279,14 @@ public function getMatcher() return $this->matcher; } + $compiled = is_a($this->options['matcher_class'], CompiledUrlMatcher::class, true); + if (null === $this->options['cache_dir'] || null === $this->options['matcher_cache_class']) { - $this->matcher = new $this->options['matcher_class']($this->getRouteCollection(), $this->context); + $routes = $this->getRouteCollection(); + if ($compiled) { + $routes = (new CompiledUrlMatcherDumper($routes))->getCompiledRoutes(); + } + $this->matcher = new $this->options['matcher_class']($routes, $this->context); if (method_exists($this->matcher, 'addExpressionLanguageProvider')) { foreach ($this->expressionLanguageProviders as $provider) { $this->matcher->addExpressionLanguageProvider($provider); @@ -302,6 +314,10 @@ function (ConfigCacheInterface $cache) { } ); + if ($compiled) { + return $this->matcher = new $this->options['matcher_class'](require $cache->getPath(), $this->context); + } + if (!class_exists($this->options['matcher_cache_class'], false)) { require_once $cache->getPath(); } @@ -320,8 +336,14 @@ public function getGenerator() return $this->generator; } + $compiled = is_a($this->options['generator_class'], CompiledUrlGenerator::class, true); + if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) { - $this->generator = new $this->options['generator_class']($this->getRouteCollection(), $this->context, $this->logger); + $routes = $this->getRouteCollection(); + if ($compiled) { + $routes = (new CompiledUrlGeneratorDumper($routes))->getCompiledRoutes(); + } + $this->generator = new $this->options['generator_class']($routes, $this->context, $this->logger); } else { $cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/'.$this->options['generator_cache_class'].'.php', function (ConfigCacheInterface $cache) { @@ -336,11 +358,15 @@ function (ConfigCacheInterface $cache) { } ); - if (!class_exists($this->options['generator_cache_class'], false)) { - require_once $cache->getPath(); - } + if ($compiled) { + $this->generator = new $this->options['generator_class'](require $cache->getPath(), $this->context, $this->logger); + } else { + if (!class_exists($this->options['generator_cache_class'], false)) { + require_once $cache->getPath(); + } - $this->generator = new $this->options['generator_cache_class']($this->context, $this->logger); + $this->generator = new $this->options['generator_cache_class']($this->context, $this->logger); + } } if ($this->generator instanceof ConfigurableRequirementsInterface) { diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher0.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher0.php new file mode 100644 index 000000000000..550288cb1fdf --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher0.php @@ -0,0 +1,17 @@ + [[['_route' => 'baz'], null, null, null, false, false, null]], + '/test/baz.html' => [[['_route' => 'baz2'], null, null, null, false, false, null]], + '/test/baz3' => [[['_route' => 'baz3'], null, null, null, true, false, null]], + '/foofoo' => [[['_route' => 'foofoo', 'def' => 'test'], null, null, null, false, false, null]], + '/spa ce' => [[['_route' => 'space'], null, null, null, false, false, null]], + '/multi/new' => [[['_route' => 'overridden2'], null, null, null, false, false, null]], + '/multi/hey' => [[['_route' => 'hey'], null, null, null, true, false, null]], + '/ababa' => [[['_route' => 'ababa'], null, null, null, false, false, null]], + '/route1' => [[['_route' => 'route1'], 'a.example.com', null, null, false, false, null]], + '/c2/route2' => [[['_route' => 'route2'], 'a.example.com', null, null, false, false, null]], + '/route4' => [[['_route' => 'route4'], 'a.example.com', null, null, false, false, null]], + '/c2/route3' => [[['_route' => 'route3'], 'b.example.com', null, null, false, false, null]], + '/route5' => [[['_route' => 'route5'], 'c.example.com', null, null, false, false, null]], + '/route6' => [[['_route' => 'route6'], null, null, null, false, false, null]], + '/route11' => [[['_route' => 'route11'], '#^(?P[^\\.]++)\\.example\\.com$#sDi', null, null, false, false, null]], + '/route12' => [[['_route' => 'route12', 'var1' => 'val'], '#^(?P[^\\.]++)\\.example\\.com$#sDi', null, null, false, false, null]], + '/route17' => [[['_route' => 'route17'], null, null, null, false, false, null]], + ], + [ // $regexpList + 0 => '{^(?' + .'|(?:(?:[^./]*+\\.)++)(?' + .'|/foo/(baz|symfony)(*:47)' + .'|/bar(?' + .'|/([^/]++)(*:70)' + .'|head/([^/]++)(*:90)' + .')' + .'|/test/([^/]++)(?' + .'|(*:115)' + .')' + .'|/([\']+)(*:131)' + .'|/a/(?' + .'|b\'b/([^/]++)(?' + .'|(*:160)' + .'|(*:168)' + .')' + .'|(.*)(*:181)' + .'|b\'b/([^/]++)(?' + .'|(*:204)' + .'|(*:212)' + .')' + .')' + .'|/multi/hello(?:/([^/]++))?(*:248)' + .'|/([^/]++)/b/([^/]++)(?' + .'|(*:279)' + .'|(*:287)' + .')' + .'|/aba/([^/]++)(*:309)' + .')|(?i:([^\\.]++)\\.example\\.com)\\.(?' + .'|/route1(?' + .'|3/([^/]++)(*:371)' + .'|4/([^/]++)(*:389)' + .')' + .')|(?i:c\\.example\\.com)\\.(?' + .'|/route15/([^/]++)(*:441)' + .')|(?:(?:[^./]*+\\.)++)(?' + .'|/route16/([^/]++)(*:489)' + .'|/a/(?' + .'|a\\.\\.\\.(*:510)' + .'|b/(?' + .'|([^/]++)(*:531)' + .'|c/([^/]++)(*:549)' + .')' + .')' + .')' + .')/?$}sD', + ], + [ // $dynamicRoutes + 47 => [[['_route' => 'foo', 'def' => 'test'], ['bar'], null, null, false, true, null]], + 70 => [[['_route' => 'bar'], ['foo'], ['GET' => 0, 'HEAD' => 1], null, false, true, null]], + 90 => [[['_route' => 'barhead'], ['foo'], ['GET' => 0], null, false, true, null]], + 115 => [ + [['_route' => 'baz4'], ['foo'], null, null, true, true, null], + [['_route' => 'baz5'], ['foo'], ['POST' => 0], null, true, true, null], + [['_route' => 'baz.baz6'], ['foo'], ['PUT' => 0], null, true, true, null], + ], + 131 => [[['_route' => 'quoter'], ['quoter'], null, null, false, true, null]], + 160 => [[['_route' => 'foo1'], ['foo'], ['PUT' => 0], null, false, true, null]], + 168 => [[['_route' => 'bar1'], ['bar'], null, null, false, true, null]], + 181 => [[['_route' => 'overridden'], ['var'], null, null, false, true, null]], + 204 => [[['_route' => 'foo2'], ['foo1'], null, null, false, true, null]], + 212 => [[['_route' => 'bar2'], ['bar1'], null, null, false, true, null]], + 248 => [[['_route' => 'helloWorld', 'who' => 'World!'], ['who'], null, null, false, true, null]], + 279 => [[['_route' => 'foo3'], ['_locale', 'foo'], null, null, false, true, null]], + 287 => [[['_route' => 'bar3'], ['_locale', 'bar'], null, null, false, true, null]], + 309 => [[['_route' => 'foo4'], ['foo'], null, null, false, true, null]], + 371 => [[['_route' => 'route13'], ['var1', 'name'], null, null, false, true, null]], + 389 => [[['_route' => 'route14', 'var1' => 'val'], ['var1', 'name'], null, null, false, true, null]], + 441 => [[['_route' => 'route15'], ['name'], null, null, false, true, null]], + 489 => [[['_route' => 'route16', 'var1' => 'val'], ['name'], null, null, false, true, null]], + 510 => [[['_route' => 'a'], [], null, null, false, false, null]], + 531 => [[['_route' => 'b'], ['var'], null, null, false, true, null]], + 549 => [ + [['_route' => 'c'], ['var'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher10.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher10.php new file mode 100644 index 000000000000..c1822190edea --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher10.php @@ -0,0 +1,2774 @@ + '{^(?' + .'|/c(?' + .'|f(?' + .'|cd20/([^/]++)/([^/]++)/([^/]++)/cfcd20(*:54)' + .'|e(?' + .'|cdb/([^/]++)/([^/]++)/([^/]++)/cfecdb(*:102)' + .'|e39/([^/]++)/([^/]++)/([^/]++)/cfee39(*:147)' + .')' + .'|a086/([^/]++)/([^/]++)/([^/]++)/cfa086(*:194)' + .'|004f/([^/]++)/([^/]++)/([^/]++)/cf004f(*:240)' + .')' + .'|4(?' + .'|ca42/([^/]++)/([^/]++)/([^/]++)/c4ca42(*:291)' + .'|5147/([^/]++)/([^/]++)/([^/]++)/c45147(*:337)' + .'|1000/([^/]++)/([^/]++)/([^/]++)/c41000(*:383)' + .')' + .'|8(?' + .'|1e72/([^/]++)/([^/]++)/([^/]++)/c81e72(*:434)' + .'|ffe9/([^/]++)/([^/]++)/([^/]++)/c8ffe9(*:480)' + .'|6a7e/([^/]++)/([^/]++)/([^/]++)/c86a7e(*:526)' + .')' + .'|9(?' + .'|f0f8/([^/]++)/([^/]++)/([^/]++)/c9f0f8(*:577)' + .'|e107/([^/]++)/([^/]++)/([^/]++)/c9e107(*:623)' + .')' + .'|2(?' + .'|0(?' + .'|ad4/([^/]++)/([^/]++)/([^/]++)/c20ad4(*:677)' + .'|3d8/([^/]++)/([^/]++)/([^/]++)/c203d8(*:722)' + .')' + .'|4cd7/([^/]++)/([^/]++)/([^/]++)/c24cd7(*:769)' + .')' + .'|5(?' + .'|1ce4/([^/]++)/([^/]++)/([^/]++)/c51ce4(*:820)' + .'|2f1b/([^/]++)/([^/]++)/([^/]++)/c52f1b(*:866)' + .'|ff25/([^/]++)/([^/]++)/([^/]++)/c5ff25(*:912)' + .')' + .'|7(?' + .'|4d97/([^/]++)/([^/]++)/([^/]++)/c74d97(*:963)' + .'|e124/([^/]++)/([^/]++)/([^/]++)/c7e124(*:1009)' + .')' + .'|16a53/([^/]++)/([^/]++)/([^/]++)/c16a53(*:1058)' + .'|0(?' + .'|c7c7/([^/]++)/([^/]++)/([^/]++)/c0c7c7(*:1109)' + .'|e190/([^/]++)/([^/]++)/([^/]++)/c0e190(*:1156)' + .'|42f4/([^/]++)/([^/]++)/([^/]++)/c042f4(*:1203)' + .'|58f5/([^/]++)/([^/]++)/([^/]++)/c058f5(*:1250)' + .')' + .'|e(?' + .'|debb/([^/]++)/([^/]++)/([^/]++)/cedebb(*:1302)' + .'|e631/([^/]++)/([^/]++)/([^/]++)/cee631(*:1349)' + .')' + .'|a(?' + .'|46c1/([^/]++)/([^/]++)/([^/]++)/ca46c1(*:1401)' + .'|f1a3/([^/]++)/([^/]++)/([^/]++)/caf1a3(*:1448)' + .')' + .'|b70ab/([^/]++)/([^/]++)/([^/]++)/cb70ab(*:1497)' + .'|d0069/([^/]++)/([^/]++)/([^/]++)/cd0069(*:1545)' + .'|3(?' + .'|e878/([^/]++)/([^/]++)/([^/]++)/c3e878(*:1596)' + .'|c59e/([^/]++)/([^/]++)/([^/]++)/c3c59e(*:1643)' + .')' + .')' + .'|/e(?' + .'|c(?' + .'|cbc8/([^/]++)/([^/]++)/([^/]++)/eccbc8(*:1701)' + .'|8(?' + .'|956/([^/]++)/([^/]++)/([^/]++)/ec8956(*:1751)' + .'|ce6/([^/]++)/([^/]++)/([^/]++)/ec8ce6(*:1797)' + .')' + .'|5dec/([^/]++)/([^/]++)/([^/]++)/ec5dec(*:1845)' + .')' + .'|4(?' + .'|da3b/([^/]++)/([^/]++)/([^/]++)/e4da3b(*:1897)' + .'|a622/([^/]++)/([^/]++)/([^/]++)/e4a622(*:1944)' + .'|6de7/([^/]++)/([^/]++)/([^/]++)/e46de7(*:1991)' + .'|4fea/([^/]++)/([^/]++)/([^/]++)/e44fea(*:2038)' + .')' + .'|3(?' + .'|6985/([^/]++)/([^/]++)/([^/]++)/e36985(*:2090)' + .'|796a/([^/]++)/([^/]++)/([^/]++)/e3796a(*:2137)' + .')' + .'|a(?' + .'|5d2f/([^/]++)/([^/]++)/([^/]++)/ea5d2f(*:2189)' + .'|e27d/([^/]++)/([^/]++)/([^/]++)/eae27d(*:2236)' + .')' + .'|2(?' + .'|c(?' + .'|420/([^/]++)/([^/]++)/([^/]++)/e2c420(*:2291)' + .'|0be/([^/]++)/([^/]++)/([^/]++)/e2c0be(*:2337)' + .')' + .'|ef52/([^/]++)/([^/]++)/([^/]++)/e2ef52(*:2385)' + .')' + .'|d(?' + .'|3d2c/([^/]++)/([^/]++)/([^/]++)/ed3d2c(*:2437)' + .'|a80a/([^/]++)/([^/]++)/([^/]++)/eda80a(*:2484)' + .'|dea8/([^/]++)/([^/]++)/([^/]++)/eddea8(*:2531)' + .')' + .'|b(?' + .'|16(?' + .'|0d/([^/]++)/([^/]++)/([^/]++)/eb160d(*:2586)' + .'|37/([^/]++)/([^/]++)/([^/]++)/eb1637(*:2631)' + .')' + .'|a0dc/([^/]++)/([^/]++)/([^/]++)/eba0dc(*:2679)' + .')' + .'|0(?' + .'|0da0/([^/]++)/([^/]++)/([^/]++)/e00da0(*:2731)' + .'|c641/([^/]++)/([^/]++)/([^/]++)/e0c641(*:2778)' + .')' + .'|e(?' + .'|cca5/([^/]++)/([^/]++)/([^/]++)/eecca5(*:2830)' + .'|d5af/([^/]++)/([^/]++)/([^/]++)/eed5af(*:2877)' + .')' + .'|96ed4/([^/]++)/([^/]++)/([^/]++)/e96ed4(*:2926)' + .'|1(?' + .'|6542/([^/]++)/([^/]++)/([^/]++)/e16542(*:2977)' + .'|e32e/([^/]++)/([^/]++)/([^/]++)/e1e32e(*:3024)' + .')' + .'|56954/([^/]++)/([^/]++)/([^/]++)/e56954(*:3073)' + .'|f(?' + .'|0d39/([^/]++)/([^/]++)/([^/]++)/ef0d39(*:3124)' + .'|e937/([^/]++)/([^/]++)/([^/]++)/efe937(*:3171)' + .'|575e/([^/]++)/([^/]++)/([^/]++)/ef575e(*:3218)' + .')' + .'|7b24b/([^/]++)/([^/]++)/([^/]++)/e7b24b(*:3267)' + .'|836d8/([^/]++)/([^/]++)/([^/]++)/e836d8(*:3315)' + .')' + .'|/a(?' + .'|8(?' + .'|7ff6/([^/]++)/([^/]++)/([^/]++)/a87ff6(*:3372)' + .'|baa5/([^/]++)/([^/]++)/([^/]++)/a8baa5(*:3419)' + .'|f15e/([^/]++)/([^/]++)/([^/]++)/a8f15e(*:3466)' + .'|c88a/([^/]++)/([^/]++)/([^/]++)/a8c88a(*:3513)' + .'|abb4/([^/]++)/([^/]++)/([^/]++)/a8abb4(*:3560)' + .')' + .'|a(?' + .'|b323/([^/]++)/([^/]++)/([^/]++)/aab323(*:3612)' + .'|942a/([^/]++)/([^/]++)/([^/]++)/aa942a(*:3659)' + .')' + .'|5(?' + .'|bfc9/([^/]++)/([^/]++)/([^/]++)/a5bfc9(*:3711)' + .'|771b/([^/]++)/([^/]++)/([^/]++)/a5771b(*:3758)' + .'|e001/([^/]++)/([^/]++)/([^/]++)/a5e001(*:3805)' + .'|97e5/([^/]++)/([^/]++)/([^/]++)/a597e5(*:3852)' + .'|16a8/([^/]++)/([^/]++)/([^/]++)/a516a8(*:3899)' + .')' + .'|1d0c6/([^/]++)/([^/]++)/([^/]++)/a1d0c6(*:3948)' + .'|6(?' + .'|84ec/([^/]++)/([^/]++)/([^/]++)/a684ec(*:3999)' + .'|6658/([^/]++)/([^/]++)/([^/]++)/a66658(*:4046)' + .')' + .'|3(?' + .'|f390/([^/]++)/([^/]++)/([^/]++)/a3f390(*:4098)' + .'|c65c/([^/]++)/([^/]++)/([^/]++)/a3c65c(*:4145)' + .')' + .'|d(?' + .'|61ab/([^/]++)/([^/]++)/([^/]++)/ad61ab(*:4197)' + .'|13a2/([^/]++)/([^/]++)/([^/]++)/ad13a2(*:4244)' + .'|972f/([^/]++)/([^/]++)/([^/]++)/ad972f(*:4291)' + .')' + .'|c(?' + .'|627a/([^/]++)/([^/]++)/([^/]++)/ac627a(*:4343)' + .'|1dd2/([^/]++)/([^/]++)/([^/]++)/ac1dd2(*:4390)' + .')' + .'|9(?' + .'|7da6/([^/]++)/([^/]++)/([^/]++)/a97da6(*:4442)' + .'|6b65/([^/]++)/([^/]++)/([^/]++)/a96b65(*:4489)' + .')' + .'|0(?' + .'|a080/([^/]++)/([^/]++)/([^/]++)/a0a080(*:4541)' + .'|2ffd/([^/]++)/([^/]++)/([^/]++)/a02ffd(*:4588)' + .'|1a03/([^/]++)/([^/]++)/([^/]++)/a01a03(*:4635)' + .')' + .'|4(?' + .'|a042/([^/]++)/([^/]++)/([^/]++)/a4a042(*:4687)' + .'|f236/([^/]++)/([^/]++)/([^/]++)/a4f236(*:4734)' + .'|9e94/([^/]++)/([^/]++)/([^/]++)/a49e94(*:4781)' + .')' + .'|2557a/([^/]++)/([^/]++)/([^/]++)/a2557a(*:4830)' + .'|b817c/([^/]++)/([^/]++)/([^/]++)/ab817c(*:4878)' + .')' + .'|/1(?' + .'|6(?' + .'|7909/([^/]++)/([^/]++)/([^/]++)/167909(*:4935)' + .'|a5cd/([^/]++)/([^/]++)/([^/]++)/16a5cd(*:4982)' + .'|51cf/([^/]++)/([^/]++)/([^/]++)/1651cf(*:5029)' + .')' + .'|f(?' + .'|0e3d/([^/]++)/([^/]++)/([^/]++)/1f0e3d(*:5081)' + .'|f(?' + .'|1de/([^/]++)/([^/]++)/([^/]++)/1ff1de(*:5131)' + .'|8a7/([^/]++)/([^/]++)/([^/]++)/1ff8a7(*:5177)' + .')' + .')' + .'|8(?' + .'|2be0/([^/]++)/([^/]++)/([^/]++)/182be0(*:5230)' + .'|d804/([^/]++)/([^/]++)/([^/]++)/18d804(*:5277)' + .'|9977/([^/]++)/([^/]++)/([^/]++)/189977(*:5324)' + .')' + .'|c(?' + .'|383c/([^/]++)/([^/]++)/([^/]++)/1c383c(*:5376)' + .'|9ac0/([^/]++)/([^/]++)/([^/]++)/1c9ac0(*:5423)' + .')' + .'|9(?' + .'|ca14/([^/]++)/([^/]++)/([^/]++)/19ca14(*:5475)' + .'|f3cd/([^/]++)/([^/]++)/([^/]++)/19f3cd(*:5522)' + .')' + .'|7(?' + .'|e621/([^/]++)/([^/]++)/([^/]++)/17e621(*:5574)' + .'|0000/([^/]++)/([^/]++)/([^/]++)/170000(*:5621)' + .'|d63b/([^/]++)/([^/]++)/([^/]++)/17d63b(*:5668)' + .')' + .'|4(?' + .'|bfa6/([^/]++)/([^/]++)/([^/]++)/14bfa6(*:5720)' + .'|0f69/([^/]++)/([^/]++)/([^/]++)/140f69(*:5767)' + .'|9e96/([^/]++)/([^/]++)/([^/]++)/149e96(*:5814)' + .'|2949/([^/]++)/([^/]++)/([^/]++)/142949(*:5861)' + .')' + .'|a(?' + .'|fa34/([^/]++)/([^/]++)/([^/]++)/1afa34(*:5913)' + .'|5b1e/([^/]++)/([^/]++)/([^/]++)/1a5b1e(*:5960)' + .')' + .'|3(?' + .'|8(?' + .'|597/([^/]++)/([^/]++)/([^/]++)/138597(*:6015)' + .'|bb0/([^/]++)/([^/]++)/([^/]++)/138bb0(*:6061)' + .')' + .'|f(?' + .'|e9d/([^/]++)/([^/]++)/([^/]++)/13fe9d(*:6112)' + .'|989/([^/]++)/([^/]++)/([^/]++)/13f989(*:6158)' + .'|3cf/([^/]++)/([^/]++)/([^/]++)/13f3cf(*:6204)' + .')' + .')' + .'|d7f7a/([^/]++)/([^/]++)/([^/]++)/1d7f7a(*:6254)' + .'|5(?' + .'|34b7/([^/]++)/([^/]++)/([^/]++)/1534b7(*:6305)' + .'|8f30/([^/]++)/([^/]++)/([^/]++)/158f30(*:6352)' + .'|4384/([^/]++)/([^/]++)/([^/]++)/154384(*:6399)' + .'|d4e8/([^/]++)/([^/]++)/([^/]++)/15d4e8(*:6446)' + .')' + .'|1(?' + .'|5f89/([^/]++)/([^/]++)/([^/]++)/115f89(*:6498)' + .'|b984/([^/]++)/([^/]++)/([^/]++)/11b984(*:6545)' + .')' + .'|068c6/([^/]++)/([^/]++)/([^/]++)/1068c6(*:6594)' + .'|be3bc/([^/]++)/([^/]++)/([^/]++)/1be3bc(*:6642)' + .')' + .'|/8(?' + .'|f(?' + .'|1(?' + .'|4e4/([^/]++)/([^/]++)/([^/]++)/8f14e4(*:6702)' + .'|21c/([^/]++)/([^/]++)/([^/]++)/8f121c(*:6748)' + .')' + .'|8551/([^/]++)/([^/]++)/([^/]++)/8f8551(*:6796)' + .'|5329/([^/]++)/([^/]++)/([^/]++)/8f5329(*:6843)' + .'|e009/([^/]++)/([^/]++)/([^/]++)/8fe009(*:6890)' + .')' + .'|e(?' + .'|296a/([^/]++)/([^/]++)/([^/]++)/8e296a(*:6942)' + .'|98d8/([^/]++)/([^/]++)/([^/]++)/8e98d8(*:6989)' + .'|fb10/([^/]++)/([^/]++)/([^/]++)/8efb10(*:7036)' + .'|6b42/([^/]++)/([^/]++)/([^/]++)/8e6b42(*:7083)' + .')' + .'|61398/([^/]++)/([^/]++)/([^/]++)/861398(*:7132)' + .'|1(?' + .'|2b4b/([^/]++)/([^/]++)/([^/]++)/812b4b(*:7183)' + .'|9f46/([^/]++)/([^/]++)/([^/]++)/819f46(*:7230)' + .'|6b11/([^/]++)/([^/]++)/([^/]++)/816b11(*:7277)' + .')' + .'|d(?' + .'|5e95/([^/]++)/([^/]++)/([^/]++)/8d5e95(*:7329)' + .'|3bba/([^/]++)/([^/]++)/([^/]++)/8d3bba(*:7376)' + .'|d48d/([^/]++)/([^/]++)/([^/]++)/8dd48d(*:7423)' + .'|7d8e/([^/]++)/([^/]++)/([^/]++)/8d7d8e(*:7470)' + .')' + .'|2(?' + .'|aa4b/([^/]++)/([^/]++)/([^/]++)/82aa4b(*:7522)' + .'|1(?' + .'|612/([^/]++)/([^/]++)/([^/]++)/821612(*:7572)' + .'|fa7/([^/]++)/([^/]++)/([^/]++)/821fa7(*:7618)' + .')' + .'|cec9/([^/]++)/([^/]++)/([^/]++)/82cec9(*:7666)' + .')' + .'|5(?' + .'|d8ce/([^/]++)/([^/]++)/([^/]++)/85d8ce(*:7718)' + .'|4d(?' + .'|6f/([^/]++)/([^/]++)/([^/]++)/854d6f(*:7768)' + .'|9f/([^/]++)/([^/]++)/([^/]++)/854d9f(*:7813)' + .')' + .')' + .'|4d9ee/([^/]++)/([^/]++)/([^/]++)/84d9ee(*:7863)' + .'|c(?' + .'|19f5/([^/]++)/([^/]++)/([^/]++)/8c19f5(*:7914)' + .'|b22b/([^/]++)/([^/]++)/([^/]++)/8cb22b(*:7961)' + .')' + .'|39ab4/([^/]++)/([^/]++)/([^/]++)/839ab4(*:8010)' + .'|9f0fd/([^/]++)/([^/]++)/([^/]++)/89f0fd(*:8058)' + .'|bf121/([^/]++)/([^/]++)/([^/]++)/8bf121(*:8106)' + .'|77a9b/([^/]++)/([^/]++)/([^/]++)/877a9b(*:8154)' + .')' + .'|/4(?' + .'|5(?' + .'|c48c/([^/]++)/([^/]++)/([^/]++)/45c48c(*:8211)' + .'|fbc6/([^/]++)/([^/]++)/([^/]++)/45fbc6(*:8258)' + .')' + .'|e732c/([^/]++)/([^/]++)/([^/]++)/4e732c(*:8307)' + .'|4f683/([^/]++)/([^/]++)/([^/]++)/44f683(*:8355)' + .'|3(?' + .'|ec51/([^/]++)/([^/]++)/([^/]++)/43ec51(*:8406)' + .'|2aca/([^/]++)/([^/]++)/([^/]++)/432aca(*:8453)' + .')' + .'|c5(?' + .'|6ff/([^/]++)/([^/]++)/([^/]++)/4c56ff(*:8505)' + .'|bde/([^/]++)/([^/]++)/([^/]++)/4c5bde(*:8551)' + .')' + .'|2(?' + .'|a0e1/([^/]++)/([^/]++)/([^/]++)/42a0e1(*:8603)' + .'|e7aa/([^/]++)/([^/]++)/([^/]++)/42e7aa(*:8650)' + .'|998c/([^/]++)/([^/]++)/([^/]++)/42998c(*:8697)' + .'|8fca/([^/]++)/([^/]++)/([^/]++)/428fca(*:8744)' + .')' + .'|7(?' + .'|d1e9/([^/]++)/([^/]++)/([^/]++)/47d1e9(*:8796)' + .'|34ba/([^/]++)/([^/]++)/([^/]++)/4734ba(*:8843)' + .')' + .'|6ba9f/([^/]++)/([^/]++)/([^/]++)/46ba9f(*:8892)' + .'|8aedb/([^/]++)/([^/]++)/([^/]++)/48aedb(*:8940)' + .'|9(?' + .'|182f/([^/]++)/([^/]++)/([^/]++)/49182f(*:8991)' + .'|6e05/([^/]++)/([^/]++)/([^/]++)/496e05(*:9038)' + .'|ae49/([^/]++)/([^/]++)/([^/]++)/49ae49(*:9085)' + .')' + .'|0008b/([^/]++)/([^/]++)/([^/]++)/40008b(*:9134)' + .'|1(?' + .'|f1f1/([^/]++)/([^/]++)/([^/]++)/41f1f1(*:9185)' + .'|ae36/([^/]++)/([^/]++)/([^/]++)/41ae36(*:9232)' + .')' + .'|f(?' + .'|6ffe/([^/]++)/([^/]++)/([^/]++)/4f6ffe(*:9284)' + .'|4adc/([^/]++)/([^/]++)/([^/]++)/4f4adc(*:9331)' + .')' + .')' + .'|/d(?' + .'|3(?' + .'|d944/([^/]++)/([^/]++)/([^/]++)/d3d944(*:9389)' + .'|9577/([^/]++)/([^/]++)/([^/]++)/d39577(*:9436)' + .'|4ab1/([^/]++)/([^/]++)/([^/]++)/d34ab1(*:9483)' + .')' + .'|6(?' + .'|7d8a/([^/]++)/([^/]++)/([^/]++)/d67d8a(*:9535)' + .'|4592/([^/]++)/([^/]++)/([^/]++)/d64592(*:9582)' + .'|baf6/([^/]++)/([^/]++)/([^/]++)/d6baf6(*:9629)' + .'|1e4b/([^/]++)/([^/]++)/([^/]++)/d61e4b(*:9676)' + .')' + .'|9(?' + .'|d4f4/([^/]++)/([^/]++)/([^/]++)/d9d4f4(*:9728)' + .'|6409/([^/]++)/([^/]++)/([^/]++)/d96409(*:9775)' + .'|47bf/([^/]++)/([^/]++)/([^/]++)/d947bf(*:9822)' + .'|fc5b/([^/]++)/([^/]++)/([^/]++)/d9fc5b(*:9869)' + .')' + .'|8(?' + .'|2c8d/([^/]++)/([^/]++)/([^/]++)/d82c8d(*:9921)' + .'|1f9c/([^/]++)/([^/]++)/([^/]++)/d81f9c(*:9968)' + .')' + .'|2(?' + .'|ddea/([^/]++)/([^/]++)/([^/]++)/d2ddea(*:10020)' + .'|96c1/([^/]++)/([^/]++)/([^/]++)/d296c1(*:10068)' + .')' + .'|0(?' + .'|9bf4/([^/]++)/([^/]++)/([^/]++)/d09bf4(*:10121)' + .'|7e70/([^/]++)/([^/]++)/([^/]++)/d07e70(*:10169)' + .')' + .'|1(?' + .'|f(?' + .'|e17/([^/]++)/([^/]++)/([^/]++)/d1fe17(*:10225)' + .'|491/([^/]++)/([^/]++)/([^/]++)/d1f491(*:10272)' + .'|255/([^/]++)/([^/]++)/([^/]++)/d1f255(*:10319)' + .')' + .'|c38a/([^/]++)/([^/]++)/([^/]++)/d1c38a(*:10368)' + .'|8f65/([^/]++)/([^/]++)/([^/]++)/d18f65(*:10416)' + .')' + .'|a4fb5/([^/]++)/([^/]++)/([^/]++)/da4fb5(*:10466)' + .'|b8e1a/([^/]++)/([^/]++)/([^/]++)/db8e1a(*:10515)' + .'|709f3/([^/]++)/([^/]++)/([^/]++)/d709f3(*:10564)' + .'|c(?' + .'|912a/([^/]++)/([^/]++)/([^/]++)/dc912a(*:10616)' + .'|6a64/([^/]++)/([^/]++)/([^/]++)/dc6a64(*:10664)' + .')' + .'|db306/([^/]++)/([^/]++)/([^/]++)/ddb306(*:10714)' + .')' + .'|/6(?' + .'|5(?' + .'|12bd/([^/]++)/([^/]++)/([^/]++)/6512bd(*:10772)' + .'|b9ee/([^/]++)/([^/]++)/([^/]++)/65b9ee(*:10820)' + .'|ded5/([^/]++)/([^/]++)/([^/]++)/65ded5(*:10868)' + .')' + .'|f(?' + .'|4922/([^/]++)/([^/]++)/([^/]++)/6f4922(*:10921)' + .'|3ef7/([^/]++)/([^/]++)/([^/]++)/6f3ef7(*:10969)' + .'|aa80/([^/]++)/([^/]++)/([^/]++)/6faa80(*:11017)' + .')' + .'|e(?' + .'|a(?' + .'|9ab/([^/]++)/([^/]++)/([^/]++)/6ea9ab(*:11073)' + .'|2ef/([^/]++)/([^/]++)/([^/]++)/6ea2ef(*:11120)' + .')' + .'|cbdd/([^/]++)/([^/]++)/([^/]++)/6ecbdd(*:11169)' + .')' + .'|3(?' + .'|64d3/([^/]++)/([^/]++)/([^/]++)/6364d3(*:11222)' + .'|dc7e/([^/]++)/([^/]++)/([^/]++)/63dc7e(*:11270)' + .'|923f/([^/]++)/([^/]++)/([^/]++)/63923f(*:11318)' + .')' + .'|c(?' + .'|8349/([^/]++)/([^/]++)/([^/]++)/6c8349(*:11371)' + .'|4b76/([^/]++)/([^/]++)/([^/]++)/6c4b76(*:11419)' + .'|dd60/([^/]++)/([^/]++)/([^/]++)/6cdd60(*:11467)' + .'|9882/([^/]++)/([^/]++)/([^/]++)/6c9882(*:11515)' + .'|524f/([^/]++)/([^/]++)/([^/]++)/6c524f(*:11563)' + .')' + .'|7(?' + .'|c6a1/([^/]++)/([^/]++)/([^/]++)/67c6a1(*:11616)' + .'|f7fb/([^/]++)/([^/]++)/([^/]++)/67f7fb(*:11664)' + .')' + .'|42e92/([^/]++)/([^/]++)/([^/]++)/642e92(*:11714)' + .'|6(?' + .'|f041/([^/]++)/([^/]++)/([^/]++)/66f041(*:11766)' + .'|808e/([^/]++)/([^/]++)/([^/]++)/66808e(*:11814)' + .'|3682/([^/]++)/([^/]++)/([^/]++)/663682(*:11862)' + .')' + .'|8(?' + .'|d30a/([^/]++)/([^/]++)/([^/]++)/68d30a(*:11915)' + .'|8396/([^/]++)/([^/]++)/([^/]++)/688396(*:11963)' + .'|5545/([^/]++)/([^/]++)/([^/]++)/685545(*:12011)' + .'|ce19/([^/]++)/([^/]++)/([^/]++)/68ce19(*:12059)' + .')' + .'|9(?' + .'|74ce/([^/]++)/([^/]++)/([^/]++)/6974ce(*:12112)' + .'|8d51/([^/]++)/([^/]++)/([^/]++)/698d51(*:12160)' + .'|adc1/([^/]++)/([^/]++)/([^/]++)/69adc1(*:12208)' + .'|cb3e/([^/]++)/([^/]++)/([^/]++)/69cb3e(*:12256)' + .')' + .'|da(?' + .'|900/([^/]++)/([^/]++)/([^/]++)/6da900(*:12309)' + .'|37d/([^/]++)/([^/]++)/([^/]++)/6da37d(*:12356)' + .')' + .'|21bf6/([^/]++)/([^/]++)/([^/]++)/621bf6(*:12406)' + .'|a9aed/([^/]++)/([^/]++)/([^/]++)/6a9aed(*:12455)' + .')' + .'|/9(?' + .'|b(?' + .'|f31c/([^/]++)/([^/]++)/([^/]++)/9bf31c(*:12513)' + .'|8619/([^/]++)/([^/]++)/([^/]++)/9b8619(*:12561)' + .'|04d1/([^/]++)/([^/]++)/([^/]++)/9b04d1(*:12609)' + .'|e40c/([^/]++)/([^/]++)/([^/]++)/9be40c(*:12657)' + .'|70e8/([^/]++)/([^/]++)/([^/]++)/9b70e8(*:12705)' + .')' + .'|8(?' + .'|f137/([^/]++)/([^/]++)/([^/]++)/98f137(*:12758)' + .'|dce8/([^/]++)/([^/]++)/([^/]++)/98dce8(*:12806)' + .'|72ed/([^/]++)/([^/]++)/([^/]++)/9872ed(*:12854)' + .'|b297/([^/]++)/([^/]++)/([^/]++)/98b297(*:12902)' + .')' + .'|a(?' + .'|1158/([^/]++)/([^/]++)/([^/]++)/9a1158(*:12955)' + .'|9687/([^/]++)/([^/]++)/([^/]++)/9a9687(*:13003)' + .')' + .'|f(?' + .'|6140/([^/]++)/([^/]++)/([^/]++)/9f6140(*:13056)' + .'|c3d7/([^/]++)/([^/]++)/([^/]++)/9fc3d7(*:13104)' + .'|d818/([^/]++)/([^/]++)/([^/]++)/9fd818(*:13152)' + .')' + .'|7(?' + .'|78d5/([^/]++)/([^/]++)/([^/]++)/9778d5(*:13205)' + .'|6652/([^/]++)/([^/]++)/([^/]++)/976652(*:13253)' + .'|9d47/([^/]++)/([^/]++)/([^/]++)/979d47(*:13301)' + .')' + .'|3db85/([^/]++)/([^/]++)/([^/]++)/93db85(*:13351)' + .'|2c(?' + .'|c22/([^/]++)/([^/]++)/([^/]++)/92cc22(*:13403)' + .'|8c9/([^/]++)/([^/]++)/([^/]++)/92c8c9(*:13450)' + .')' + .'|03ce9/([^/]++)/([^/]++)/([^/]++)/903ce9(*:13500)' + .'|6da2f/([^/]++)/([^/]++)/([^/]++)/96da2f(*:13549)' + .'|d(?' + .'|cb88/([^/]++)/([^/]++)/([^/]++)/9dcb88(*:13601)' + .'|fcd5/([^/]++)/([^/]++)/([^/]++)/9dfcd5(*:13649)' + .'|e6d1/([^/]++)/([^/]++)/([^/]++)/9de6d1(*:13697)' + .')' + .'|c(?' + .'|fdf1/([^/]++)/([^/]++)/([^/]++)/9cfdf1(*:13750)' + .'|838d/([^/]++)/([^/]++)/([^/]++)/9c838d(*:13798)' + .')' + .'|18(?' + .'|890/([^/]++)/([^/]++)/([^/]++)/918890(*:13851)' + .'|317/([^/]++)/([^/]++)/([^/]++)/918317(*:13898)' + .')' + .'|4(?' + .'|f6d7/([^/]++)/([^/]++)/([^/]++)/94f6d7(*:13951)' + .'|1e1a/([^/]++)/([^/]++)/([^/]++)/941e1a(*:13999)' + .'|31c8/([^/]++)/([^/]++)/([^/]++)/9431c8(*:14047)' + .'|61cc/([^/]++)/([^/]++)/([^/]++)/9461cc(*:14095)' + .')' + .'|50a41/([^/]++)/([^/]++)/([^/]++)/950a41(*:14145)' + .')' + .'|/7(?' + .'|0(?' + .'|efdf/([^/]++)/([^/]++)/([^/]++)/70efdf(*:14203)' + .'|5f21/([^/]++)/([^/]++)/([^/]++)/705f21(*:14251)' + .'|c639/([^/]++)/([^/]++)/([^/]++)/70c639(*:14299)' + .')' + .'|2b32a/([^/]++)/([^/]++)/([^/]++)/72b32a(*:14349)' + .'|f(?' + .'|39f8/([^/]++)/([^/]++)/([^/]++)/7f39f8(*:14401)' + .'|6ffa/([^/]++)/([^/]++)/([^/]++)/7f6ffa(*:14449)' + .'|1(?' + .'|de2/([^/]++)/([^/]++)/([^/]++)/7f1de2(*:14500)' + .'|00b/([^/]++)/([^/]++)/([^/]++)/7f100b(*:14547)' + .')' + .'|e1f8/([^/]++)/([^/]++)/([^/]++)/7fe1f8(*:14596)' + .')' + .'|3(?' + .'|5b90/([^/]++)/([^/]++)/([^/]++)/735b90(*:14649)' + .'|278a/([^/]++)/([^/]++)/([^/]++)/73278a(*:14697)' + .'|80ad/([^/]++)/([^/]++)/([^/]++)/7380ad(*:14745)' + .')' + .'|cbbc4/([^/]++)/([^/]++)/([^/]++)/7cbbc4(*:14795)' + .'|6(?' + .'|4796/([^/]++)/([^/]++)/([^/]++)/764796(*:14847)' + .'|dc61/([^/]++)/([^/]++)/([^/]++)/76dc61(*:14895)' + .')' + .'|e(?' + .'|f605/([^/]++)/([^/]++)/([^/]++)/7ef605(*:14948)' + .'|7757/([^/]++)/([^/]++)/([^/]++)/7e7757(*:14996)' + .'|a(?' + .'|be3/([^/]++)/([^/]++)/([^/]++)/7eabe3(*:15047)' + .'|cb5/([^/]++)/([^/]++)/([^/]++)/7eacb5(*:15094)' + .')' + .')' + .'|5(?' + .'|7b50/([^/]++)/([^/]++)/([^/]++)/757b50(*:15148)' + .'|8874/([^/]++)/([^/]++)/([^/]++)/758874(*:15196)' + .'|fc09/([^/]++)/([^/]++)/([^/]++)/75fc09(*:15244)' + .')' + .'|4(?' + .'|db12/([^/]++)/([^/]++)/([^/]++)/74db12(*:15297)' + .'|071a/([^/]++)/([^/]++)/([^/]++)/74071a(*:15345)' + .')' + .'|a614f/([^/]++)/([^/]++)/([^/]++)/7a614f(*:15395)' + .'|d04bb/([^/]++)/([^/]++)/([^/]++)/7d04bb(*:15444)' + .')' + .'|/3(?' + .'|c(?' + .'|59dc/([^/]++)/([^/]++)/([^/]++)/3c59dc(*:15502)' + .'|ec07/([^/]++)/([^/]++)/([^/]++)/3cec07(*:15550)' + .'|7781/([^/]++)/([^/]++)/([^/]++)/3c7781(*:15598)' + .'|f166/([^/]++)/([^/]++)/([^/]++)/3cf166(*:15646)' + .')' + .'|7(?' + .'|693c/([^/]++)/([^/]++)/([^/]++)/37693c(*:15699)' + .'|a749/([^/]++)/([^/]++)/([^/]++)/37a749(*:15747)' + .'|bc2f/([^/]++)/([^/]++)/([^/]++)/37bc2f(*:15795)' + .'|1bce/([^/]++)/([^/]++)/([^/]++)/371bce(*:15843)' + .')' + .'|3(?' + .'|e75f/([^/]++)/([^/]++)/([^/]++)/33e75f(*:15896)' + .'|5f53/([^/]++)/([^/]++)/([^/]++)/335f53(*:15944)' + .')' + .'|4(?' + .'|1(?' + .'|73c/([^/]++)/([^/]++)/([^/]++)/34173c(*:16000)' + .'|6a7/([^/]++)/([^/]++)/([^/]++)/3416a7(*:16047)' + .')' + .'|ed06/([^/]++)/([^/]++)/([^/]++)/34ed06(*:16096)' + .')' + .'|2(?' + .'|95c7/([^/]++)/([^/]++)/([^/]++)/3295c7(*:16149)' + .'|bb90/([^/]++)/([^/]++)/([^/]++)/32bb90(*:16197)' + .'|0722/([^/]++)/([^/]++)/([^/]++)/320722(*:16245)' + .')' + .'|5(?' + .'|f4a8/([^/]++)/([^/]++)/([^/]++)/35f4a8(*:16298)' + .'|7a6f/([^/]++)/([^/]++)/([^/]++)/357a6f(*:16346)' + .'|2fe2/([^/]++)/([^/]++)/([^/]++)/352fe2(*:16394)' + .'|0510/([^/]++)/([^/]++)/([^/]++)/350510(*:16442)' + .')' + .'|ef815/([^/]++)/([^/]++)/([^/]++)/3ef815(*:16492)' + .'|8(?' + .'|b3ef/([^/]++)/([^/]++)/([^/]++)/38b3ef(*:16544)' + .'|af86/([^/]++)/([^/]++)/([^/]++)/38af86(*:16592)' + .'|db3a/([^/]++)/([^/]++)/([^/]++)/38db3a(*:16640)' + .')' + .'|d(?' + .'|ef18/([^/]++)/([^/]++)/([^/]++)/3def18(*:16693)' + .'|d48a/([^/]++)/([^/]++)/([^/]++)/3dd48a(*:16741)' + .')' + .'|9(?' + .'|88c7/([^/]++)/([^/]++)/([^/]++)/3988c7(*:16794)' + .'|0597/([^/]++)/([^/]++)/([^/]++)/390597(*:16842)' + .'|461a/([^/]++)/([^/]++)/([^/]++)/39461a(*:16890)' + .')' + .'|6(?' + .'|3663/([^/]++)/([^/]++)/([^/]++)/363663(*:16943)' + .'|44a6/([^/]++)/([^/]++)/([^/]++)/3644a6(*:16991)' + .'|660e/([^/]++)/([^/]++)/([^/]++)/36660e(*:17039)' + .')' + .'|1(?' + .'|fefc/([^/]++)/([^/]++)/([^/]++)/31fefc(*:17092)' + .'|0dcb/([^/]++)/([^/]++)/([^/]++)/310dcb(*:17140)' + .')' + .'|b8a61/([^/]++)/([^/]++)/([^/]++)/3b8a61(*:17190)' + .'|fe94a/([^/]++)/([^/]++)/([^/]++)/3fe94a(*:17239)' + .'|ad7c2/([^/]++)/([^/]++)/([^/]++)/3ad7c2(*:17288)' + .')' + .'|/b(?' + .'|6(?' + .'|d767/([^/]++)/([^/]++)/([^/]++)/b6d767(*:17346)' + .'|f047/([^/]++)/([^/]++)/([^/]++)/b6f047(*:17394)' + .')' + .'|53(?' + .'|b3a/([^/]++)/([^/]++)/([^/]++)/b53b3a(*:17447)' + .'|4ba/([^/]++)/([^/]++)/([^/]++)/b534ba(*:17494)' + .')' + .'|3(?' + .'|e3e3/([^/]++)/([^/]++)/([^/]++)/b3e3e3(*:17547)' + .'|967a/([^/]++)/([^/]++)/([^/]++)/b3967a(*:17595)' + .')' + .'|7(?' + .'|3ce3/([^/]++)/([^/]++)/([^/]++)/b73ce3(*:17648)' + .'|b16e/([^/]++)/([^/]++)/([^/]++)/b7b16e(*:17696)' + .')' + .'|d(?' + .'|4c9a/([^/]++)/([^/]++)/([^/]++)/bd4c9a(*:17749)' + .'|686f/([^/]++)/([^/]++)/([^/]++)/bd686f(*:17797)' + .')' + .'|f8229/([^/]++)/([^/]++)/([^/]++)/bf8229(*:17847)' + .'|1(?' + .'|d10e/([^/]++)/([^/]++)/([^/]++)/b1d10e(*:17899)' + .'|a59b/([^/]++)/([^/]++)/([^/]++)/b1a59b(*:17947)' + .')' + .'|c(?' + .'|be33/([^/]++)/([^/]++)/([^/]++)/bcbe33(*:18000)' + .'|6dc4/([^/]++)/([^/]++)/([^/]++)/bc6dc4(*:18048)' + .'|a82e/([^/]++)/([^/]++)/([^/]++)/bca82e(*:18096)' + .')' + .'|e(?' + .'|83ab/([^/]++)/([^/]++)/([^/]++)/be83ab(*:18149)' + .'|ed13/([^/]++)/([^/]++)/([^/]++)/beed13(*:18197)' + .')' + .'|2eb73/([^/]++)/([^/]++)/([^/]++)/b2eb73(*:18247)' + .'|83aac/([^/]++)/([^/]++)/([^/]++)/b83aac(*:18296)' + .'|ac916/([^/]++)/([^/]++)/([^/]++)/bac916(*:18345)' + .'|b(?' + .'|f94b/([^/]++)/([^/]++)/([^/]++)/bbf94b(*:18397)' + .'|cbff/([^/]++)/([^/]++)/([^/]++)/bbcbff(*:18445)' + .')' + .'|9228e/([^/]++)/([^/]++)/([^/]++)/b9228e(*:18495)' + .')' + .'|/0(?' + .'|2(?' + .'|e74f/([^/]++)/([^/]++)/([^/]++)/02e74f(*:18553)' + .'|522a/([^/]++)/([^/]++)/([^/]++)/02522a(*:18601)' + .'|66e3/([^/]++)/([^/]++)/([^/]++)/0266e3(*:18649)' + .')' + .'|9(?' + .'|3f65/([^/]++)/([^/]++)/([^/]++)/093f65(*:18702)' + .'|1d58/([^/]++)/([^/]++)/([^/]++)/091d58(*:18750)' + .')' + .'|7(?' + .'|2b03/([^/]++)/([^/]++)/([^/]++)/072b03(*:18803)' + .'|e1cd/([^/]++)/([^/]++)/([^/]++)/07e1cd(*:18851)' + .'|7(?' + .'|7d5/([^/]++)/([^/]++)/([^/]++)/0777d5(*:18902)' + .'|e29/([^/]++)/([^/]++)/([^/]++)/077e29(*:18949)' + .')' + .'|cdfd/([^/]++)/([^/]++)/([^/]++)/07cdfd(*:18998)' + .')' + .'|3(?' + .'|afdb/([^/]++)/([^/]++)/([^/]++)/03afdb(*:19051)' + .'|36dc/([^/]++)/([^/]++)/([^/]++)/0336dc(*:19099)' + .'|c6b0/([^/]++)/([^/]++)/([^/]++)/03c6b0(*:19147)' + .'|53ab/([^/]++)/([^/]++)/([^/]++)/0353ab(*:19195)' + .')' + .'|6(?' + .'|9059/([^/]++)/([^/]++)/([^/]++)/069059(*:19248)' + .'|4096/([^/]++)/([^/]++)/([^/]++)/064096(*:19296)' + .'|0ad9/([^/]++)/([^/]++)/([^/]++)/060ad9(*:19344)' + .'|138b/([^/]++)/([^/]++)/([^/]++)/06138b(*:19392)' + .'|eb61/([^/]++)/([^/]++)/([^/]++)/06eb61(*:19440)' + .')' + .'|1(?' + .'|3(?' + .'|d40/([^/]++)/([^/]++)/([^/]++)/013d40(*:19496)' + .'|86b/([^/]++)/([^/]++)/([^/]++)/01386b(*:19543)' + .')' + .'|161a/([^/]++)/([^/]++)/([^/]++)/01161a(*:19592)' + .'|9d38/([^/]++)/([^/]++)/([^/]++)/019d38(*:19640)' + .')' + .'|f(?' + .'|28b5/([^/]++)/([^/]++)/([^/]++)/0f28b5(*:19693)' + .'|49c8/([^/]++)/([^/]++)/([^/]++)/0f49c8(*:19741)' + .')' + .'|a(?' + .'|09c8/([^/]++)/([^/]++)/([^/]++)/0a09c8(*:19794)' + .'|a188/([^/]++)/([^/]++)/([^/]++)/0aa188(*:19842)' + .')' + .'|0(?' + .'|6f52/([^/]++)/([^/]++)/([^/]++)/006f52(*:19895)' + .'|4114/([^/]++)/([^/]++)/([^/]++)/004114(*:19943)' + .'|ec53/([^/]++)/([^/]++)/([^/]++)/00ec53(*:19991)' + .')' + .'|4(?' + .'|5117/([^/]++)/([^/]++)/([^/]++)/045117(*:20044)' + .'|0259/([^/]++)/([^/]++)/([^/]++)/040259(*:20092)' + .')' + .'|84b6f/([^/]++)/([^/]++)/([^/]++)/084b6f(*:20142)' + .'|e(?' + .'|6597/([^/]++)/([^/]++)/([^/]++)/0e6597(*:20194)' + .'|0193/([^/]++)/([^/]++)/([^/]++)/0e0193(*:20242)' + .')' + .'|bb4ae/([^/]++)/([^/]++)/([^/]++)/0bb4ae(*:20292)' + .'|5(?' + .'|049e/([^/]++)/([^/]++)/([^/]++)/05049e(*:20344)' + .'|84ce/([^/]++)/([^/]++)/([^/]++)/0584ce(*:20392)' + .'|f971/([^/]++)/([^/]++)/([^/]++)/05f971(*:20440)' + .')' + .'|c74b7/([^/]++)/([^/]++)/([^/]++)/0c74b7(*:20490)' + .'|d(?' + .'|0fd7/([^/]++)/([^/]++)/([^/]++)/0d0fd7(*:20542)' + .'|eb1c/([^/]++)/([^/]++)/([^/]++)/0deb1c(*:20590)' + .')' + .')' + .'|/f(?' + .'|7(?' + .'|1(?' + .'|771/([^/]++)/([^/]++)/([^/]++)/f71771(*:20652)' + .'|849/([^/]++)/([^/]++)/([^/]++)/f71849(*:20699)' + .')' + .'|e6c8/([^/]++)/([^/]++)/([^/]++)/f7e6c8(*:20748)' + .'|6640/([^/]++)/([^/]++)/([^/]++)/f76640(*:20796)' + .'|3b76/([^/]++)/([^/]++)/([^/]++)/f73b76(*:20844)' + .'|4909/([^/]++)/([^/]++)/([^/]++)/f74909(*:20892)' + .'|70b6/([^/]++)/([^/]++)/([^/]++)/f770b6(*:20940)' + .')' + .'|4(?' + .'|57c5/([^/]++)/([^/]++)/([^/]++)/f457c5(*:20993)' + .'|b9ec/([^/]++)/([^/]++)/([^/]++)/f4b9ec(*:21041)' + .'|f6dc/([^/]++)/([^/]++)/([^/]++)/f4f6dc(*:21089)' + .')' + .'|c(?' + .'|490c/([^/]++)/([^/]++)/([^/]++)/fc490c(*:21142)' + .'|2213/([^/]++)/([^/]++)/([^/]++)/fc2213(*:21190)' + .'|cb60/([^/]++)/([^/]++)/([^/]++)/fccb60(*:21238)' + .')' + .'|b(?' + .'|d793/([^/]++)/([^/]++)/([^/]++)/fbd793(*:21291)' + .'|7b9f/([^/]++)/([^/]++)/([^/]++)/fb7b9f(*:21339)' + .')' + .'|0(?' + .'|33ab/([^/]++)/([^/]++)/([^/]++)/f033ab(*:21392)' + .'|935e/([^/]++)/([^/]++)/([^/]++)/f0935e(*:21440)' + .')' + .'|e(?' + .'|9fc2/([^/]++)/([^/]++)/([^/]++)/fe9fc2(*:21493)' + .'|131d/([^/]++)/([^/]++)/([^/]++)/fe131d(*:21541)' + .'|73f6/([^/]++)/([^/]++)/([^/]++)/fe73f6(*:21589)' + .')' + .'|8(?' + .'|9913/([^/]++)/([^/]++)/([^/]++)/f89913(*:21642)' + .'|c1f2/([^/]++)/([^/]++)/([^/]++)/f8c1f2(*:21690)' + .'|5454/([^/]++)/([^/]++)/([^/]++)/f85454(*:21738)' + .')' + .'|2(?' + .'|2170/([^/]++)/([^/]++)/([^/]++)/f22170(*:21791)' + .'|fc99/([^/]++)/([^/]++)/([^/]++)/f2fc99(*:21839)' + .')' + .'|a(?' + .'|7cdf/([^/]++)/([^/]++)/([^/]++)/fa7cdf(*:21892)' + .'|a9af/([^/]++)/([^/]++)/([^/]++)/faa9af(*:21940)' + .')' + .'|340f1/([^/]++)/([^/]++)/([^/]++)/f340f1(*:21990)' + .'|9(?' + .'|0f2a/([^/]++)/([^/]++)/([^/]++)/f90f2a(*:22042)' + .'|b902/([^/]++)/([^/]++)/([^/]++)/f9b902(*:22090)' + .')' + .'|fd52f/([^/]++)/([^/]++)/([^/]++)/ffd52f(*:22140)' + .'|61d69/([^/]++)/([^/]++)/([^/]++)/f61d69(*:22189)' + .'|5f859/([^/]++)/([^/]++)/([^/]++)/f5f859(*:22238)' + .'|1b6f2/([^/]++)/([^/]++)/([^/]++)/f1b6f2(*:22287)' + .')' + .'|/2(?' + .'|8(?' + .'|3802/([^/]++)/([^/]++)/([^/]++)/283802(*:22345)' + .'|dd2c/([^/]++)/([^/]++)/([^/]++)/28dd2c(*:22393)' + .'|9dff/([^/]++)/([^/]++)/([^/]++)/289dff(*:22441)' + .'|f0b8/([^/]++)/([^/]++)/([^/]++)/28f0b8(*:22489)' + .')' + .'|a(?' + .'|38a4/([^/]++)/([^/]++)/([^/]++)/2a38a4(*:22542)' + .'|79ea/([^/]++)/([^/]++)/([^/]++)/2a79ea(*:22590)' + .')' + .'|6(?' + .'|657d/([^/]++)/([^/]++)/([^/]++)/26657d(*:22643)' + .'|e359/([^/]++)/([^/]++)/([^/]++)/26e359(*:22691)' + .'|3373/([^/]++)/([^/]++)/([^/]++)/263373(*:22739)' + .')' + .'|7(?' + .'|23d0/([^/]++)/([^/]++)/([^/]++)/2723d0(*:22792)' + .'|4ad4/([^/]++)/([^/]++)/([^/]++)/274ad4(*:22840)' + .')' + .'|b(?' + .'|4492/([^/]++)/([^/]++)/([^/]++)/2b4492(*:22893)' + .'|24d4/([^/]++)/([^/]++)/([^/]++)/2b24d4(*:22941)' + .')' + .'|0(?' + .'|2cb9/([^/]++)/([^/]++)/([^/]++)/202cb9(*:22994)' + .'|f075/([^/]++)/([^/]++)/([^/]++)/20f075(*:23042)' + .'|50e0/([^/]++)/([^/]++)/([^/]++)/2050e0(*:23090)' + .')' + .'|f(?' + .'|2b26/([^/]++)/([^/]++)/([^/]++)/2f2b26(*:23143)' + .'|5570/([^/]++)/([^/]++)/([^/]++)/2f5570(*:23191)' + .')' + .'|4(?' + .'|b16f/([^/]++)/([^/]++)/([^/]++)/24b16f(*:23244)' + .'|8e84/([^/]++)/([^/]++)/([^/]++)/248e84(*:23292)' + .'|21fc/([^/]++)/([^/]++)/([^/]++)/2421fc(*:23340)' + .')' + .'|5(?' + .'|b282/([^/]++)/([^/]++)/([^/]++)/25b282(*:23393)' + .'|0cf8/([^/]++)/([^/]++)/([^/]++)/250cf8(*:23441)' + .'|ddc0/([^/]++)/([^/]++)/([^/]++)/25ddc0(*:23489)' + .')' + .'|18a0a/([^/]++)/([^/]++)/([^/]++)/218a0a(*:23539)' + .')' + .'|/5(?' + .'|4229a/([^/]++)/([^/]++)/([^/]++)/54229a(*:23594)' + .'|f(?' + .'|93f9/([^/]++)/([^/]++)/([^/]++)/5f93f9(*:23646)' + .'|d0b3/([^/]++)/([^/]++)/([^/]++)/5fd0b3(*:23694)' + .')' + .'|ef(?' + .'|0(?' + .'|59/([^/]++)/([^/]++)/([^/]++)/5ef059(*:23750)' + .'|b4/([^/]++)/([^/]++)/([^/]++)/5ef0b4(*:23796)' + .')' + .'|698/([^/]++)/([^/]++)/([^/]++)/5ef698(*:23844)' + .')' + .'|8(?' + .'|78a7/([^/]++)/([^/]++)/([^/]++)/5878a7(*:23897)' + .'|a2fc/([^/]++)/([^/]++)/([^/]++)/58a2fc(*:23945)' + .'|238e/([^/]++)/([^/]++)/([^/]++)/58238e(*:23993)' + .')' + .'|7(?' + .'|aeee/([^/]++)/([^/]++)/([^/]++)/57aeee(*:24046)' + .'|7(?' + .'|ef1/([^/]++)/([^/]++)/([^/]++)/577ef1(*:24097)' + .'|bcc/([^/]++)/([^/]++)/([^/]++)/577bcc(*:24144)' + .')' + .'|37c6/([^/]++)/([^/]++)/([^/]++)/5737c6(*:24193)' + .')' + .'|3(?' + .'|9fd5/([^/]++)/([^/]++)/([^/]++)/539fd5(*:24246)' + .'|c3bc/([^/]++)/([^/]++)/([^/]++)/53c3bc(*:24294)' + .')' + .'|5(?' + .'|5d67/([^/]++)/([^/]++)/([^/]++)/555d67(*:24347)' + .'|0a14/([^/]++)/([^/]++)/([^/]++)/550a14(*:24395)' + .'|9cb9/([^/]++)/([^/]++)/([^/]++)/559cb9(*:24443)' + .'|a7cf/([^/]++)/([^/]++)/([^/]++)/55a7cf(*:24491)' + .')' + .'|02e4a/([^/]++)/([^/]++)/([^/]++)/502e4a(*:24541)' + .'|b8add/([^/]++)/([^/]++)/([^/]++)/5b8add(*:24590)' + .'|2720e/([^/]++)/([^/]++)/([^/]++)/52720e(*:24639)' + .'|a4b25/([^/]++)/([^/]++)/([^/]++)/5a4b25(*:24688)' + .'|1d92b/([^/]++)/([^/]++)/([^/]++)/51d92b(*:24737)' + .'|98b3e/([^/]++)/([^/]++)/([^/]++)/598b3e(*:24786)' + .')' + .')/?$}sD', + 24786 => '{^(?' + .'|/5(?' + .'|b69b9/([^/]++)/([^/]++)/([^/]++)/5b69b9(*:24837)' + .'|9(?' + .'|b90e/([^/]++)/([^/]++)/([^/]++)/59b90e(*:24889)' + .'|c330/([^/]++)/([^/]++)/([^/]++)/59c330(*:24937)' + .')' + .'|3(?' + .'|fde9/([^/]++)/([^/]++)/([^/]++)/53fde9(*:24990)' + .'|e3a7/([^/]++)/([^/]++)/([^/]++)/53e3a7(*:25038)' + .')' + .'|e(?' + .'|a164/([^/]++)/([^/]++)/([^/]++)/5ea164(*:25091)' + .'|3881/([^/]++)/([^/]++)/([^/]++)/5e3881(*:25139)' + .'|9f92/([^/]++)/([^/]++)/([^/]++)/5e9f92(*:25187)' + .'|c91a/([^/]++)/([^/]++)/([^/]++)/5ec91a(*:25235)' + .')' + .'|7(?' + .'|3703/([^/]++)/([^/]++)/([^/]++)/573703(*:25288)' + .'|51ec/([^/]++)/([^/]++)/([^/]++)/5751ec(*:25336)' + .'|05e1/([^/]++)/([^/]++)/([^/]++)/5705e1(*:25384)' + .')' + .'|8(?' + .'|ae74/([^/]++)/([^/]++)/([^/]++)/58ae74(*:25437)' + .'|d4d1/([^/]++)/([^/]++)/([^/]++)/58d4d1(*:25485)' + .'|07a6/([^/]++)/([^/]++)/([^/]++)/5807a6(*:25533)' + .'|e4d4/([^/]++)/([^/]++)/([^/]++)/58e4d4(*:25581)' + .')' + .'|d(?' + .'|44ee/([^/]++)/([^/]++)/([^/]++)/5d44ee(*:25634)' + .'|d9db/([^/]++)/([^/]++)/([^/]++)/5dd9db(*:25682)' + .')' + .'|5(?' + .'|b37c/([^/]++)/([^/]++)/([^/]++)/55b37c(*:25735)' + .'|743c/([^/]++)/([^/]++)/([^/]++)/55743c(*:25783)' + .'|6f39/([^/]++)/([^/]++)/([^/]++)/556f39(*:25831)' + .')' + .'|c(?' + .'|0492/([^/]++)/([^/]++)/([^/]++)/5c0492(*:25884)' + .'|572e/([^/]++)/([^/]++)/([^/]++)/5c572e(*:25932)' + .'|9362/([^/]++)/([^/]++)/([^/]++)/5c9362(*:25980)' + .')' + .'|4(?' + .'|8731/([^/]++)/([^/]++)/([^/]++)/548731(*:26033)' + .'|a367/([^/]++)/([^/]++)/([^/]++)/54a367(*:26081)' + .')' + .'|0(?' + .'|0e75/([^/]++)/([^/]++)/([^/]++)/500e75(*:26134)' + .'|c3d7/([^/]++)/([^/]++)/([^/]++)/50c3d7(*:26182)' + .')' + .'|f(?' + .'|2c22/([^/]++)/([^/]++)/([^/]++)/5f2c22(*:26235)' + .'|0f5e/([^/]++)/([^/]++)/([^/]++)/5f0f5e(*:26283)' + .')' + .'|1ef18/([^/]++)/([^/]++)/([^/]++)/51ef18(*:26333)' + .')' + .'|/b(?' + .'|5(?' + .'|b41f/([^/]++)/([^/]++)/([^/]++)/b5b41f(*:26391)' + .'|dc4e/([^/]++)/([^/]++)/([^/]++)/b5dc4e(*:26439)' + .'|6a18/([^/]++)/([^/]++)/([^/]++)/b56a18(*:26487)' + .'|5ec2/([^/]++)/([^/]++)/([^/]++)/b55ec2(*:26535)' + .')' + .'|337e8/([^/]++)/([^/]++)/([^/]++)/b337e8(*:26585)' + .'|a(?' + .'|2fd3/([^/]++)/([^/]++)/([^/]++)/ba2fd3(*:26637)' + .'|3866/([^/]++)/([^/]++)/([^/]++)/ba3866(*:26685)' + .')' + .'|2(?' + .'|eeb7/([^/]++)/([^/]++)/([^/]++)/b2eeb7(*:26738)' + .'|f627/([^/]++)/([^/]++)/([^/]++)/b2f627(*:26786)' + .')' + .'|7(?' + .'|3dfe/([^/]++)/([^/]++)/([^/]++)/b73dfe(*:26839)' + .'|bb35/([^/]++)/([^/]++)/([^/]++)/b7bb35(*:26887)' + .'|ee6f/([^/]++)/([^/]++)/([^/]++)/b7ee6f(*:26935)' + .'|892f/([^/]++)/([^/]++)/([^/]++)/b7892f(*:26983)' + .'|0683/([^/]++)/([^/]++)/([^/]++)/b70683(*:27031)' + .')' + .'|4(?' + .'|288d/([^/]++)/([^/]++)/([^/]++)/b4288d(*:27084)' + .'|a528/([^/]++)/([^/]++)/([^/]++)/b4a528(*:27132)' + .')' + .'|e(?' + .'|3159/([^/]++)/([^/]++)/([^/]++)/be3159(*:27185)' + .'|b22f/([^/]++)/([^/]++)/([^/]++)/beb22f(*:27233)' + .'|a595/([^/]++)/([^/]++)/([^/]++)/bea595(*:27281)' + .')' + .'|1(?' + .'|eec3/([^/]++)/([^/]++)/([^/]++)/b1eec3(*:27334)' + .'|37fd/([^/]++)/([^/]++)/([^/]++)/b137fd(*:27382)' + .')' + .'|0(?' + .'|56eb/([^/]++)/([^/]++)/([^/]++)/b056eb(*:27435)' + .'|b183/([^/]++)/([^/]++)/([^/]++)/b0b183(*:27483)' + .')' + .'|f6276/([^/]++)/([^/]++)/([^/]++)/bf6276(*:27533)' + .'|6(?' + .'|edc1/([^/]++)/([^/]++)/([^/]++)/b6edc1(*:27585)' + .'|a108/([^/]++)/([^/]++)/([^/]++)/b6a108(*:27633)' + .')' + .'|86e8d/([^/]++)/([^/]++)/([^/]++)/b86e8d(*:27683)' + .')' + .'|/2(?' + .'|8(?' + .'|5e19/([^/]++)/([^/]++)/([^/]++)/285e19(*:27741)' + .'|2(?' + .'|3f4/([^/]++)/([^/]++)/([^/]++)/2823f4(*:27792)' + .'|67a/([^/]++)/([^/]++)/([^/]++)/28267a(*:27839)' + .')' + .'|8cc0/([^/]++)/([^/]++)/([^/]++)/288cc0(*:27888)' + .'|7e03/([^/]++)/([^/]++)/([^/]++)/287e03(*:27936)' + .')' + .'|d(?' + .'|6cc4/([^/]++)/([^/]++)/([^/]++)/2d6cc4(*:27989)' + .'|ea61/([^/]++)/([^/]++)/([^/]++)/2dea61(*:28037)' + .'|ace7/([^/]++)/([^/]++)/([^/]++)/2dace7(*:28085)' + .')' + .'|b(?' + .'|8a61/([^/]++)/([^/]++)/([^/]++)/2b8a61(*:28138)' + .'|b232/([^/]++)/([^/]++)/([^/]++)/2bb232(*:28186)' + .'|a596/([^/]++)/([^/]++)/([^/]++)/2ba596(*:28234)' + .'|cab9/([^/]++)/([^/]++)/([^/]++)/2bcab9(*:28282)' + .')' + .'|9(?' + .'|8f95/([^/]++)/([^/]++)/([^/]++)/298f95(*:28335)' + .'|1597/([^/]++)/([^/]++)/([^/]++)/291597(*:28383)' + .')' + .'|58be1/([^/]++)/([^/]++)/([^/]++)/258be1(*:28433)' + .'|3(?' + .'|3509/([^/]++)/([^/]++)/([^/]++)/233509(*:28485)' + .'|ce18/([^/]++)/([^/]++)/([^/]++)/23ce18(*:28533)' + .')' + .'|6(?' + .'|dd0d/([^/]++)/([^/]++)/([^/]++)/26dd0d(*:28586)' + .'|408f/([^/]++)/([^/]++)/([^/]++)/26408f(*:28634)' + .')' + .'|f(?' + .'|37d1/([^/]++)/([^/]++)/([^/]++)/2f37d1(*:28687)' + .'|885d/([^/]++)/([^/]++)/([^/]++)/2f885d(*:28735)' + .')' + .'|2(?' + .'|91d2/([^/]++)/([^/]++)/([^/]++)/2291d2(*:28788)' + .'|ac3c/([^/]++)/([^/]++)/([^/]++)/22ac3c(*:28836)' + .'|fb0c/([^/]++)/([^/]++)/([^/]++)/22fb0c(*:28884)' + .')' + .'|4(?' + .'|6819/([^/]++)/([^/]++)/([^/]++)/246819(*:28937)' + .'|896e/([^/]++)/([^/]++)/([^/]++)/24896e(*:28985)' + .')' + .'|a(?' + .'|fe45/([^/]++)/([^/]++)/([^/]++)/2afe45(*:29038)' + .'|084e/([^/]++)/([^/]++)/([^/]++)/2a084e(*:29086)' + .'|9d12/([^/]++)/([^/]++)/([^/]++)/2a9d12(*:29134)' + .'|b564/([^/]++)/([^/]++)/([^/]++)/2ab564(*:29182)' + .')' + .'|1(?' + .'|7eed/([^/]++)/([^/]++)/([^/]++)/217eed(*:29235)' + .'|0f76/([^/]++)/([^/]++)/([^/]++)/210f76(*:29283)' + .')' + .'|e65f2/([^/]++)/([^/]++)/([^/]++)/2e65f2(*:29333)' + .'|ca65f/([^/]++)/([^/]++)/([^/]++)/2ca65f(*:29382)' + .'|0aee3/([^/]++)/([^/]++)/([^/]++)/20aee3(*:29431)' + .')' + .'|/e(?' + .'|8(?' + .'|c065/([^/]++)/([^/]++)/([^/]++)/e8c065(*:29489)' + .'|20a4/([^/]++)/([^/]++)/([^/]++)/e820a4(*:29537)' + .')' + .'|2(?' + .'|230b/([^/]++)/([^/]++)/([^/]++)/e2230b(*:29590)' + .'|a2dc/([^/]++)/([^/]++)/([^/]++)/e2a2dc(*:29638)' + .'|05ee/([^/]++)/([^/]++)/([^/]++)/e205ee(*:29686)' + .')' + .'|b(?' + .'|d962/([^/]++)/([^/]++)/([^/]++)/ebd962(*:29739)' + .'|6fdc/([^/]++)/([^/]++)/([^/]++)/eb6fdc(*:29787)' + .')' + .'|d(?' + .'|265b/([^/]++)/([^/]++)/([^/]++)/ed265b(*:29840)' + .'|fbe1/([^/]++)/([^/]++)/([^/]++)/edfbe1(*:29888)' + .'|e7e2/([^/]++)/([^/]++)/([^/]++)/ede7e2(*:29936)' + .')' + .'|6(?' + .'|b4b2/([^/]++)/([^/]++)/([^/]++)/e6b4b2(*:29989)' + .'|cb2a/([^/]++)/([^/]++)/([^/]++)/e6cb2a(*:30037)' + .')' + .'|5(?' + .'|f6ad/([^/]++)/([^/]++)/([^/]++)/e5f6ad(*:30090)' + .'|55eb/([^/]++)/([^/]++)/([^/]++)/e555eb(*:30138)' + .'|841d/([^/]++)/([^/]++)/([^/]++)/e5841d(*:30186)' + .'|7c6b/([^/]++)/([^/]++)/([^/]++)/e57c6b(*:30234)' + .')' + .'|aae33/([^/]++)/([^/]++)/([^/]++)/eaae33(*:30284)' + .'|4(?' + .'|bb4c/([^/]++)/([^/]++)/([^/]++)/e4bb4c(*:30336)' + .'|9b8b/([^/]++)/([^/]++)/([^/]++)/e49b8b(*:30384)' + .')' + .'|7(?' + .'|0611/([^/]++)/([^/]++)/([^/]++)/e70611(*:30437)' + .'|f8a7/([^/]++)/([^/]++)/([^/]++)/e7f8a7(*:30485)' + .'|44f9/([^/]++)/([^/]++)/([^/]++)/e744f9(*:30533)' + .')' + .'|9(?' + .'|95f9/([^/]++)/([^/]++)/([^/]++)/e995f9(*:30586)' + .'|4550/([^/]++)/([^/]++)/([^/]++)/e94550(*:30634)' + .'|7ee2/([^/]++)/([^/]++)/([^/]++)/e97ee2(*:30682)' + .')' + .'|e(?' + .'|fc9e/([^/]++)/([^/]++)/([^/]++)/eefc9e(*:30735)' + .'|b69a/([^/]++)/([^/]++)/([^/]++)/eeb69a(*:30783)' + .')' + .'|0(?' + .'|7413/([^/]++)/([^/]++)/([^/]++)/e07413(*:30836)' + .'|cf1f/([^/]++)/([^/]++)/([^/]++)/e0cf1f(*:30884)' + .'|ec45/([^/]++)/([^/]++)/([^/]++)/e0ec45(*:30932)' + .')' + .'|f4e3b/([^/]++)/([^/]++)/([^/]++)/ef4e3b(*:30982)' + .'|c5aa0/([^/]++)/([^/]++)/([^/]++)/ec5aa0(*:31031)' + .')' + .'|/f(?' + .'|f(?' + .'|4d5f/([^/]++)/([^/]++)/([^/]++)/ff4d5f(*:31089)' + .'|eabd/([^/]++)/([^/]++)/([^/]++)/ffeabd(*:31137)' + .')' + .'|3(?' + .'|f27a/([^/]++)/([^/]++)/([^/]++)/f3f27a(*:31190)' + .'|8762/([^/]++)/([^/]++)/([^/]++)/f38762(*:31238)' + .')' + .'|4(?' + .'|be00/([^/]++)/([^/]++)/([^/]++)/f4be00(*:31291)' + .'|5526/([^/]++)/([^/]++)/([^/]++)/f45526(*:31339)' + .'|7d0a/([^/]++)/([^/]++)/([^/]++)/f47d0a(*:31387)' + .')' + .'|0(?' + .'|e52b/([^/]++)/([^/]++)/([^/]++)/f0e52b(*:31440)' + .'|adc8/([^/]++)/([^/]++)/([^/]++)/f0adc8(*:31488)' + .')' + .'|de926/([^/]++)/([^/]++)/([^/]++)/fde926(*:31538)' + .'|5(?' + .'|deae/([^/]++)/([^/]++)/([^/]++)/f5deae(*:31590)' + .'|7a2f/([^/]++)/([^/]++)/([^/]++)/f57a2f(*:31638)' + .')' + .'|7(?' + .'|6a89/([^/]++)/([^/]++)/([^/]++)/f76a89(*:31691)' + .'|9921/([^/]++)/([^/]++)/([^/]++)/f79921(*:31739)' + .'|e905/([^/]++)/([^/]++)/([^/]++)/f7e905(*:31787)' + .')' + .'|2(?' + .'|9c21/([^/]++)/([^/]++)/([^/]++)/f29c21(*:31840)' + .'|201f/([^/]++)/([^/]++)/([^/]++)/f2201f(*:31888)' + .')' + .'|a(?' + .'|e0b2/([^/]++)/([^/]++)/([^/]++)/fae0b2(*:31941)' + .'|14d4/([^/]++)/([^/]++)/([^/]++)/fa14d4(*:31989)' + .'|3a3c/([^/]++)/([^/]++)/([^/]++)/fa3a3c(*:32037)' + .'|83a1/([^/]++)/([^/]++)/([^/]++)/fa83a1(*:32085)' + .')' + .'|c(?' + .'|cb3c/([^/]++)/([^/]++)/([^/]++)/fccb3c(*:32138)' + .'|8001/([^/]++)/([^/]++)/([^/]++)/fc8001(*:32186)' + .'|3cf4/([^/]++)/([^/]++)/([^/]++)/fc3cf4(*:32234)' + .'|4930/([^/]++)/([^/]++)/([^/]++)/fc4930(*:32282)' + .')' + .'|64eac/([^/]++)/([^/]++)/([^/]++)/f64eac(*:32332)' + .'|b8970/([^/]++)/([^/]++)/([^/]++)/fb8970(*:32381)' + .'|1c159/([^/]++)/([^/]++)/([^/]++)/f1c159(*:32430)' + .'|9(?' + .'|028f/([^/]++)/([^/]++)/([^/]++)/f9028f(*:32482)' + .'|a40a/([^/]++)/([^/]++)/([^/]++)/f9a40a(*:32530)' + .')' + .'|e(?' + .'|8c15/([^/]++)/([^/]++)/([^/]++)/fe8c15(*:32583)' + .'|c8d4/([^/]++)/([^/]++)/([^/]++)/fec8d4(*:32631)' + .'|7ee8/([^/]++)/([^/]++)/([^/]++)/fe7ee8(*:32679)' + .')' + .')' + .'|/3(?' + .'|8(?' + .'|9(?' + .'|bc7/([^/]++)/([^/]++)/([^/]++)/389bc7(*:32741)' + .'|13e/([^/]++)/([^/]++)/([^/]++)/38913e(*:32788)' + .')' + .'|71bd/([^/]++)/([^/]++)/([^/]++)/3871bd(*:32837)' + .')' + .'|d(?' + .'|c487/([^/]++)/([^/]++)/([^/]++)/3dc487(*:32890)' + .'|2d8c/([^/]++)/([^/]++)/([^/]++)/3d2d8c(*:32938)' + .'|8e28/([^/]++)/([^/]++)/([^/]++)/3d8e28(*:32986)' + .'|f1d4/([^/]++)/([^/]++)/([^/]++)/3df1d4(*:33034)' + .')' + .'|7f0e8/([^/]++)/([^/]++)/([^/]++)/37f0e8(*:33084)' + .'|3(?' + .'|e807/([^/]++)/([^/]++)/([^/]++)/33e807(*:33136)' + .'|28bd/([^/]++)/([^/]++)/([^/]++)/3328bd(*:33184)' + .')' + .'|a(?' + .'|0(?' + .'|772/([^/]++)/([^/]++)/([^/]++)/3a0772(*:33240)' + .'|66b/([^/]++)/([^/]++)/([^/]++)/3a066b(*:33287)' + .')' + .'|835d/([^/]++)/([^/]++)/([^/]++)/3a835d(*:33336)' + .')' + .'|0(?' + .'|bb38/([^/]++)/([^/]++)/([^/]++)/30bb38(*:33389)' + .'|3ed4/([^/]++)/([^/]++)/([^/]++)/303ed4(*:33437)' + .'|ef30/([^/]++)/([^/]++)/([^/]++)/30ef30(*:33485)' + .'|1ad0/([^/]++)/([^/]++)/([^/]++)/301ad0(*:33533)' + .')' + .'|4(?' + .'|9389/([^/]++)/([^/]++)/([^/]++)/349389(*:33586)' + .'|35c3/([^/]++)/([^/]++)/([^/]++)/3435c3(*:33634)' + .')' + .'|62(?' + .'|1f1/([^/]++)/([^/]++)/([^/]++)/3621f1(*:33687)' + .'|e80/([^/]++)/([^/]++)/([^/]++)/362e80(*:33734)' + .')' + .'|5(?' + .'|cf86/([^/]++)/([^/]++)/([^/]++)/35cf86(*:33787)' + .'|2407/([^/]++)/([^/]++)/([^/]++)/352407(*:33835)' + .')' + .'|2b30a/([^/]++)/([^/]++)/([^/]++)/32b30a(*:33885)' + .'|1839b/([^/]++)/([^/]++)/([^/]++)/31839b(*:33934)' + .'|b(?' + .'|5dca/([^/]++)/([^/]++)/([^/]++)/3b5dca(*:33986)' + .'|3dba/([^/]++)/([^/]++)/([^/]++)/3b3dba(*:34034)' + .')' + .'|e89eb/([^/]++)/([^/]++)/([^/]++)/3e89eb(*:34084)' + .'|cef96/([^/]++)/([^/]++)/([^/]++)/3cef96(*:34133)' + .')' + .'|/0(?' + .'|8(?' + .'|7408/([^/]++)/([^/]++)/([^/]++)/087408(*:34191)' + .'|b255/([^/]++)/([^/]++)/([^/]++)/08b255(*:34239)' + .'|c543/([^/]++)/([^/]++)/([^/]++)/08c543(*:34287)' + .'|d986/([^/]++)/([^/]++)/([^/]++)/08d986(*:34335)' + .'|419b/([^/]++)/([^/]++)/([^/]++)/08419b(*:34383)' + .')' + .'|7(?' + .'|563a/([^/]++)/([^/]++)/([^/]++)/07563a(*:34436)' + .'|6a0c/([^/]++)/([^/]++)/([^/]++)/076a0c(*:34484)' + .'|a96b/([^/]++)/([^/]++)/([^/]++)/07a96b(*:34532)' + .'|c580/([^/]++)/([^/]++)/([^/]++)/07c580(*:34580)' + .'|8719/([^/]++)/([^/]++)/([^/]++)/078719(*:34628)' + .')' + .'|f(?' + .'|cbc6/([^/]++)/([^/]++)/([^/]++)/0fcbc6(*:34681)' + .'|9661/([^/]++)/([^/]++)/([^/]++)/0f9661(*:34729)' + .'|f(?' + .'|39b/([^/]++)/([^/]++)/([^/]++)/0ff39b(*:34780)' + .'|803/([^/]++)/([^/]++)/([^/]++)/0ff803(*:34827)' + .')' + .'|840b/([^/]++)/([^/]++)/([^/]++)/0f840b(*:34876)' + .')' + .'|1(?' + .'|f78b/([^/]++)/([^/]++)/([^/]++)/01f78b(*:34929)' + .'|3a00/([^/]++)/([^/]++)/([^/]++)/013a00(*:34977)' + .'|8825/([^/]++)/([^/]++)/([^/]++)/018825(*:35025)' + .')' + .'|6(?' + .'|9(?' + .'|d3b/([^/]++)/([^/]++)/([^/]++)/069d3b(*:35081)' + .'|97f/([^/]++)/([^/]++)/([^/]++)/06997f(*:35128)' + .')' + .'|1412/([^/]++)/([^/]++)/([^/]++)/061412(*:35177)' + .')' + .'|4(?' + .'|ecb1/([^/]++)/([^/]++)/([^/]++)/04ecb1(*:35230)' + .'|3c3d/([^/]++)/([^/]++)/([^/]++)/043c3d(*:35278)' + .')' + .'|0ac8e/([^/]++)/([^/]++)/([^/]++)/00ac8e(*:35328)' + .'|5(?' + .'|1e4e/([^/]++)/([^/]++)/([^/]++)/051e4e(*:35380)' + .'|37fb/([^/]++)/([^/]++)/([^/]++)/0537fb(*:35428)' + .')' + .'|d(?' + .'|7de1/([^/]++)/([^/]++)/([^/]++)/0d7de1(*:35481)' + .'|3180/([^/]++)/([^/]++)/([^/]++)/0d3180(*:35529)' + .'|0871/([^/]++)/([^/]++)/([^/]++)/0d0871(*:35577)' + .')' + .'|cb929/([^/]++)/([^/]++)/([^/]++)/0cb929(*:35627)' + .'|2(?' + .'|a32a/([^/]++)/([^/]++)/([^/]++)/02a32a(*:35679)' + .'|4d7f/([^/]++)/([^/]++)/([^/]++)/024d7f(*:35727)' + .')' + .'|efe32/([^/]++)/([^/]++)/([^/]++)/0efe32(*:35777)' + .'|a113e/([^/]++)/([^/]++)/([^/]++)/0a113e(*:35826)' + .'|b8aff/([^/]++)/([^/]++)/([^/]++)/0b8aff(*:35875)' + .')' + .'|/a(?' + .'|7(?' + .'|6088/([^/]++)/([^/]++)/([^/]++)/a76088(*:35933)' + .'|aeed/([^/]++)/([^/]++)/([^/]++)/a7aeed(*:35981)' + .'|33fa/([^/]++)/([^/]++)/([^/]++)/a733fa(*:36029)' + .')' + .'|9a(?' + .'|665/([^/]++)/([^/]++)/([^/]++)/a9a665(*:36082)' + .'|1d5/([^/]++)/([^/]++)/([^/]++)/a9a1d5(*:36129)' + .')' + .'|8(?' + .'|6c45/([^/]++)/([^/]++)/([^/]++)/a86c45(*:36182)' + .'|849b/([^/]++)/([^/]++)/([^/]++)/a8849b(*:36230)' + .'|e(?' + .'|864/([^/]++)/([^/]++)/([^/]++)/a8e864(*:36281)' + .'|cba/([^/]++)/([^/]++)/([^/]++)/a8ecba(*:36328)' + .')' + .')' + .'|c(?' + .'|c3e0/([^/]++)/([^/]++)/([^/]++)/acc3e0(*:36382)' + .'|f4b8/([^/]++)/([^/]++)/([^/]++)/acf4b8(*:36430)' + .')' + .'|b(?' + .'|d815/([^/]++)/([^/]++)/([^/]++)/abd815(*:36483)' + .'|233b/([^/]++)/([^/]++)/([^/]++)/ab233b(*:36531)' + .'|a3b6/([^/]++)/([^/]++)/([^/]++)/aba3b6(*:36579)' + .'|88b1/([^/]++)/([^/]++)/([^/]++)/ab88b1(*:36627)' + .')' + .'|5(?' + .'|3240/([^/]++)/([^/]++)/([^/]++)/a53240(*:36680)' + .'|cdd4/([^/]++)/([^/]++)/([^/]++)/a5cdd4(*:36728)' + .')' + .'|f(?' + .'|d(?' + .'|483/([^/]++)/([^/]++)/([^/]++)/afd483(*:36784)' + .'|a33/([^/]++)/([^/]++)/([^/]++)/afda33(*:36831)' + .')' + .'|f162/([^/]++)/([^/]++)/([^/]++)/aff162(*:36880)' + .')' + .'|e(?' + .'|0eb3/([^/]++)/([^/]++)/([^/]++)/ae0eb3(*:36933)' + .'|b313/([^/]++)/([^/]++)/([^/]++)/aeb313(*:36981)' + .')' + .'|1(?' + .'|d33d/([^/]++)/([^/]++)/([^/]++)/a1d33d(*:37034)' + .'|140a/([^/]++)/([^/]++)/([^/]++)/a1140a(*:37082)' + .')' + .'|ddfa9/([^/]++)/([^/]++)/([^/]++)/addfa9(*:37132)' + .'|6(?' + .'|7f09/([^/]++)/([^/]++)/([^/]++)/a67f09(*:37184)' + .'|4c94/([^/]++)/([^/]++)/([^/]++)/a64c94(*:37232)' + .')' + .'|a169b/([^/]++)/([^/]++)/([^/]++)/aa169b(*:37282)' + .'|4300b/([^/]++)/([^/]++)/([^/]++)/a4300b(*:37331)' + .'|3d68b/([^/]++)/([^/]++)/([^/]++)/a3d68b(*:37380)' + .')' + .'|/1(?' + .'|0(?' + .'|a(?' + .'|7cd/([^/]++)/([^/]++)/([^/]++)/10a7cd(*:37441)' + .'|5ab/([^/]++)/([^/]++)/([^/]++)/10a5ab(*:37488)' + .')' + .'|9a0c/([^/]++)/([^/]++)/([^/]++)/109a0c(*:37537)' + .')' + .'|3f320/([^/]++)/([^/]++)/([^/]++)/13f320(*:37587)' + .'|6(?' + .'|c222/([^/]++)/([^/]++)/([^/]++)/16c222(*:37639)' + .'|8908/([^/]++)/([^/]++)/([^/]++)/168908(*:37687)' + .')' + .'|5(?' + .'|de21/([^/]++)/([^/]++)/([^/]++)/15de21(*:37740)' + .'|95af/([^/]++)/([^/]++)/([^/]++)/1595af(*:37788)' + .')' + .'|1(?' + .'|b921/([^/]++)/([^/]++)/([^/]++)/11b921(*:37841)' + .'|4193/([^/]++)/([^/]++)/([^/]++)/114193(*:37889)' + .')' + .'|bb91f/([^/]++)/([^/]++)/([^/]++)/1bb91f(*:37939)' + .'|7(?' + .'|28ef/([^/]++)/([^/]++)/([^/]++)/1728ef(*:37991)' + .'|c276/([^/]++)/([^/]++)/([^/]++)/17c276(*:38039)' + .'|0c94/([^/]++)/([^/]++)/([^/]++)/170c94(*:38087)' + .')' + .'|85(?' + .'|c29/([^/]++)/([^/]++)/([^/]++)/185c29(*:38140)' + .'|e65/([^/]++)/([^/]++)/([^/]++)/185e65(*:38187)' + .')' + .'|9(?' + .'|2fc0/([^/]++)/([^/]++)/([^/]++)/192fc0(*:38240)' + .'|b(?' + .'|c91/([^/]++)/([^/]++)/([^/]++)/19bc91(*:38291)' + .'|650/([^/]++)/([^/]++)/([^/]++)/19b650(*:38338)' + .')' + .'|05ae/([^/]++)/([^/]++)/([^/]++)/1905ae(*:38387)' + .')' + .'|e(?' + .'|cfb4/([^/]++)/([^/]++)/([^/]++)/1ecfb4(*:38440)' + .'|fa39/([^/]++)/([^/]++)/([^/]++)/1efa39(*:38488)' + .'|056d/([^/]++)/([^/]++)/([^/]++)/1e056d(*:38536)' + .')' + .'|aa48f/([^/]++)/([^/]++)/([^/]++)/1aa48f(*:38586)' + .'|f(?' + .'|c214/([^/]++)/([^/]++)/([^/]++)/1fc214(*:38638)' + .'|5089/([^/]++)/([^/]++)/([^/]++)/1f5089(*:38686)' + .'|4477/([^/]++)/([^/]++)/([^/]++)/1f4477(*:38734)' + .')' + .'|c(?' + .'|c363/([^/]++)/([^/]++)/([^/]++)/1cc363(*:38787)' + .'|1d4d/([^/]++)/([^/]++)/([^/]++)/1c1d4d(*:38835)' + .'|e927/([^/]++)/([^/]++)/([^/]++)/1ce927(*:38883)' + .')' + .')' + .'|/6(?' + .'|3(?' + .'|538f/([^/]++)/([^/]++)/([^/]++)/63538f(*:38942)' + .'|2cee/([^/]++)/([^/]++)/([^/]++)/632cee(*:38990)' + .'|95eb/([^/]++)/([^/]++)/([^/]++)/6395eb(*:39038)' + .')' + .'|9(?' + .'|421f/([^/]++)/([^/]++)/([^/]++)/69421f(*:39091)' + .'|2f93/([^/]++)/([^/]++)/([^/]++)/692f93(*:39139)' + .')' + .'|5658f/([^/]++)/([^/]++)/([^/]++)/65658f(*:39189)' + .'|4(?' + .'|7bba/([^/]++)/([^/]++)/([^/]++)/647bba(*:39241)' + .'|223c/([^/]++)/([^/]++)/([^/]++)/64223c(*:39289)' + .')' + .'|e(?' + .'|2713/([^/]++)/([^/]++)/([^/]++)/6e2713(*:39342)' + .'|0721/([^/]++)/([^/]++)/([^/]++)/6e0721(*:39390)' + .'|7b33/([^/]++)/([^/]++)/([^/]++)/6e7b33(*:39438)' + .')' + .'|0(?' + .'|5ff7/([^/]++)/([^/]++)/([^/]++)/605ff7(*:39491)' + .'|8159/([^/]++)/([^/]++)/([^/]++)/608159(*:39539)' + .')' + .'|a(?' + .'|ca97/([^/]++)/([^/]++)/([^/]++)/6aca97(*:39592)' + .'|10bb/([^/]++)/([^/]++)/([^/]++)/6a10bb(*:39640)' + .'|ab12/([^/]++)/([^/]++)/([^/]++)/6aab12(*:39688)' + .')' + .'|7(?' + .'|66aa/([^/]++)/([^/]++)/([^/]++)/6766aa(*:39741)' + .'|e103/([^/]++)/([^/]++)/([^/]++)/67e103(*:39789)' + .'|d(?' + .'|96d/([^/]++)/([^/]++)/([^/]++)/67d96d(*:39840)' + .'|16d/([^/]++)/([^/]++)/([^/]++)/67d16d(*:39887)' + .')' + .'|0e8a/([^/]++)/([^/]++)/([^/]++)/670e8a(*:39936)' + .'|7e09/([^/]++)/([^/]++)/([^/]++)/677e09(*:39984)' + .')' + .'|8(?' + .'|264b/([^/]++)/([^/]++)/([^/]++)/68264b(*:40037)' + .'|053a/([^/]++)/([^/]++)/([^/]++)/68053a(*:40085)' + .')' + .'|c(?' + .'|2979/([^/]++)/([^/]++)/([^/]++)/6c2979(*:40138)' + .'|d67d/([^/]++)/([^/]++)/([^/]++)/6cd67d(*:40186)' + .'|3cf7/([^/]++)/([^/]++)/([^/]++)/6c3cf7(*:40234)' + .'|fe0e/([^/]++)/([^/]++)/([^/]++)/6cfe0e(*:40282)' + .')' + .'|bc24f/([^/]++)/([^/]++)/([^/]++)/6bc24f(*:40332)' + .'|f2268/([^/]++)/([^/]++)/([^/]++)/6f2268(*:40381)' + .'|1b4a6/([^/]++)/([^/]++)/([^/]++)/61b4a6(*:40430)' + .'|21461/([^/]++)/([^/]++)/([^/]++)/621461(*:40479)' + .'|d0f84/([^/]++)/([^/]++)/([^/]++)/6d0f84(*:40528)' + .'|60229/([^/]++)/([^/]++)/([^/]++)/660229(*:40577)' + .')' + .'|/c(?' + .'|f(?' + .'|6735/([^/]++)/([^/]++)/([^/]++)/cf6735(*:40635)' + .'|bce4/([^/]++)/([^/]++)/([^/]++)/cfbce4(*:40683)' + .')' + .'|3(?' + .'|99(?' + .'|86/([^/]++)/([^/]++)/([^/]++)/c39986(*:40739)' + .'|2e/([^/]++)/([^/]++)/([^/]++)/c3992e(*:40785)' + .')' + .'|61bc/([^/]++)/([^/]++)/([^/]++)/c361bc(*:40834)' + .'|2d9b/([^/]++)/([^/]++)/([^/]++)/c32d9b(*:40882)' + .')' + .'|75b6f/([^/]++)/([^/]++)/([^/]++)/c75b6f(*:40932)' + .'|c(?' + .'|b(?' + .'|1d4/([^/]++)/([^/]++)/([^/]++)/ccb1d4(*:40987)' + .'|098/([^/]++)/([^/]++)/([^/]++)/ccb098(*:41034)' + .')' + .'|c0aa/([^/]++)/([^/]++)/([^/]++)/ccc0aa(*:41083)' + .'|1aa4/([^/]++)/([^/]++)/([^/]++)/cc1aa4(*:41131)' + .')' + .'|b(?' + .'|cb58/([^/]++)/([^/]++)/([^/]++)/cbcb58(*:41184)' + .'|b6a3/([^/]++)/([^/]++)/([^/]++)/cbb6a3(*:41232)' + .')' + .'|9892a/([^/]++)/([^/]++)/([^/]++)/c9892a(*:41282)' + .'|6e19e/([^/]++)/([^/]++)/([^/]++)/c6e19e(*:41331)' + .'|dc0d6/([^/]++)/([^/]++)/([^/]++)/cdc0d6(*:41380)' + .'|5ab0b/([^/]++)/([^/]++)/([^/]++)/c5ab0b(*:41429)' + .'|a(?' + .'|9c26/([^/]++)/([^/]++)/([^/]++)/ca9c26(*:41481)' + .'|8155/([^/]++)/([^/]++)/([^/]++)/ca8155(*:41529)' + .'|7591/([^/]++)/([^/]++)/([^/]++)/ca7591(*:41577)' + .')' + .'|0(?' + .'|6d06/([^/]++)/([^/]++)/([^/]++)/c06d06(*:41630)' + .'|f168/([^/]++)/([^/]++)/([^/]++)/c0f168(*:41678)' + .')' + .'|8(?' + .'|ed21/([^/]++)/([^/]++)/([^/]++)/c8ed21(*:41731)' + .'|fbbc/([^/]++)/([^/]++)/([^/]++)/c8fbbc(*:41779)' + .'|c41c/([^/]++)/([^/]++)/([^/]++)/c8c41c(*:41827)' + .')' + .'|15da1/([^/]++)/([^/]++)/([^/]++)/c15da1(*:41877)' + .'|2(?' + .'|626d/([^/]++)/([^/]++)/([^/]++)/c2626d(*:41929)' + .'|aee8/([^/]++)/([^/]++)/([^/]++)/c2aee8(*:41977)' + .'|2abf/([^/]++)/([^/]++)/([^/]++)/c22abf(*:42025)' + .')' + .'|e78d1/([^/]++)/([^/]++)/([^/]++)/ce78d1(*:42075)' + .'|4(?' + .'|015b/([^/]++)/([^/]++)/([^/]++)/c4015b(*:42127)' + .'|b31c/([^/]++)/([^/]++)/([^/]++)/c4b31c(*:42175)' + .')' + .')' + .'|/8(?' + .'|5(?' + .'|422a/([^/]++)/([^/]++)/([^/]++)/85422a(*:42234)' + .'|1ddf/([^/]++)/([^/]++)/([^/]++)/851ddf(*:42282)' + .'|fc37/([^/]++)/([^/]++)/([^/]++)/85fc37(*:42330)' + .')' + .'|1(?' + .'|4481/([^/]++)/([^/]++)/([^/]++)/814481(*:42383)' + .'|e74d/([^/]++)/([^/]++)/([^/]++)/81e74d(*:42431)' + .')' + .'|d(?' + .'|3(?' + .'|420/([^/]++)/([^/]++)/([^/]++)/8d3420(*:42487)' + .'|17b/([^/]++)/([^/]++)/([^/]++)/8d317b(*:42534)' + .')' + .'|f707/([^/]++)/([^/]++)/([^/]++)/8df707(*:42583)' + .'|6dc3/([^/]++)/([^/]++)/([^/]++)/8d6dc3(*:42631)' + .')' + .'|e(?' + .'|efcf/([^/]++)/([^/]++)/([^/]++)/8eefcf(*:42684)' + .'|bda5/([^/]++)/([^/]++)/([^/]++)/8ebda5(*:42732)' + .'|82ab/([^/]++)/([^/]++)/([^/]++)/8e82ab(*:42780)' + .')' + .'|b(?' + .'|16eb/([^/]++)/([^/]++)/([^/]++)/8b16eb(*:42833)' + .'|6dd7/([^/]++)/([^/]++)/([^/]++)/8b6dd7(*:42881)' + .'|5040/([^/]++)/([^/]++)/([^/]++)/8b5040(*:42929)' + .')' + .'|c(?' + .'|7bbb/([^/]++)/([^/]++)/([^/]++)/8c7bbb(*:42982)' + .'|6744/([^/]++)/([^/]++)/([^/]++)/8c6744(*:43030)' + .'|235f/([^/]++)/([^/]++)/([^/]++)/8c235f(*:43078)' + .')' + .'|8(?' + .'|4d24/([^/]++)/([^/]++)/([^/]++)/884d24(*:43131)' + .'|ae63/([^/]++)/([^/]++)/([^/]++)/88ae63(*:43179)' + .')' + .'|7(?' + .'|5715/([^/]++)/([^/]++)/([^/]++)/875715(*:43232)' + .'|2488/([^/]++)/([^/]++)/([^/]++)/872488(*:43280)' + .')' + .'|4(?' + .'|1172/([^/]++)/([^/]++)/([^/]++)/841172(*:43333)' + .'|6c26/([^/]++)/([^/]++)/([^/]++)/846c26(*:43381)' + .'|f7e6/([^/]++)/([^/]++)/([^/]++)/84f7e6(*:43429)' + .'|7cc5/([^/]++)/([^/]++)/([^/]++)/847cc5(*:43477)' + .')' + .'|f(?' + .'|ecb2/([^/]++)/([^/]++)/([^/]++)/8fecb2(*:43530)' + .'|7d80/([^/]++)/([^/]++)/([^/]++)/8f7d80(*:43578)' + .'|468c/([^/]++)/([^/]++)/([^/]++)/8f468c(*:43626)' + .')' + .'|a0e11/([^/]++)/([^/]++)/([^/]++)/8a0e11(*:43676)' + .'|2(?' + .'|f2b3/([^/]++)/([^/]++)/([^/]++)/82f2b3(*:43728)' + .'|489c/([^/]++)/([^/]++)/([^/]++)/82489c(*:43776)' + .')' + .'|6(?' + .'|b122/([^/]++)/([^/]++)/([^/]++)/86b122(*:43829)' + .'|0320/([^/]++)/([^/]++)/([^/]++)/860320(*:43877)' + .')' + .'|9(?' + .'|2c91/([^/]++)/([^/]++)/([^/]++)/892c91(*:43930)' + .'|fcd0/([^/]++)/([^/]++)/([^/]++)/89fcd0(*:43978)' + .')' + .'|065d0/([^/]++)/([^/]++)/([^/]++)/8065d0(*:44028)' + .')' + .'|/d(?' + .'|6(?' + .'|4a34/([^/]++)/([^/]++)/([^/]++)/d64a34(*:44086)' + .'|c651/([^/]++)/([^/]++)/([^/]++)/d6c651(*:44134)' + .')' + .'|f(?' + .'|877f/([^/]++)/([^/]++)/([^/]++)/df877f(*:44187)' + .'|263d/([^/]++)/([^/]++)/([^/]++)/df263d(*:44235)' + .'|7f28/([^/]++)/([^/]++)/([^/]++)/df7f28(*:44283)' + .'|6d23/([^/]++)/([^/]++)/([^/]++)/df6d23(*:44331)' + .')' + .'|b(?' + .'|85e2/([^/]++)/([^/]++)/([^/]++)/db85e2(*:44384)' + .'|e272/([^/]++)/([^/]++)/([^/]++)/dbe272(*:44432)' + .')' + .'|d(?' + .'|45(?' + .'|85/([^/]++)/([^/]++)/([^/]++)/dd4585(*:44488)' + .'|04/([^/]++)/([^/]++)/([^/]++)/dd4504(*:44534)' + .')' + .'|8eb9/([^/]++)/([^/]++)/([^/]++)/dd8eb9(*:44583)' + .')' + .'|a(?' + .'|ca41/([^/]++)/([^/]++)/([^/]++)/daca41(*:44636)' + .'|8ce5/([^/]++)/([^/]++)/([^/]++)/da8ce5(*:44684)' + .'|0d11/([^/]++)/([^/]++)/([^/]++)/da0d11(*:44732)' + .')' + .'|4(?' + .'|90d7/([^/]++)/([^/]++)/([^/]++)/d490d7(*:44785)' + .'|c2e4/([^/]++)/([^/]++)/([^/]++)/d4c2e4(*:44833)' + .')' + .'|8(?' + .'|6ea6/([^/]++)/([^/]++)/([^/]++)/d86ea6(*:44886)' + .'|40cc/([^/]++)/([^/]++)/([^/]++)/d840cc(*:44934)' + .')' + .'|c(?' + .'|82d6/([^/]++)/([^/]++)/([^/]++)/dc82d6(*:44987)' + .'|6a70/([^/]++)/([^/]++)/([^/]++)/dc6a70(*:45035)' + .'|5689/([^/]++)/([^/]++)/([^/]++)/dc5689(*:45083)' + .')' + .'|7(?' + .'|a728/([^/]++)/([^/]++)/([^/]++)/d7a728(*:45136)' + .'|0732/([^/]++)/([^/]++)/([^/]++)/d70732(*:45184)' + .'|9aac/([^/]++)/([^/]++)/([^/]++)/d79aac(*:45232)' + .')' + .'|14220/([^/]++)/([^/]++)/([^/]++)/d14220(*:45282)' + .'|5(?' + .'|cfea/([^/]++)/([^/]++)/([^/]++)/d5cfea(*:45334)' + .'|8072/([^/]++)/([^/]++)/([^/]++)/d58072(*:45382)' + .'|54f7/([^/]++)/([^/]++)/([^/]++)/d554f7(*:45430)' + .'|16b1/([^/]++)/([^/]++)/([^/]++)/d516b1(*:45478)' + .'|6b9f/([^/]++)/([^/]++)/([^/]++)/d56b9f(*:45526)' + .')' + .'|045c5/([^/]++)/([^/]++)/([^/]++)/d045c5(*:45576)' + .'|2(?' + .'|ed45/([^/]++)/([^/]++)/([^/]++)/d2ed45(*:45628)' + .'|40e3/([^/]++)/([^/]++)/([^/]++)/d240e3(*:45676)' + .')' + .'|93ed5/([^/]++)/([^/]++)/([^/]++)/d93ed5(*:45726)' + .')' + .'|/7(?' + .'|b(?' + .'|cdf7/([^/]++)/([^/]++)/([^/]++)/7bcdf7(*:45784)' + .'|13b2/([^/]++)/([^/]++)/([^/]++)/7b13b2(*:45832)' + .')' + .'|dcd34/([^/]++)/([^/]++)/([^/]++)/7dcd34(*:45882)' + .'|f(?' + .'|24d2/([^/]++)/([^/]++)/([^/]++)/7f24d2(*:45934)' + .'|5d04/([^/]++)/([^/]++)/([^/]++)/7f5d04(*:45982)' + .'|1171/([^/]++)/([^/]++)/([^/]++)/7f1171(*:46030)' + .'|a732/([^/]++)/([^/]++)/([^/]++)/7fa732(*:46078)' + .')' + .'|6(?' + .'|6ebc/([^/]++)/([^/]++)/([^/]++)/766ebc(*:46131)' + .'|34ea/([^/]++)/([^/]++)/([^/]++)/7634ea(*:46179)' + .')' + .'|750ca/([^/]++)/([^/]++)/([^/]++)/7750ca(*:46229)' + .'|1(?' + .'|a(?' + .'|3cb/([^/]++)/([^/]++)/([^/]++)/71a3cb(*:46284)' + .'|d16/([^/]++)/([^/]++)/([^/]++)/71ad16(*:46331)' + .')' + .'|43d7/([^/]++)/([^/]++)/([^/]++)/7143d7(*:46380)' + .')' + .'|88d98/([^/]++)/([^/]++)/([^/]++)/788d98(*:46430)' + .'|2(?' + .'|da7f/([^/]++)/([^/]++)/([^/]++)/72da7f(*:46482)' + .'|50eb/([^/]++)/([^/]++)/([^/]++)/7250eb(*:46530)' + .')' + .'|c(?' + .'|590f/([^/]++)/([^/]++)/([^/]++)/7c590f(*:46583)' + .'|e328/([^/]++)/([^/]++)/([^/]++)/7ce328(*:46631)' + .')' + .'|a5392/([^/]++)/([^/]++)/([^/]++)/7a5392(*:46681)' + .'|95c7a/([^/]++)/([^/]++)/([^/]++)/795c7a(*:46730)' + .'|504ad/([^/]++)/([^/]++)/([^/]++)/7504ad(*:46779)' + .'|04afe/([^/]++)/([^/]++)/([^/]++)/704afe(*:46828)' + .'|4bba2/([^/]++)/([^/]++)/([^/]++)/74bba2(*:46877)' + .')' + .'|/9(?' + .'|b(?' + .'|72e3/([^/]++)/([^/]++)/([^/]++)/9b72e3(*:46935)' + .'|698e/([^/]++)/([^/]++)/([^/]++)/9b698e(*:46983)' + .')' + .'|7e852/([^/]++)/([^/]++)/([^/]++)/97e852(*:47033)' + .'|4c7bb/([^/]++)/([^/]++)/([^/]++)/94c7bb(*:47082)' + .'|9(?' + .'|c5e0/([^/]++)/([^/]++)/([^/]++)/99c5e0(*:47134)' + .'|6a7f/([^/]++)/([^/]++)/([^/]++)/996a7f(*:47182)' + .'|bcfc/([^/]++)/([^/]++)/([^/]++)/99bcfc(*:47230)' + .'|0827/([^/]++)/([^/]++)/([^/]++)/990827(*:47278)' + .')' + .'|a(?' + .'|d6aa/([^/]++)/([^/]++)/([^/]++)/9ad6aa(*:47331)' + .'|b0d8/([^/]++)/([^/]++)/([^/]++)/9ab0d8(*:47379)' + .')' + .'|c(?' + .'|f81d/([^/]++)/([^/]++)/([^/]++)/9cf81d(*:47432)' + .'|c138/([^/]++)/([^/]++)/([^/]++)/9cc138(*:47480)' + .'|82c7/([^/]++)/([^/]++)/([^/]++)/9c82c7(*:47528)' + .'|0180/([^/]++)/([^/]++)/([^/]++)/9c0180(*:47576)' + .')' + .'|f(?' + .'|396f/([^/]++)/([^/]++)/([^/]++)/9f396f(*:47629)' + .'|e859/([^/]++)/([^/]++)/([^/]++)/9fe859(*:47677)' + .'|53d8/([^/]++)/([^/]++)/([^/]++)/9f53d8(*:47725)' + .')' + .'|12d2b/([^/]++)/([^/]++)/([^/]++)/912d2b(*:47775)' + .'|59a55/([^/]++)/([^/]++)/([^/]++)/959a55(*:47824)' + .'|6(?' + .'|ea64/([^/]++)/([^/]++)/([^/]++)/96ea64(*:47876)' + .'|b9bf/([^/]++)/([^/]++)/([^/]++)/96b9bf(*:47924)' + .')' + .'|e3cfc/([^/]++)/([^/]++)/([^/]++)/9e3cfc(*:47974)' + .'|2(?' + .'|fb0c/([^/]++)/([^/]++)/([^/]++)/92fb0c(*:48026)' + .'|262b/([^/]++)/([^/]++)/([^/]++)/92262b(*:48074)' + .'|32fe/([^/]++)/([^/]++)/([^/]++)/9232fe(*:48122)' + .'|977a/([^/]++)/([^/]++)/([^/]++)/92977a(*:48170)' + .')' + .'|8d6f5/([^/]++)/([^/]++)/([^/]++)/98d6f5(*:48220)' + .'|0794e/([^/]++)/([^/]++)/([^/]++)/90794e(*:48269)' + .'|34815/([^/]++)/([^/]++)/([^/]++)/934815(*:48318)' + .')' + .'|/4(?' + .'|e(?' + .'|4b5f/([^/]++)/([^/]++)/([^/]++)/4e4b5f(*:48376)' + .'|a06f/([^/]++)/([^/]++)/([^/]++)/4ea06f(*:48424)' + .'|0(?' + .'|928/([^/]++)/([^/]++)/([^/]++)/4e0928(*:48475)' + .'|cb6/([^/]++)/([^/]++)/([^/]++)/4e0cb6(*:48522)' + .')' + .')' + .'|6922a/([^/]++)/([^/]++)/([^/]++)/46922a(*:48573)' + .'|4(?' + .'|c4c1/([^/]++)/([^/]++)/([^/]++)/44c4c1(*:48625)' + .'|3cb0/([^/]++)/([^/]++)/([^/]++)/443cb0(*:48673)' + .')' + .'|8ab2f/([^/]++)/([^/]++)/([^/]++)/48ab2f(*:48723)' + .'|5(?' + .'|645a/([^/]++)/([^/]++)/([^/]++)/45645a(*:48775)' + .'|58db/([^/]++)/([^/]++)/([^/]++)/4558db(*:48823)' + .')' + .'|2e77b/([^/]++)/([^/]++)/([^/]++)/42e77b(*:48873)' + .'|c27ce/([^/]++)/([^/]++)/([^/]++)/4c27ce(*:48922)' + .'|f(?' + .'|fce0/([^/]++)/([^/]++)/([^/]++)/4ffce0(*:48974)' + .'|ac9b/([^/]++)/([^/]++)/([^/]++)/4fac9b(*:49022)' + .')' + .'|a47d2/([^/]++)/([^/]++)/([^/]++)/4a47d2(*:49072)' + .'|70e7a/([^/]++)/([^/]++)/([^/]++)/470e7a(*:49121)' + .'|b(?' + .'|0(?' + .'|4a6/([^/]++)/([^/]++)/([^/]++)/4b04a6(*:49176)' + .'|a59/([^/]++)/([^/]++)/([^/]++)/4b0a59(*:49223)' + .'|250/([^/]++)/([^/]++)/([^/]++)/4b0250(*:49270)' + .')' + .'|6538/([^/]++)/([^/]++)/([^/]++)/4b6538(*:49319)' + .')' + .'|3(?' + .'|f(?' + .'|a7f/([^/]++)/([^/]++)/([^/]++)/43fa7f(*:49375)' + .'|eae/([^/]++)/([^/]++)/([^/]++)/43feae(*:49422)' + .')' + .'|0c36/([^/]++)/([^/]++)/([^/]++)/430c36(*:49471)' + .'|7d7d/([^/]++)/([^/]++)/([^/]++)/437d7d(*:49519)' + .'|1135/([^/]++)/([^/]++)/([^/]++)/431135(*:49567)' + .')' + .'|d(?' + .'|5b99/([^/]++)/([^/]++)/([^/]++)/4d5b99(*:49620)' + .'|aa3d/([^/]++)/([^/]++)/([^/]++)/4daa3d(*:49668)' + .')' + .'|9c9ad/([^/]++)/([^/]++)/([^/]++)/49c9ad(*:49718)' + .')' + .')/?$}sD', + ], + [ // $dynamicRoutes + 54 => [[['_route' => '_0'], ['a', 'b', 'c'], null, null, false, false, null]], + 102 => [[['_route' => '_190'], ['a', 'b', 'c'], null, null, false, false, null]], + 147 => [[['_route' => '_478'], ['a', 'b', 'c'], null, null, false, false, null]], + 194 => [[['_route' => '_259'], ['a', 'b', 'c'], null, null, false, false, null]], + 240 => [[['_route' => '_368'], ['a', 'b', 'c'], null, null, false, false, null]], + 291 => [[['_route' => '_1'], ['a', 'b', 'c'], null, null, false, false, null]], + 337 => [[['_route' => '_116'], ['a', 'b', 'c'], null, null, false, false, null]], + 383 => [[['_route' => '_490'], ['a', 'b', 'c'], null, null, false, false, null]], + 434 => [[['_route' => '_2'], ['a', 'b', 'c'], null, null, false, false, null]], + 480 => [[['_route' => '_124'], ['a', 'b', 'c'], null, null, false, false, null]], + 526 => [[['_route' => '_389'], ['a', 'b', 'c'], null, null, false, false, null]], + 577 => [[['_route' => '_8'], ['a', 'b', 'c'], null, null, false, false, null]], + 623 => [[['_route' => '_104'], ['a', 'b', 'c'], null, null, false, false, null]], + 677 => [[['_route' => '_12'], ['a', 'b', 'c'], null, null, false, false, null]], + 722 => [[['_route' => '_442'], ['a', 'b', 'c'], null, null, false, false, null]], + 769 => [[['_route' => '_253'], ['a', 'b', 'c'], null, null, false, false, null]], + 820 => [[['_route' => '_13'], ['a', 'b', 'c'], null, null, false, false, null]], + 866 => [[['_route' => '_254'], ['a', 'b', 'c'], null, null, false, false, null]], + 912 => [[['_route' => '_347'], ['a', 'b', 'c'], null, null, false, false, null]], + 963 => [[['_route' => '_16'], ['a', 'b', 'c'], null, null, false, false, null]], + 1009 => [[['_route' => '_87'], ['a', 'b', 'c'], null, null, false, false, null]], + 1058 => [[['_route' => '_31'], ['a', 'b', 'c'], null, null, false, false, null]], + 1109 => [[['_route' => '_50'], ['a', 'b', 'c'], null, null, false, false, null]], + 1156 => [[['_route' => '_219'], ['a', 'b', 'c'], null, null, false, false, null]], + 1203 => [[['_route' => '_332'], ['a', 'b', 'c'], null, null, false, false, null]], + 1250 => [[['_route' => '_359'], ['a', 'b', 'c'], null, null, false, false, null]], + 1302 => [[['_route' => '_183'], ['a', 'b', 'c'], null, null, false, false, null]], + 1349 => [[['_route' => '_500'], ['a', 'b', 'c'], null, null, false, false, null]], + 1401 => [[['_route' => '_214'], ['a', 'b', 'c'], null, null, false, false, null]], + 1448 => [[['_route' => '_321'], ['a', 'b', 'c'], null, null, false, false, null]], + 1497 => [[['_route' => '_243'], ['a', 'b', 'c'], null, null, false, false, null]], + 1545 => [[['_route' => '_328'], ['a', 'b', 'c'], null, null, false, false, null]], + 1596 => [[['_route' => '_362'], ['a', 'b', 'c'], null, null, false, false, null]], + 1643 => [[['_route' => '_488'], ['a', 'b', 'c'], null, null, false, false, null]], + 1701 => [[['_route' => '_3'], ['a', 'b', 'c'], null, null, false, false, null]], + 1751 => [[['_route' => '_102'], ['a', 'b', 'c'], null, null, false, false, null]], + 1797 => [[['_route' => '_220'], ['a', 'b', 'c'], null, null, false, false, null]], + 1845 => [[['_route' => '_127'], ['a', 'b', 'c'], null, null, false, false, null]], + 1897 => [[['_route' => '_5'], ['a', 'b', 'c'], null, null, false, false, null]], + 1944 => [[['_route' => '_242'], ['a', 'b', 'c'], null, null, false, false, null]], + 1991 => [[['_route' => '_397'], ['a', 'b', 'c'], null, null, false, false, null]], + 2038 => [[['_route' => '_454'], ['a', 'b', 'c'], null, null, false, false, null]], + 2090 => [[['_route' => '_34'], ['a', 'b', 'c'], null, null, false, false, null]], + 2137 => [[['_route' => '_281'], ['a', 'b', 'c'], null, null, false, false, null]], + 2189 => [[['_route' => '_64'], ['a', 'b', 'c'], null, null, false, false, null]], + 2236 => [[['_route' => '_205'], ['a', 'b', 'c'], null, null, false, false, null]], + 2291 => [[['_route' => '_71'], ['a', 'b', 'c'], null, null, false, false, null]], + 2337 => [[['_route' => '_203'], ['a', 'b', 'c'], null, null, false, false, null]], + 2385 => [[['_route' => '_97'], ['a', 'b', 'c'], null, null, false, false, null]], + 2437 => [[['_route' => '_98'], ['a', 'b', 'c'], null, null, false, false, null]], + 2484 => [[['_route' => '_267'], ['a', 'b', 'c'], null, null, false, false, null]], + 2531 => [[['_route' => '_309'], ['a', 'b', 'c'], null, null, false, false, null]], + 2586 => [[['_route' => '_117'], ['a', 'b', 'c'], null, null, false, false, null]], + 2631 => [[['_route' => '_211'], ['a', 'b', 'c'], null, null, false, false, null]], + 2679 => [[['_route' => '_484'], ['a', 'b', 'c'], null, null, false, false, null]], + 2731 => [[['_route' => '_139'], ['a', 'b', 'c'], null, null, false, false, null]], + 2778 => [[['_route' => '_421'], ['a', 'b', 'c'], null, null, false, false, null]], + 2830 => [[['_route' => '_185'], ['a', 'b', 'c'], null, null, false, false, null]], + 2877 => [[['_route' => '_439'], ['a', 'b', 'c'], null, null, false, false, null]], + 2926 => [[['_route' => '_218'], ['a', 'b', 'c'], null, null, false, false, null]], + 2977 => [[['_route' => '_233'], ['a', 'b', 'c'], null, null, false, false, null]], + 3024 => [[['_route' => '_483'], ['a', 'b', 'c'], null, null, false, false, null]], + 3073 => [[['_route' => '_265'], ['a', 'b', 'c'], null, null, false, false, null]], + 3124 => [[['_route' => '_299'], ['a', 'b', 'c'], null, null, false, false, null]], + 3171 => [[['_route' => '_351'], ['a', 'b', 'c'], null, null, false, false, null]], + 3218 => [[['_route' => '_472'], ['a', 'b', 'c'], null, null, false, false, null]], + 3267 => [[['_route' => '_360'], ['a', 'b', 'c'], null, null, false, false, null]], + 3315 => [[['_route' => '_466'], ['a', 'b', 'c'], null, null, false, false, null]], + 3372 => [[['_route' => '_4'], ['a', 'b', 'c'], null, null, false, false, null]], + 3419 => [[['_route' => '_142'], ['a', 'b', 'c'], null, null, false, false, null]], + 3466 => [[['_route' => '_151'], ['a', 'b', 'c'], null, null, false, false, null]], + 3513 => [[['_route' => '_308'], ['a', 'b', 'c'], null, null, false, false, null]], + 3560 => [[['_route' => '_440'], ['a', 'b', 'c'], null, null, false, false, null]], + 3612 => [[['_route' => '_14'], ['a', 'b', 'c'], null, null, false, false, null]], + 3659 => [[['_route' => '_358'], ['a', 'b', 'c'], null, null, false, false, null]], + 3711 => [[['_route' => '_37'], ['a', 'b', 'c'], null, null, false, false, null]], + 3758 => [[['_route' => '_38'], ['a', 'b', 'c'], null, null, false, false, null]], + 3805 => [[['_route' => '_146'], ['a', 'b', 'c'], null, null, false, false, null]], + 3852 => [[['_route' => '_194'], ['a', 'b', 'c'], null, null, false, false, null]], + 3899 => [[['_route' => '_487'], ['a', 'b', 'c'], null, null, false, false, null]], + 3948 => [[['_route' => '_42'], ['a', 'b', 'c'], null, null, false, false, null]], + 3999 => [[['_route' => '_54'], ['a', 'b', 'c'], null, null, false, false, null]], + 4046 => [[['_route' => '_326'], ['a', 'b', 'c'], null, null, false, false, null]], + 4098 => [[['_route' => '_68'], ['a', 'b', 'c'], null, null, false, false, null]], + 4145 => [[['_route' => '_108'], ['a', 'b', 'c'], null, null, false, false, null]], + 4197 => [[['_route' => '_74'], ['a', 'b', 'c'], null, null, false, false, null]], + 4244 => [[['_route' => '_315'], ['a', 'b', 'c'], null, null, false, false, null]], + 4291 => [[['_route' => '_374'], ['a', 'b', 'c'], null, null, false, false, null]], + 4343 => [[['_route' => '_99'], ['a', 'b', 'c'], null, null, false, false, null]], + 4390 => [[['_route' => '_238'], ['a', 'b', 'c'], null, null, false, false, null]], + 4442 => [[['_route' => '_107'], ['a', 'b', 'c'], null, null, false, false, null]], + 4489 => [[['_route' => '_409'], ['a', 'b', 'c'], null, null, false, false, null]], + 4541 => [[['_route' => '_122'], ['a', 'b', 'c'], null, null, false, false, null]], + 4588 => [[['_route' => '_379'], ['a', 'b', 'c'], null, null, false, false, null]], + 4635 => [[['_route' => '_390'], ['a', 'b', 'c'], null, null, false, false, null]], + 4687 => [[['_route' => '_171'], ['a', 'b', 'c'], null, null, false, false, null]], + 4734 => [[['_route' => '_260'], ['a', 'b', 'c'], null, null, false, false, null]], + 4781 => [[['_route' => '_434'], ['a', 'b', 'c'], null, null, false, false, null]], + 4830 => [[['_route' => '_189'], ['a', 'b', 'c'], null, null, false, false, null]], + 4878 => [[['_route' => '_467'], ['a', 'b', 'c'], null, null, false, false, null]], + 4935 => [[['_route' => '_6'], ['a', 'b', 'c'], null, null, false, false, null]], + 4982 => [[['_route' => '_286'], ['a', 'b', 'c'], null, null, false, false, null]], + 5029 => [[['_route' => '_438'], ['a', 'b', 'c'], null, null, false, false, null]], + 5081 => [[['_route' => '_19'], ['a', 'b', 'c'], null, null, false, false, null]], + 5131 => [[['_route' => '_24'], ['a', 'b', 'c'], null, null, false, false, null]], + 5177 => [[['_route' => '_172'], ['a', 'b', 'c'], null, null, false, false, null]], + 5230 => [[['_route' => '_33'], ['a', 'b', 'c'], null, null, false, false, null]], + 5277 => [[['_route' => '_400'], ['a', 'b', 'c'], null, null, false, false, null]], + 5324 => [[['_route' => '_427'], ['a', 'b', 'c'], null, null, false, false, null]], + 5376 => [[['_route' => '_35'], ['a', 'b', 'c'], null, null, false, false, null]], + 5423 => [[['_route' => '_156'], ['a', 'b', 'c'], null, null, false, false, null]], + 5475 => [[['_route' => '_36'], ['a', 'b', 'c'], null, null, false, false, null]], + 5522 => [[['_route' => '_251'], ['a', 'b', 'c'], null, null, false, false, null]], + 5574 => [[['_route' => '_43'], ['a', 'b', 'c'], null, null, false, false, null]], + 5621 => [[['_route' => '_292'], ['a', 'b', 'c'], null, null, false, false, null]], + 5668 => [[['_route' => '_411'], ['a', 'b', 'c'], null, null, false, false, null]], + 5720 => [[['_route' => '_69'], ['a', 'b', 'c'], null, null, false, false, null]], + 5767 => [[['_route' => '_159'], ['a', 'b', 'c'], null, null, false, false, null]], + 5814 => [[['_route' => '_170'], ['a', 'b', 'c'], null, null, false, false, null]], + 5861 => [[['_route' => '_376'], ['a', 'b', 'c'], null, null, false, false, null]], + 5913 => [[['_route' => '_131'], ['a', 'b', 'c'], null, null, false, false, null]], + 5960 => [[['_route' => '_446'], ['a', 'b', 'c'], null, null, false, false, null]], + 6015 => [[['_route' => '_140'], ['a', 'b', 'c'], null, null, false, false, null]], + 6061 => [[['_route' => '_353'], ['a', 'b', 'c'], null, null, false, false, null]], + 6112 => [[['_route' => '_224'], ['a', 'b', 'c'], null, null, false, false, null]], + 6158 => [[['_route' => '_346'], ['a', 'b', 'c'], null, null, false, false, null]], + 6204 => [[['_route' => '_443'], ['a', 'b', 'c'], null, null, false, false, null]], + 6254 => [[['_route' => '_154'], ['a', 'b', 'c'], null, null, false, false, null]], + 6305 => [[['_route' => '_212'], ['a', 'b', 'c'], null, null, false, false, null]], + 6352 => [[['_route' => '_313'], ['a', 'b', 'c'], null, null, false, false, null]], + 6399 => [[['_route' => '_395'], ['a', 'b', 'c'], null, null, false, false, null]], + 6446 => [[['_route' => '_441'], ['a', 'b', 'c'], null, null, false, false, null]], + 6498 => [[['_route' => '_223'], ['a', 'b', 'c'], null, null, false, false, null]], + 6545 => [[['_route' => '_303'], ['a', 'b', 'c'], null, null, false, false, null]], + 6594 => [[['_route' => '_410'], ['a', 'b', 'c'], null, null, false, false, null]], + 6642 => [[['_route' => '_494'], ['a', 'b', 'c'], null, null, false, false, null]], + 6702 => [[['_route' => '_7'], ['a', 'b', 'c'], null, null, false, false, null]], + 6748 => [[['_route' => '_268'], ['a', 'b', 'c'], null, null, false, false, null]], + 6796 => [[['_route' => '_178'], ['a', 'b', 'c'], null, null, false, false, null]], + 6843 => [[['_route' => '_179'], ['a', 'b', 'c'], null, null, false, false, null]], + 6890 => [[['_route' => '_416'], ['a', 'b', 'c'], null, null, false, false, null]], + 6942 => [[['_route' => '_25'], ['a', 'b', 'c'], null, null, false, false, null]], + 6989 => [[['_route' => '_307'], ['a', 'b', 'c'], null, null, false, false, null]], + 7036 => [[['_route' => '_387'], ['a', 'b', 'c'], null, null, false, false, null]], + 7083 => [[['_route' => '_471'], ['a', 'b', 'c'], null, null, false, false, null]], + 7132 => [[['_route' => '_90'], ['a', 'b', 'c'], null, null, false, false, null]], + 7183 => [[['_route' => '_95'], ['a', 'b', 'c'], null, null, false, false, null]], + 7230 => [[['_route' => '_338'], ['a', 'b', 'c'], null, null, false, false, null]], + 7277 => [[['_route' => '_401'], ['a', 'b', 'c'], null, null, false, false, null]], + 7329 => [[['_route' => '_147'], ['a', 'b', 'c'], null, null, false, false, null]], + 7376 => [[['_route' => '_319'], ['a', 'b', 'c'], null, null, false, false, null]], + 7423 => [[['_route' => '_354'], ['a', 'b', 'c'], null, null, false, false, null]], + 7470 => [[['_route' => '_428'], ['a', 'b', 'c'], null, null, false, false, null]], + 7522 => [[['_route' => '_162'], ['a', 'b', 'c'], null, null, false, false, null]], + 7572 => [[['_route' => '_175'], ['a', 'b', 'c'], null, null, false, false, null]], + 7618 => [[['_route' => '_455'], ['a', 'b', 'c'], null, null, false, false, null]], + 7666 => [[['_route' => '_355'], ['a', 'b', 'c'], null, null, false, false, null]], + 7718 => [[['_route' => '_197'], ['a', 'b', 'c'], null, null, false, false, null]], + 7768 => [[['_route' => '_202'], ['a', 'b', 'c'], null, null, false, false, null]], + 7813 => [[['_route' => '_489'], ['a', 'b', 'c'], null, null, false, false, null]], + 7863 => [[['_route' => '_199'], ['a', 'b', 'c'], null, null, false, false, null]], + 7914 => [[['_route' => '_263'], ['a', 'b', 'c'], null, null, false, false, null]], + 7961 => [[['_route' => '_406'], ['a', 'b', 'c'], null, null, false, false, null]], + 8010 => [[['_route' => '_289'], ['a', 'b', 'c'], null, null, false, false, null]], + 8058 => [[['_route' => '_325'], ['a', 'b', 'c'], null, null, false, false, null]], + 8106 => [[['_route' => '_378'], ['a', 'b', 'c'], null, null, false, false, null]], + 8154 => [[['_route' => '_468'], ['a', 'b', 'c'], null, null, false, false, null]], + 8211 => [[['_route' => '_9'], ['a', 'b', 'c'], null, null, false, false, null]], + 8258 => [[['_route' => '_216'], ['a', 'b', 'c'], null, null, false, false, null]], + 8307 => [[['_route' => '_26'], ['a', 'b', 'c'], null, null, false, false, null]], + 8355 => [[['_route' => '_62'], ['a', 'b', 'c'], null, null, false, false, null]], + 8406 => [[['_route' => '_81'], ['a', 'b', 'c'], null, null, false, false, null]], + 8453 => [[['_route' => '_318'], ['a', 'b', 'c'], null, null, false, false, null]], + 8505 => [[['_route' => '_121'], ['a', 'b', 'c'], null, null, false, false, null]], + 8551 => [[['_route' => '_182'], ['a', 'b', 'c'], null, null, false, false, null]], + 8603 => [[['_route' => '_136'], ['a', 'b', 'c'], null, null, false, false, null]], + 8650 => [[['_route' => '_415'], ['a', 'b', 'c'], null, null, false, false, null]], + 8697 => [[['_route' => '_457'], ['a', 'b', 'c'], null, null, false, false, null]], + 8744 => [[['_route' => '_463'], ['a', 'b', 'c'], null, null, false, false, null]], + 8796 => [[['_route' => '_148'], ['a', 'b', 'c'], null, null, false, false, null]], + 8843 => [[['_route' => '_273'], ['a', 'b', 'c'], null, null, false, false, null]], + 8892 => [[['_route' => '_284'], ['a', 'b', 'c'], null, null, false, false, null]], + 8940 => [[['_route' => '_288'], ['a', 'b', 'c'], null, null, false, false, null]], + 8991 => [[['_route' => '_295'], ['a', 'b', 'c'], null, null, false, false, null]], + 9038 => [[['_route' => '_305'], ['a', 'b', 'c'], null, null, false, false, null]], + 9085 => [[['_route' => '_453'], ['a', 'b', 'c'], null, null, false, false, null]], + 9134 => [[['_route' => '_340'], ['a', 'b', 'c'], null, null, false, false, null]], + 9185 => [[['_route' => '_371'], ['a', 'b', 'c'], null, null, false, false, null]], + 9232 => [[['_route' => '_417'], ['a', 'b', 'c'], null, null, false, false, null]], + 9284 => [[['_route' => '_382'], ['a', 'b', 'c'], null, null, false, false, null]], + 9331 => [[['_route' => '_404'], ['a', 'b', 'c'], null, null, false, false, null]], + 9389 => [[['_route' => '_10'], ['a', 'b', 'c'], null, null, false, false, null]], + 9436 => [[['_route' => '_279'], ['a', 'b', 'c'], null, null, false, false, null]], + 9483 => [[['_route' => '_377'], ['a', 'b', 'c'], null, null, false, false, null]], + 9535 => [[['_route' => '_39'], ['a', 'b', 'c'], null, null, false, false, null]], + 9582 => [[['_route' => '_40'], ['a', 'b', 'c'], null, null, false, false, null]], + 9629 => [[['_route' => '_264'], ['a', 'b', 'c'], null, null, false, false, null]], + 9676 => [[['_route' => '_449'], ['a', 'b', 'c'], null, null, false, false, null]], + 9728 => [[['_route' => '_46'], ['a', 'b', 'c'], null, null, false, false, null]], + 9775 => [[['_route' => '_257'], ['a', 'b', 'c'], null, null, false, false, null]], + 9822 => [[['_route' => '_274'], ['a', 'b', 'c'], null, null, false, false, null]], + 9869 => [[['_route' => '_388'], ['a', 'b', 'c'], null, null, false, false, null]], + 9921 => [[['_route' => '_53'], ['a', 'b', 'c'], null, null, false, false, null]], + 9968 => [[['_route' => '_345'], ['a', 'b', 'c'], null, null, false, false, null]], + 10020 => [[['_route' => '_73'], ['a', 'b', 'c'], null, null, false, false, null]], + 10068 => [[['_route' => '_296'], ['a', 'b', 'c'], null, null, false, false, null]], + 10121 => [[['_route' => '_75'], ['a', 'b', 'c'], null, null, false, false, null]], + 10169 => [[['_route' => '_458'], ['a', 'b', 'c'], null, null, false, false, null]], + 10225 => [[['_route' => '_79'], ['a', 'b', 'c'], null, null, false, false, null]], + 10272 => [[['_route' => '_129'], ['a', 'b', 'c'], null, null, false, false, null]], + 10319 => [[['_route' => '_418'], ['a', 'b', 'c'], null, null, false, false, null]], + 10368 => [[['_route' => '_225'], ['a', 'b', 'c'], null, null, false, false, null]], + 10416 => [[['_route' => '_479'], ['a', 'b', 'c'], null, null, false, false, null]], + 10466 => [[['_route' => '_120'], ['a', 'b', 'c'], null, null, false, false, null]], + 10515 => [[['_route' => '_276'], ['a', 'b', 'c'], null, null, false, false, null]], + 10564 => [[['_route' => '_370'], ['a', 'b', 'c'], null, null, false, false, null]], + 10616 => [[['_route' => '_385'], ['a', 'b', 'c'], null, null, false, false, null]], + 10664 => [[['_route' => '_469'], ['a', 'b', 'c'], null, null, false, false, null]], + 10714 => [[['_route' => '_435'], ['a', 'b', 'c'], null, null, false, false, null]], + 10772 => [[['_route' => '_11'], ['a', 'b', 'c'], null, null, false, false, null]], + 10820 => [[['_route' => '_105'], ['a', 'b', 'c'], null, null, false, false, null]], + 10868 => [[['_route' => '_132'], ['a', 'b', 'c'], null, null, false, false, null]], + 10921 => [[['_route' => '_18'], ['a', 'b', 'c'], null, null, false, false, null]], + 10969 => [[['_route' => '_210'], ['a', 'b', 'c'], null, null, false, false, null]], + 11017 => [[['_route' => '_329'], ['a', 'b', 'c'], null, null, false, false, null]], + 11073 => [[['_route' => '_29'], ['a', 'b', 'c'], null, null, false, false, null]], + 11120 => [[['_route' => '_480'], ['a', 'b', 'c'], null, null, false, false, null]], + 11169 => [[['_route' => '_426'], ['a', 'b', 'c'], null, null, false, false, null]], + 11222 => [[['_route' => '_32'], ['a', 'b', 'c'], null, null, false, false, null]], + 11270 => [[['_route' => '_217'], ['a', 'b', 'c'], null, null, false, false, null]], + 11318 => [[['_route' => '_275'], ['a', 'b', 'c'], null, null, false, false, null]], + 11371 => [[['_route' => '_45'], ['a', 'b', 'c'], null, null, false, false, null]], + 11419 => [[['_route' => '_157'], ['a', 'b', 'c'], null, null, false, false, null]], + 11467 => [[['_route' => '_184'], ['a', 'b', 'c'], null, null, false, false, null]], + 11515 => [[['_route' => '_250'], ['a', 'b', 'c'], null, null, false, false, null]], + 11563 => [[['_route' => '_356'], ['a', 'b', 'c'], null, null, false, false, null]], + 11616 => [[['_route' => '_47'], ['a', 'b', 'c'], null, null, false, false, null]], + 11664 => [[['_route' => '_445'], ['a', 'b', 'c'], null, null, false, false, null]], + 11714 => [[['_route' => '_48'], ['a', 'b', 'c'], null, null, false, false, null]], + 11766 => [[['_route' => '_58'], ['a', 'b', 'c'], null, null, false, false, null]], + 11814 => [[['_route' => '_414'], ['a', 'b', 'c'], null, null, false, false, null]], + 11862 => [[['_route' => '_431'], ['a', 'b', 'c'], null, null, false, false, null]], + 11915 => [[['_route' => '_84'], ['a', 'b', 'c'], null, null, false, false, null]], + 11963 => [[['_route' => '_294'], ['a', 'b', 'c'], null, null, false, false, null]], + 12011 => [[['_route' => '_336'], ['a', 'b', 'c'], null, null, false, false, null]], + 12059 => [[['_route' => '_465'], ['a', 'b', 'c'], null, null, false, false, null]], + 12112 => [[['_route' => '_103'], ['a', 'b', 'c'], null, null, false, false, null]], + 12160 => [[['_route' => '_111'], ['a', 'b', 'c'], null, null, false, false, null]], + 12208 => [[['_route' => '_207'], ['a', 'b', 'c'], null, null, false, false, null]], + 12256 => [[['_route' => '_402'], ['a', 'b', 'c'], null, null, false, false, null]], + 12309 => [[['_route' => '_230'], ['a', 'b', 'c'], null, null, false, false, null]], + 12356 => [[['_route' => '_331'], ['a', 'b', 'c'], null, null, false, false, null]], + 12406 => [[['_route' => '_248'], ['a', 'b', 'c'], null, null, false, false, null]], + 12455 => [[['_route' => '_282'], ['a', 'b', 'c'], null, null, false, false, null]], + 12513 => [[['_route' => '_15'], ['a', 'b', 'c'], null, null, false, false, null]], + 12561 => [[['_route' => '_130'], ['a', 'b', 'c'], null, null, false, false, null]], + 12609 => [[['_route' => '_231'], ['a', 'b', 'c'], null, null, false, false, null]], + 12657 => [[['_route' => '_365'], ['a', 'b', 'c'], null, null, false, false, null]], + 12705 => [[['_route' => '_448'], ['a', 'b', 'c'], null, null, false, false, null]], + 12758 => [[['_route' => '_20'], ['a', 'b', 'c'], null, null, false, false, null]], + 12806 => [[['_route' => '_93'], ['a', 'b', 'c'], null, null, false, false, null]], + 12854 => [[['_route' => '_186'], ['a', 'b', 'c'], null, null, false, false, null]], + 12902 => [[['_route' => '_460'], ['a', 'b', 'c'], null, null, false, false, null]], + 12955 => [[['_route' => '_52'], ['a', 'b', 'c'], null, null, false, false, null]], + 13003 => [[['_route' => '_447'], ['a', 'b', 'c'], null, null, false, false, null]], + 13056 => [[['_route' => '_56'], ['a', 'b', 'c'], null, null, false, false, null]], + 13104 => [[['_route' => '_133'], ['a', 'b', 'c'], null, null, false, false, null]], + 13152 => [[['_route' => '_297'], ['a', 'b', 'c'], null, null, false, false, null]], + 13205 => [[['_route' => '_82'], ['a', 'b', 'c'], null, null, false, false, null]], + 13253 => [[['_route' => '_165'], ['a', 'b', 'c'], null, null, false, false, null]], + 13301 => [[['_route' => '_213'], ['a', 'b', 'c'], null, null, false, false, null]], + 13351 => [[['_route' => '_86'], ['a', 'b', 'c'], null, null, false, false, null]], + 13403 => [[['_route' => '_92'], ['a', 'b', 'c'], null, null, false, false, null]], + 13450 => [[['_route' => '_280'], ['a', 'b', 'c'], null, null, false, false, null]], + 13500 => [[['_route' => '_143'], ['a', 'b', 'c'], null, null, false, false, null]], + 13549 => [[['_route' => '_177'], ['a', 'b', 'c'], null, null, false, false, null]], + 13601 => [[['_route' => '_188'], ['a', 'b', 'c'], null, null, false, false, null]], + 13649 => [[['_route' => '_311'], ['a', 'b', 'c'], null, null, false, false, null]], + 13697 => [[['_route' => '_350'], ['a', 'b', 'c'], null, null, false, false, null]], + 13750 => [[['_route' => '_226'], ['a', 'b', 'c'], null, null, false, false, null]], + 13798 => [[['_route' => '_291'], ['a', 'b', 'c'], null, null, false, false, null]], + 13851 => [[['_route' => '_244'], ['a', 'b', 'c'], null, null, false, false, null]], + 13898 => [[['_route' => '_287'], ['a', 'b', 'c'], null, null, false, false, null]], + 13951 => [[['_route' => '_300'], ['a', 'b', 'c'], null, null, false, false, null]], + 13999 => [[['_route' => '_451'], ['a', 'b', 'c'], null, null, false, false, null]], + 14047 => [[['_route' => '_452'], ['a', 'b', 'c'], null, null, false, false, null]], + 14095 => [[['_route' => '_481'], ['a', 'b', 'c'], null, null, false, false, null]], + 14145 => [[['_route' => '_312'], ['a', 'b', 'c'], null, null, false, false, null]], + 14203 => [[['_route' => '_17'], ['a', 'b', 'c'], null, null, false, false, null]], + 14251 => [[['_route' => '_227'], ['a', 'b', 'c'], null, null, false, false, null]], + 14299 => [[['_route' => '_393'], ['a', 'b', 'c'], null, null, false, false, null]], + 14349 => [[['_route' => '_57'], ['a', 'b', 'c'], null, null, false, false, null]], + 14401 => [[['_route' => '_61'], ['a', 'b', 'c'], null, null, false, false, null]], + 14449 => [[['_route' => '_112'], ['a', 'b', 'c'], null, null, false, false, null]], + 14500 => [[['_route' => '_135'], ['a', 'b', 'c'], null, null, false, false, null]], + 14547 => [[['_route' => '_271'], ['a', 'b', 'c'], null, null, false, false, null]], + 14596 => [[['_route' => '_459'], ['a', 'b', 'c'], null, null, false, false, null]], + 14649 => [[['_route' => '_67'], ['a', 'b', 'c'], null, null, false, false, null]], + 14697 => [[['_route' => '_113'], ['a', 'b', 'c'], null, null, false, false, null]], + 14745 => [[['_route' => '_497'], ['a', 'b', 'c'], null, null, false, false, null]], + 14795 => [[['_route' => '_70'], ['a', 'b', 'c'], null, null, false, false, null]], + 14847 => [[['_route' => '_89'], ['a', 'b', 'c'], null, null, false, false, null]], + 14895 => [[['_route' => '_128'], ['a', 'b', 'c'], null, null, false, false, null]], + 14948 => [[['_route' => '_150'], ['a', 'b', 'c'], null, null, false, false, null]], + 14996 => [[['_route' => '_166'], ['a', 'b', 'c'], null, null, false, false, null]], + 15047 => [[['_route' => '_206'], ['a', 'b', 'c'], null, null, false, false, null]], + 15094 => [[['_route' => '_419'], ['a', 'b', 'c'], null, null, false, false, null]], + 15148 => [[['_route' => '_201'], ['a', 'b', 'c'], null, null, false, false, null]], + 15196 => [[['_route' => '_314'], ['a', 'b', 'c'], null, null, false, false, null]], + 15244 => [[['_route' => '_429'], ['a', 'b', 'c'], null, null, false, false, null]], + 15297 => [[['_route' => '_228'], ['a', 'b', 'c'], null, null, false, false, null]], + 15345 => [[['_route' => '_477'], ['a', 'b', 'c'], null, null, false, false, null]], + 15395 => [[['_route' => '_272'], ['a', 'b', 'c'], null, null, false, false, null]], + 15444 => [[['_route' => '_486'], ['a', 'b', 'c'], null, null, false, false, null]], + 15502 => [[['_route' => '_21'], ['a', 'b', 'c'], null, null, false, false, null]], + 15550 => [[['_route' => '_247'], ['a', 'b', 'c'], null, null, false, false, null]], + 15598 => [[['_route' => '_424'], ['a', 'b', 'c'], null, null, false, false, null]], + 15646 => [[['_route' => '_499'], ['a', 'b', 'c'], null, null, false, false, null]], + 15699 => [[['_route' => '_23'], ['a', 'b', 'c'], null, null, false, false, null]], + 15747 => [[['_route' => '_152'], ['a', 'b', 'c'], null, null, false, false, null]], + 15795 => [[['_route' => '_304'], ['a', 'b', 'c'], null, null, false, false, null]], + 15843 => [[['_route' => '_352'], ['a', 'b', 'c'], null, null, false, false, null]], + 15896 => [[['_route' => '_28'], ['a', 'b', 'c'], null, null, false, false, null]], + 15944 => [[['_route' => '_240'], ['a', 'b', 'c'], null, null, false, false, null]], + 16000 => [[['_route' => '_30'], ['a', 'b', 'c'], null, null, false, false, null]], + 16047 => [[['_route' => '_41'], ['a', 'b', 'c'], null, null, false, false, null]], + 16096 => [[['_route' => '_301'], ['a', 'b', 'c'], null, null, false, false, null]], + 16149 => [[['_route' => '_66'], ['a', 'b', 'c'], null, null, false, false, null]], + 16197 => [[['_route' => '_72'], ['a', 'b', 'c'], null, null, false, false, null]], + 16245 => [[['_route' => '_320'], ['a', 'b', 'c'], null, null, false, false, null]], + 16298 => [[['_route' => '_78'], ['a', 'b', 'c'], null, null, false, false, null]], + 16346 => [[['_route' => '_337'], ['a', 'b', 'c'], null, null, false, false, null]], + 16394 => [[['_route' => '_399'], ['a', 'b', 'c'], null, null, false, false, null]], + 16442 => [[['_route' => '_495'], ['a', 'b', 'c'], null, null, false, false, null]], + 16492 => [[['_route' => '_85'], ['a', 'b', 'c'], null, null, false, false, null]], + 16544 => [[['_route' => '_101'], ['a', 'b', 'c'], null, null, false, false, null]], + 16592 => [[['_route' => '_176'], ['a', 'b', 'c'], null, null, false, false, null]], + 16640 => [[['_route' => '_246'], ['a', 'b', 'c'], null, null, false, false, null]], + 16693 => [[['_route' => '_125'], ['a', 'b', 'c'], null, null, false, false, null]], + 16741 => [[['_route' => '_341'], ['a', 'b', 'c'], null, null, false, false, null]], + 16794 => [[['_route' => '_137'], ['a', 'b', 'c'], null, null, false, false, null]], + 16842 => [[['_route' => '_270'], ['a', 'b', 'c'], null, null, false, false, null]], + 16890 => [[['_route' => '_386'], ['a', 'b', 'c'], null, null, false, false, null]], + 16943 => [[['_route' => '_169'], ['a', 'b', 'c'], null, null, false, false, null]], + 16991 => [[['_route' => '_200'], ['a', 'b', 'c'], null, null, false, false, null]], + 17039 => [[['_route' => '_262'], ['a', 'b', 'c'], null, null, false, false, null]], + 17092 => [[['_route' => '_187'], ['a', 'b', 'c'], null, null, false, false, null]], + 17140 => [[['_route' => '_333'], ['a', 'b', 'c'], null, null, false, false, null]], + 17190 => [[['_route' => '_215'], ['a', 'b', 'c'], null, null, false, false, null]], + 17239 => [[['_route' => '_316'], ['a', 'b', 'c'], null, null, false, false, null]], + 17288 => [[['_route' => '_343'], ['a', 'b', 'c'], null, null, false, false, null]], + 17346 => [[['_route' => '_22'], ['a', 'b', 'c'], null, null, false, false, null]], + 17394 => [[['_route' => '_420'], ['a', 'b', 'c'], null, null, false, false, null]], + 17447 => [[['_route' => '_55'], ['a', 'b', 'c'], null, null, false, false, null]], + 17494 => [[['_route' => '_496'], ['a', 'b', 'c'], null, null, false, false, null]], + 17547 => [[['_route' => '_153'], ['a', 'b', 'c'], null, null, false, false, null]], + 17595 => [[['_route' => '_344'], ['a', 'b', 'c'], null, null, false, false, null]], + 17648 => [[['_route' => '_160'], ['a', 'b', 'c'], null, null, false, false, null]], + 17696 => [[['_route' => '_398'], ['a', 'b', 'c'], null, null, false, false, null]], + 17749 => [[['_route' => '_161'], ['a', 'b', 'c'], null, null, false, false, null]], + 17797 => [[['_route' => '_193'], ['a', 'b', 'c'], null, null, false, false, null]], + 17847 => [[['_route' => '_174'], ['a', 'b', 'c'], null, null, false, false, null]], + 17899 => [[['_route' => '_209'], ['a', 'b', 'c'], null, null, false, false, null]], + 17947 => [[['_route' => '_261'], ['a', 'b', 'c'], null, null, false, false, null]], + 18000 => [[['_route' => '_222'], ['a', 'b', 'c'], null, null, false, false, null]], + 18048 => [[['_route' => '_323'], ['a', 'b', 'c'], null, null, false, false, null]], + 18096 => [[['_route' => '_380'], ['a', 'b', 'c'], null, null, false, false, null]], + 18149 => [[['_route' => '_232'], ['a', 'b', 'c'], null, null, false, false, null]], + 18197 => [[['_route' => '_383'], ['a', 'b', 'c'], null, null, false, false, null]], + 18247 => [[['_route' => '_306'], ['a', 'b', 'c'], null, null, false, false, null]], + 18296 => [[['_route' => '_327'], ['a', 'b', 'c'], null, null, false, false, null]], + 18345 => [[['_route' => '_364'], ['a', 'b', 'c'], null, null, false, false, null]], + 18397 => [[['_route' => '_403'], ['a', 'b', 'c'], null, null, false, false, null]], + 18445 => [[['_route' => '_405'], ['a', 'b', 'c'], null, null, false, false, null]], + 18495 => [[['_route' => '_412'], ['a', 'b', 'c'], null, null, false, false, null]], + 18553 => [[['_route' => '_27'], ['a', 'b', 'c'], null, null, false, false, null]], + 18601 => [[['_route' => '_134'], ['a', 'b', 'c'], null, null, false, false, null]], + 18649 => [[['_route' => '_245'], ['a', 'b', 'c'], null, null, false, false, null]], + 18702 => [[['_route' => '_59'], ['a', 'b', 'c'], null, null, false, false, null]], + 18750 => [[['_route' => '_208'], ['a', 'b', 'c'], null, null, false, false, null]], + 18803 => [[['_route' => '_60'], ['a', 'b', 'c'], null, null, false, false, null]], + 18851 => [[['_route' => '_119'], ['a', 'b', 'c'], null, null, false, false, null]], + 18902 => [[['_route' => '_163'], ['a', 'b', 'c'], null, null, false, false, null]], + 18949 => [[['_route' => '_249'], ['a', 'b', 'c'], null, null, false, false, null]], + 18998 => [[['_route' => '_278'], ['a', 'b', 'c'], null, null, false, false, null]], + 19051 => [[['_route' => '_63'], ['a', 'b', 'c'], null, null, false, false, null]], + 19099 => [[['_route' => '_195'], ['a', 'b', 'c'], null, null, false, false, null]], + 19147 => [[['_route' => '_252'], ['a', 'b', 'c'], null, null, false, false, null]], + 19195 => [[['_route' => '_461'], ['a', 'b', 'c'], null, null, false, false, null]], + 19248 => [[['_route' => '_126'], ['a', 'b', 'c'], null, null, false, false, null]], + 19296 => [[['_route' => '_158'], ['a', 'b', 'c'], null, null, false, false, null]], + 19344 => [[['_route' => '_221'], ['a', 'b', 'c'], null, null, false, false, null]], + 19392 => [[['_route' => '_269'], ['a', 'b', 'c'], null, null, false, false, null]], + 19440 => [[['_route' => '_310'], ['a', 'b', 'c'], null, null, false, false, null]], + 19496 => [[['_route' => '_138'], ['a', 'b', 'c'], null, null, false, false, null]], + 19543 => [[['_route' => '_348'], ['a', 'b', 'c'], null, null, false, false, null]], + 19592 => [[['_route' => '_236'], ['a', 'b', 'c'], null, null, false, false, null]], + 19640 => [[['_route' => '_433'], ['a', 'b', 'c'], null, null, false, false, null]], + 19693 => [[['_route' => '_141'], ['a', 'b', 'c'], null, null, false, false, null]], + 19741 => [[['_route' => '_283'], ['a', 'b', 'c'], null, null, false, false, null]], + 19794 => [[['_route' => '_144'], ['a', 'b', 'c'], null, null, false, false, null]], + 19842 => [[['_route' => '_191'], ['a', 'b', 'c'], null, null, false, false, null]], + 19895 => [[['_route' => '_168'], ['a', 'b', 'c'], null, null, false, false, null]], + 19943 => [[['_route' => '_363'], ['a', 'b', 'c'], null, null, false, false, null]], + 19991 => [[['_route' => '_381'], ['a', 'b', 'c'], null, null, false, false, null]], + 20044 => [[['_route' => '_180'], ['a', 'b', 'c'], null, null, false, false, null]], + 20092 => [[['_route' => '_339'], ['a', 'b', 'c'], null, null, false, false, null]], + 20142 => [[['_route' => '_196'], ['a', 'b', 'c'], null, null, false, false, null]], + 20194 => [[['_route' => '_198'], ['a', 'b', 'c'], null, null, false, false, null]], + 20242 => [[['_route' => '_285'], ['a', 'b', 'c'], null, null, false, false, null]], + 20292 => [[['_route' => '_349'], ['a', 'b', 'c'], null, null, false, false, null]], + 20344 => [[['_route' => '_367'], ['a', 'b', 'c'], null, null, false, false, null]], + 20392 => [[['_route' => '_384'], ['a', 'b', 'c'], null, null, false, false, null]], + 20440 => [[['_route' => '_498'], ['a', 'b', 'c'], null, null, false, false, null]], + 20490 => [[['_route' => '_369'], ['a', 'b', 'c'], null, null, false, false, null]], + 20542 => [[['_route' => '_408'], ['a', 'b', 'c'], null, null, false, false, null]], + 20590 => [[['_route' => '_413'], ['a', 'b', 'c'], null, null, false, false, null]], + 20652 => [[['_route' => '_44'], ['a', 'b', 'c'], null, null, false, false, null]], + 20699 => [[['_route' => '_256'], ['a', 'b', 'c'], null, null, false, false, null]], + 20748 => [[['_route' => '_173'], ['a', 'b', 'c'], null, null, false, false, null]], + 20796 => [[['_route' => '_266'], ['a', 'b', 'c'], null, null, false, false, null]], + 20844 => [[['_route' => '_392'], ['a', 'b', 'c'], null, null, false, false, null]], + 20892 => [[['_route' => '_430'], ['a', 'b', 'c'], null, null, false, false, null]], + 20940 => [[['_route' => '_482'], ['a', 'b', 'c'], null, null, false, false, null]], + 20993 => [[['_route' => '_49'], ['a', 'b', 'c'], null, null, false, false, null]], + 21041 => [[['_route' => '_94'], ['a', 'b', 'c'], null, null, false, false, null]], + 21089 => [[['_route' => '_407'], ['a', 'b', 'c'], null, null, false, false, null]], + 21142 => [[['_route' => '_65'], ['a', 'b', 'c'], null, null, false, false, null]], + 21190 => [[['_route' => '_181'], ['a', 'b', 'c'], null, null, false, false, null]], + 21238 => [[['_route' => '_437'], ['a', 'b', 'c'], null, null, false, false, null]], + 21291 => [[['_route' => '_76'], ['a', 'b', 'c'], null, null, false, false, null]], + 21339 => [[['_route' => '_357'], ['a', 'b', 'c'], null, null, false, false, null]], + 21392 => [[['_route' => '_80'], ['a', 'b', 'c'], null, null, false, false, null]], + 21440 => [[['_route' => '_106'], ['a', 'b', 'c'], null, null, false, false, null]], + 21493 => [[['_route' => '_83'], ['a', 'b', 'c'], null, null, false, false, null]], + 21541 => [[['_route' => '_255'], ['a', 'b', 'c'], null, null, false, false, null]], + 21589 => [[['_route' => '_330'], ['a', 'b', 'c'], null, null, false, false, null]], + 21642 => [[['_route' => '_100'], ['a', 'b', 'c'], null, null, false, false, null]], + 21690 => [[['_route' => '_396'], ['a', 'b', 'c'], null, null, false, false, null]], + 21738 => [[['_route' => '_422'], ['a', 'b', 'c'], null, null, false, false, null]], + 21791 => [[['_route' => '_149'], ['a', 'b', 'c'], null, null, false, false, null]], + 21839 => [[['_route' => '_324'], ['a', 'b', 'c'], null, null, false, false, null]], + 21892 => [[['_route' => '_164'], ['a', 'b', 'c'], null, null, false, false, null]], + 21940 => [[['_route' => '_423'], ['a', 'b', 'c'], null, null, false, false, null]], + 21990 => [[['_route' => '_241'], ['a', 'b', 'c'], null, null, false, false, null]], + 22042 => [[['_route' => '_290'], ['a', 'b', 'c'], null, null, false, false, null]], + 22090 => [[['_route' => '_335'], ['a', 'b', 'c'], null, null, false, false, null]], + 22140 => [[['_route' => '_373'], ['a', 'b', 'c'], null, null, false, false, null]], + 22189 => [[['_route' => '_375'], ['a', 'b', 'c'], null, null, false, false, null]], + 22238 => [[['_route' => '_450'], ['a', 'b', 'c'], null, null, false, false, null]], + 22287 => [[['_route' => '_464'], ['a', 'b', 'c'], null, null, false, false, null]], + 22345 => [[['_route' => '_51'], ['a', 'b', 'c'], null, null, false, false, null]], + 22393 => [[['_route' => '_77'], ['a', 'b', 'c'], null, null, false, false, null]], + 22441 => [[['_route' => '_234'], ['a', 'b', 'c'], null, null, false, false, null]], + 22489 => [[['_route' => '_394'], ['a', 'b', 'c'], null, null, false, false, null]], + 22542 => [[['_route' => '_88'], ['a', 'b', 'c'], null, null, false, false, null]], + 22590 => [[['_route' => '_155'], ['a', 'b', 'c'], null, null, false, false, null]], + 22643 => [[['_route' => '_96'], ['a', 'b', 'c'], null, null, false, false, null]], + 22691 => [[['_route' => '_298'], ['a', 'b', 'c'], null, null, false, false, null]], + 22739 => [[['_route' => '_470'], ['a', 'b', 'c'], null, null, false, false, null]], + 22792 => [[['_route' => '_109'], ['a', 'b', 'c'], null, null, false, false, null]], + 22840 => [[['_route' => '_204'], ['a', 'b', 'c'], null, null, false, false, null]], + 22893 => [[['_route' => '_115'], ['a', 'b', 'c'], null, null, false, false, null]], + 22941 => [[['_route' => '_145'], ['a', 'b', 'c'], null, null, false, false, null]], + 22994 => [[['_route' => '_123'], ['a', 'b', 'c'], null, null, false, false, null]], + 23042 => [[['_route' => '_277'], ['a', 'b', 'c'], null, null, false, false, null]], + 23090 => [[['_route' => '_473'], ['a', 'b', 'c'], null, null, false, false, null]], + 23143 => [[['_route' => '_334'], ['a', 'b', 'c'], null, null, false, false, null]], + 23191 => [[['_route' => '_493'], ['a', 'b', 'c'], null, null, false, false, null]], + 23244 => [[['_route' => '_372'], ['a', 'b', 'c'], null, null, false, false, null]], + 23292 => [[['_route' => '_432'], ['a', 'b', 'c'], null, null, false, false, null]], + 23340 => [[['_route' => '_436'], ['a', 'b', 'c'], null, null, false, false, null]], + 23393 => [[['_route' => '_425'], ['a', 'b', 'c'], null, null, false, false, null]], + 23441 => [[['_route' => '_456'], ['a', 'b', 'c'], null, null, false, false, null]], + 23489 => [[['_route' => '_474'], ['a', 'b', 'c'], null, null, false, false, null]], + 23539 => [[['_route' => '_485'], ['a', 'b', 'c'], null, null, false, false, null]], + 23594 => [[['_route' => '_91'], ['a', 'b', 'c'], null, null, false, false, null]], + 23646 => [[['_route' => '_110'], ['a', 'b', 'c'], null, null, false, false, null]], + 23694 => [[['_route' => '_114'], ['a', 'b', 'c'], null, null, false, false, null]], + 23750 => [[['_route' => '_118'], ['a', 'b', 'c'], null, null, false, false, null]], + 23796 => [[['_route' => '_475'], ['a', 'b', 'c'], null, null, false, false, null]], + 23844 => [[['_route' => '_366'], ['a', 'b', 'c'], null, null, false, false, null]], + 23897 => [[['_route' => '_167'], ['a', 'b', 'c'], null, null, false, false, null]], + 23945 => [[['_route' => '_192'], ['a', 'b', 'c'], null, null, false, false, null]], + 23993 => [[['_route' => '_342'], ['a', 'b', 'c'], null, null, false, false, null]], + 24046 => [[['_route' => '_229'], ['a', 'b', 'c'], null, null, false, false, null]], + 24097 => [[['_route' => '_235'], ['a', 'b', 'c'], null, null, false, false, null]], + 24144 => [[['_route' => '_302'], ['a', 'b', 'c'], null, null, false, false, null]], + 24193 => [[['_route' => '_322'], ['a', 'b', 'c'], null, null, false, false, null]], + 24246 => [[['_route' => '_237'], ['a', 'b', 'c'], null, null, false, false, null]], + 24294 => [[['_route' => '_293'], ['a', 'b', 'c'], null, null, false, false, null]], + 24347 => [[['_route' => '_239'], ['a', 'b', 'c'], null, null, false, false, null]], + 24395 => [[['_route' => '_444'], ['a', 'b', 'c'], null, null, false, false, null]], + 24443 => [[['_route' => '_491'], ['a', 'b', 'c'], null, null, false, false, null]], + 24491 => [[['_route' => '_492'], ['a', 'b', 'c'], null, null, false, false, null]], + 24541 => [[['_route' => '_258'], ['a', 'b', 'c'], null, null, false, false, null]], + 24590 => [[['_route' => '_317'], ['a', 'b', 'c'], null, null, false, false, null]], + 24639 => [[['_route' => '_361'], ['a', 'b', 'c'], null, null, false, false, null]], + 24688 => [[['_route' => '_391'], ['a', 'b', 'c'], null, null, false, false, null]], + 24737 => [[['_route' => '_462'], ['a', 'b', 'c'], null, null, false, false, null]], + 24786 => [[['_route' => '_476'], ['a', 'b', 'c'], null, null, false, false, null]], + 24837 => [[['_route' => '_501'], ['a', 'b', 'c'], null, null, false, false, null]], + 24889 => [[['_route' => '_514'], ['a', 'b', 'c'], null, null, false, false, null]], + 24937 => [[['_route' => '_731'], ['a', 'b', 'c'], null, null, false, false, null]], + 24990 => [[['_route' => '_522'], ['a', 'b', 'c'], null, null, false, false, null]], + 25038 => [[['_route' => '_693'], ['a', 'b', 'c'], null, null, false, false, null]], + 25091 => [[['_route' => '_537'], ['a', 'b', 'c'], null, null, false, false, null]], + 25139 => [[['_route' => '_554'], ['a', 'b', 'c'], null, null, false, false, null]], + 25187 => [[['_route' => '_645'], ['a', 'b', 'c'], null, null, false, false, null]], + 25235 => [[['_route' => '_862'], ['a', 'b', 'c'], null, null, false, false, null]], + 25288 => [[['_route' => '_539'], ['a', 'b', 'c'], null, null, false, false, null]], + 25336 => [[['_route' => '_729'], ['a', 'b', 'c'], null, null, false, false, null]], + 25384 => [[['_route' => '_897'], ['a', 'b', 'c'], null, null, false, false, null]], + 25437 => [[['_route' => '_561'], ['a', 'b', 'c'], null, null, false, false, null]], + 25485 => [[['_route' => '_615'], ['a', 'b', 'c'], null, null, false, false, null]], + 25533 => [[['_route' => '_764'], ['a', 'b', 'c'], null, null, false, false, null]], + 25581 => [[['_route' => '_948'], ['a', 'b', 'c'], null, null, false, false, null]], + 25634 => [[['_route' => '_617'], ['a', 'b', 'c'], null, null, false, false, null]], + 25682 => [[['_route' => '_671'], ['a', 'b', 'c'], null, null, false, false, null]], + 25735 => [[['_route' => '_649'], ['a', 'b', 'c'], null, null, false, false, null]], + 25783 => [[['_route' => '_651'], ['a', 'b', 'c'], null, null, false, false, null]], + 25831 => [[['_route' => '_684'], ['a', 'b', 'c'], null, null, false, false, null]], + 25884 => [[['_route' => '_669'], ['a', 'b', 'c'], null, null, false, false, null]], + 25932 => [[['_route' => '_743'], ['a', 'b', 'c'], null, null, false, false, null]], + 25980 => [[['_route' => '_962'], ['a', 'b', 'c'], null, null, false, false, null]], + 26033 => [[['_route' => '_694'], ['a', 'b', 'c'], null, null, false, false, null]], + 26081 => [[['_route' => '_985'], ['a', 'b', 'c'], null, null, false, false, null]], + 26134 => [[['_route' => '_707'], ['a', 'b', 'c'], null, null, false, false, null]], + 26182 => [[['_route' => '_718'], ['a', 'b', 'c'], null, null, false, false, null]], + 26235 => [[['_route' => '_720'], ['a', 'b', 'c'], null, null, false, false, null]], + 26283 => [[['_route' => '_745'], ['a', 'b', 'c'], null, null, false, false, null]], + 26333 => [[['_route' => '_874'], ['a', 'b', 'c'], null, null, false, false, null]], + 26391 => [[['_route' => '_502'], ['a', 'b', 'c'], null, null, false, false, null]], + 26439 => [[['_route' => '_667'], ['a', 'b', 'c'], null, null, false, false, null]], + 26487 => [[['_route' => '_911'], ['a', 'b', 'c'], null, null, false, false, null]], + 26535 => [[['_route' => '_942'], ['a', 'b', 'c'], null, null, false, false, null]], + 26585 => [[['_route' => '_504'], ['a', 'b', 'c'], null, null, false, false, null]], + 26637 => [[['_route' => '_524'], ['a', 'b', 'c'], null, null, false, false, null]], + 26685 => [[['_route' => '_732'], ['a', 'b', 'c'], null, null, false, false, null]], + 26738 => [[['_route' => '_596'], ['a', 'b', 'c'], null, null, false, false, null]], + 26786 => [[['_route' => '_601'], ['a', 'b', 'c'], null, null, false, false, null]], + 26839 => [[['_route' => '_620'], ['a', 'b', 'c'], null, null, false, false, null]], + 26887 => [[['_route' => '_631'], ['a', 'b', 'c'], null, null, false, false, null]], + 26935 => [[['_route' => '_771'], ['a', 'b', 'c'], null, null, false, false, null]], + 26983 => [[['_route' => '_937'], ['a', 'b', 'c'], null, null, false, false, null]], + 27031 => [[['_route' => '_999'], ['a', 'b', 'c'], null, null, false, false, null]], + 27084 => [[['_route' => '_657'], ['a', 'b', 'c'], null, null, false, false, null]], + 27132 => [[['_route' => '_701'], ['a', 'b', 'c'], null, null, false, false, null]], + 27185 => [[['_route' => '_662'], ['a', 'b', 'c'], null, null, false, false, null]], + 27233 => [[['_route' => '_797'], ['a', 'b', 'c'], null, null, false, false, null]], + 27281 => [[['_route' => '_924'], ['a', 'b', 'c'], null, null, false, false, null]], + 27334 => [[['_route' => '_702'], ['a', 'b', 'c'], null, null, false, false, null]], + 27382 => [[['_route' => '_750'], ['a', 'b', 'c'], null, null, false, false, null]], + 27435 => [[['_route' => '_749'], ['a', 'b', 'c'], null, null, false, false, null]], + 27483 => [[['_route' => '_837'], ['a', 'b', 'c'], null, null, false, false, null]], + 27533 => [[['_route' => '_758'], ['a', 'b', 'c'], null, null, false, false, null]], + 27585 => [[['_route' => '_810'], ['a', 'b', 'c'], null, null, false, false, null]], + 27633 => [[['_route' => '_902'], ['a', 'b', 'c'], null, null, false, false, null]], + 27683 => [[['_route' => '_845'], ['a', 'b', 'c'], null, null, false, false, null]], + 27741 => [[['_route' => '_503'], ['a', 'b', 'c'], null, null, false, false, null]], + 27792 => [[['_route' => '_756'], ['a', 'b', 'c'], null, null, false, false, null]], + 27839 => [[['_route' => '_799'], ['a', 'b', 'c'], null, null, false, false, null]], + 27888 => [[['_route' => '_769'], ['a', 'b', 'c'], null, null, false, false, null]], + 27936 => [[['_route' => '_981'], ['a', 'b', 'c'], null, null, false, false, null]], + 27989 => [[['_route' => '_507'], ['a', 'b', 'c'], null, null, false, false, null]], + 28037 => [[['_route' => '_672'], ['a', 'b', 'c'], null, null, false, false, null]], + 28085 => [[['_route' => '_790'], ['a', 'b', 'c'], null, null, false, false, null]], + 28138 => [[['_route' => '_515'], ['a', 'b', 'c'], null, null, false, false, null]], + 28186 => [[['_route' => '_523'], ['a', 'b', 'c'], null, null, false, false, null]], + 28234 => [[['_route' => '_957'], ['a', 'b', 'c'], null, null, false, false, null]], + 28282 => [[['_route' => '_995'], ['a', 'b', 'c'], null, null, false, false, null]], + 28335 => [[['_route' => '_532'], ['a', 'b', 'c'], null, null, false, false, null]], + 28383 => [[['_route' => '_642'], ['a', 'b', 'c'], null, null, false, false, null]], + 28433 => [[['_route' => '_579'], ['a', 'b', 'c'], null, null, false, false, null]], + 28485 => [[['_route' => '_625'], ['a', 'b', 'c'], null, null, false, false, null]], + 28533 => [[['_route' => '_916'], ['a', 'b', 'c'], null, null, false, false, null]], + 28586 => [[['_route' => '_633'], ['a', 'b', 'c'], null, null, false, false, null]], + 28634 => [[['_route' => '_656'], ['a', 'b', 'c'], null, null, false, false, null]], + 28687 => [[['_route' => '_658'], ['a', 'b', 'c'], null, null, false, false, null]], + 28735 => [[['_route' => '_943'], ['a', 'b', 'c'], null, null, false, false, null]], + 28788 => [[['_route' => '_664'], ['a', 'b', 'c'], null, null, false, false, null]], + 28836 => [[['_route' => '_852'], ['a', 'b', 'c'], null, null, false, false, null]], + 28884 => [[['_route' => '_870'], ['a', 'b', 'c'], null, null, false, false, null]], + 28937 => [[['_route' => '_683'], ['a', 'b', 'c'], null, null, false, false, null]], + 28985 => [[['_route' => '_915'], ['a', 'b', 'c'], null, null, false, false, null]], + 29038 => [[['_route' => '_719'], ['a', 'b', 'c'], null, null, false, false, null]], + 29086 => [[['_route' => '_859'], ['a', 'b', 'c'], null, null, false, false, null]], + 29134 => [[['_route' => '_912'], ['a', 'b', 'c'], null, null, false, false, null]], + 29182 => [[['_route' => '_978'], ['a', 'b', 'c'], null, null, false, false, null]], + 29235 => [[['_route' => '_738'], ['a', 'b', 'c'], null, null, false, false, null]], + 29283 => [[['_route' => '_883'], ['a', 'b', 'c'], null, null, false, false, null]], + 29333 => [[['_route' => '_741'], ['a', 'b', 'c'], null, null, false, false, null]], + 29382 => [[['_route' => '_760'], ['a', 'b', 'c'], null, null, false, false, null]], + 29431 => [[['_route' => '_895'], ['a', 'b', 'c'], null, null, false, false, null]], + 29489 => [[['_route' => '_505'], ['a', 'b', 'c'], null, null, false, false, null]], + 29537 => [[['_route' => '_935'], ['a', 'b', 'c'], null, null, false, false, null]], + 29590 => [[['_route' => '_509'], ['a', 'b', 'c'], null, null, false, false, null]], + 29638 => [[['_route' => '_820'], ['a', 'b', 'c'], null, null, false, false, null]], + 29686 => [[['_route' => '_910'], ['a', 'b', 'c'], null, null, false, false, null]], + 29739 => [[['_route' => '_518'], ['a', 'b', 'c'], null, null, false, false, null]], + 29787 => [[['_route' => '_618'], ['a', 'b', 'c'], null, null, false, false, null]], + 29840 => [[['_route' => '_546'], ['a', 'b', 'c'], null, null, false, false, null]], + 29888 => [[['_route' => '_740'], ['a', 'b', 'c'], null, null, false, false, null]], + 29936 => [[['_route' => '_867'], ['a', 'b', 'c'], null, null, false, false, null]], + 29989 => [[['_route' => '_572'], ['a', 'b', 'c'], null, null, false, false, null]], + 30037 => [[['_route' => '_952'], ['a', 'b', 'c'], null, null, false, false, null]], + 30090 => [[['_route' => '_573'], ['a', 'b', 'c'], null, null, false, false, null]], + 30138 => [[['_route' => '_692'], ['a', 'b', 'c'], null, null, false, false, null]], + 30186 => [[['_route' => '_700'], ['a', 'b', 'c'], null, null, false, false, null]], + 30234 => [[['_route' => '_772'], ['a', 'b', 'c'], null, null, false, false, null]], + 30284 => [[['_route' => '_653'], ['a', 'b', 'c'], null, null, false, false, null]], + 30336 => [[['_route' => '_695'], ['a', 'b', 'c'], null, null, false, false, null]], + 30384 => [[['_route' => '_748'], ['a', 'b', 'c'], null, null, false, false, null]], + 30437 => [[['_route' => '_710'], ['a', 'b', 'c'], null, null, false, false, null]], + 30485 => [[['_route' => '_716'], ['a', 'b', 'c'], null, null, false, false, null]], + 30533 => [[['_route' => '_969'], ['a', 'b', 'c'], null, null, false, false, null]], + 30586 => [[['_route' => '_734'], ['a', 'b', 'c'], null, null, false, false, null]], + 30634 => [[['_route' => '_742'], ['a', 'b', 'c'], null, null, false, false, null]], + 30682 => [[['_route' => '_844'], ['a', 'b', 'c'], null, null, false, false, null]], + 30735 => [[['_route' => '_763'], ['a', 'b', 'c'], null, null, false, false, null]], + 30783 => [[['_route' => '_965'], ['a', 'b', 'c'], null, null, false, false, null]], + 30836 => [[['_route' => '_778'], ['a', 'b', 'c'], null, null, false, false, null]], + 30884 => [[['_route' => '_813'], ['a', 'b', 'c'], null, null, false, false, null]], + 30932 => [[['_route' => '_831'], ['a', 'b', 'c'], null, null, false, false, null]], + 30982 => [[['_route' => '_955'], ['a', 'b', 'c'], null, null, false, false, null]], + 31031 => [[['_route' => '_997'], ['a', 'b', 'c'], null, null, false, false, null]], + 31089 => [[['_route' => '_506'], ['a', 'b', 'c'], null, null, false, false, null]], + 31137 => [[['_route' => '_575'], ['a', 'b', 'c'], null, null, false, false, null]], + 31190 => [[['_route' => '_516'], ['a', 'b', 'c'], null, null, false, false, null]], + 31238 => [[['_route' => '_553'], ['a', 'b', 'c'], null, null, false, false, null]], + 31291 => [[['_route' => '_528'], ['a', 'b', 'c'], null, null, false, false, null]], + 31339 => [[['_route' => '_847'], ['a', 'b', 'c'], null, null, false, false, null]], + 31387 => [[['_route' => '_904'], ['a', 'b', 'c'], null, null, false, false, null]], + 31440 => [[['_route' => '_574'], ['a', 'b', 'c'], null, null, false, false, null]], + 31488 => [[['_route' => '_818'], ['a', 'b', 'c'], null, null, false, false, null]], + 31538 => [[['_route' => '_577'], ['a', 'b', 'c'], null, null, false, false, null]], + 31590 => [[['_route' => '_584'], ['a', 'b', 'c'], null, null, false, false, null]], + 31638 => [[['_route' => '_905'], ['a', 'b', 'c'], null, null, false, false, null]], + 31691 => [[['_route' => '_612'], ['a', 'b', 'c'], null, null, false, false, null]], + 31739 => [[['_route' => '_688'], ['a', 'b', 'c'], null, null, false, false, null]], + 31787 => [[['_route' => '_854'], ['a', 'b', 'c'], null, null, false, false, null]], + 31840 => [[['_route' => '_613'], ['a', 'b', 'c'], null, null, false, false, null]], + 31888 => [[['_route' => '_767'], ['a', 'b', 'c'], null, null, false, false, null]], + 31941 => [[['_route' => '_666'], ['a', 'b', 'c'], null, null, false, false, null]], + 31989 => [[['_route' => '_759'], ['a', 'b', 'c'], null, null, false, false, null]], + 32037 => [[['_route' => '_827'], ['a', 'b', 'c'], null, null, false, false, null]], + 32085 => [[['_route' => '_840'], ['a', 'b', 'c'], null, null, false, false, null]], + 32138 => [[['_route' => '_680'], ['a', 'b', 'c'], null, null, false, false, null]], + 32186 => [[['_route' => '_784'], ['a', 'b', 'c'], null, null, false, false, null]], + 32234 => [[['_route' => '_842'], ['a', 'b', 'c'], null, null, false, false, null]], + 32282 => [[['_route' => '_860'], ['a', 'b', 'c'], null, null, false, false, null]], + 32332 => [[['_route' => '_704'], ['a', 'b', 'c'], null, null, false, false, null]], + 32381 => [[['_route' => '_727'], ['a', 'b', 'c'], null, null, false, false, null]], + 32430 => [[['_route' => '_777'], ['a', 'b', 'c'], null, null, false, false, null]], + 32482 => [[['_route' => '_838'], ['a', 'b', 'c'], null, null, false, false, null]], + 32530 => [[['_route' => '_861'], ['a', 'b', 'c'], null, null, false, false, null]], + 32583 => [[['_route' => '_849'], ['a', 'b', 'c'], null, null, false, false, null]], + 32631 => [[['_route' => '_982'], ['a', 'b', 'c'], null, null, false, false, null]], + 32679 => [[['_route' => '_986'], ['a', 'b', 'c'], null, null, false, false, null]], + 32741 => [[['_route' => '_508'], ['a', 'b', 'c'], null, null, false, false, null]], + 32788 => [[['_route' => '_517'], ['a', 'b', 'c'], null, null, false, false, null]], + 32837 => [[['_route' => '_622'], ['a', 'b', 'c'], null, null, false, false, null]], + 32890 => [[['_route' => '_513'], ['a', 'b', 'c'], null, null, false, false, null]], + 32938 => [[['_route' => '_655'], ['a', 'b', 'c'], null, null, false, false, null]], + 32986 => [[['_route' => '_843'], ['a', 'b', 'c'], null, null, false, false, null]], + 33034 => [[['_route' => '_939'], ['a', 'b', 'c'], null, null, false, false, null]], + 33084 => [[['_route' => '_529'], ['a', 'b', 'c'], null, null, false, false, null]], + 33136 => [[['_route' => '_535'], ['a', 'b', 'c'], null, null, false, false, null]], + 33184 => [[['_route' => '_685'], ['a', 'b', 'c'], null, null, false, false, null]], + 33240 => [[['_route' => '_559'], ['a', 'b', 'c'], null, null, false, false, null]], + 33287 => [[['_route' => '_661'], ['a', 'b', 'c'], null, null, false, false, null]], + 33336 => [[['_route' => '_768'], ['a', 'b', 'c'], null, null, false, false, null]], + 33389 => [[['_route' => '_589'], ['a', 'b', 'c'], null, null, false, false, null]], + 33437 => [[['_route' => '_647'], ['a', 'b', 'c'], null, null, false, false, null]], + 33485 => [[['_route' => '_652'], ['a', 'b', 'c'], null, null, false, false, null]], + 33533 => [[['_route' => '_834'], ['a', 'b', 'c'], null, null, false, false, null]], + 33586 => [[['_route' => '_591'], ['a', 'b', 'c'], null, null, false, false, null]], + 33634 => [[['_route' => '_599'], ['a', 'b', 'c'], null, null, false, false, null]], + 33687 => [[['_route' => '_787'], ['a', 'b', 'c'], null, null, false, false, null]], + 33734 => [[['_route' => '_848'], ['a', 'b', 'c'], null, null, false, false, null]], + 33787 => [[['_route' => '_796'], ['a', 'b', 'c'], null, null, false, false, null]], + 33835 => [[['_route' => '_877'], ['a', 'b', 'c'], null, null, false, false, null]], + 33885 => [[['_route' => '_809'], ['a', 'b', 'c'], null, null, false, false, null]], + 33934 => [[['_route' => '_817'], ['a', 'b', 'c'], null, null, false, false, null]], + 33986 => [[['_route' => '_819'], ['a', 'b', 'c'], null, null, false, false, null]], + 34034 => [[['_route' => '_865'], ['a', 'b', 'c'], null, null, false, false, null]], + 34084 => [[['_route' => '_919'], ['a', 'b', 'c'], null, null, false, false, null]], + 34133 => [[['_route' => '_949'], ['a', 'b', 'c'], null, null, false, false, null]], + 34191 => [[['_route' => '_510'], ['a', 'b', 'c'], null, null, false, false, null]], + 34239 => [[['_route' => '_590'], ['a', 'b', 'c'], null, null, false, false, null]], + 34287 => [[['_route' => '_597'], ['a', 'b', 'c'], null, null, false, false, null]], + 34335 => [[['_route' => '_682'], ['a', 'b', 'c'], null, null, false, false, null]], + 34383 => [[['_route' => '_723'], ['a', 'b', 'c'], null, null, false, false, null]], + 34436 => [[['_route' => '_521'], ['a', 'b', 'c'], null, null, false, false, null]], + 34484 => [[['_route' => '_594'], ['a', 'b', 'c'], null, null, false, false, null]], + 34532 => [[['_route' => '_689'], ['a', 'b', 'c'], null, null, false, false, null]], + 34580 => [[['_route' => '_713'], ['a', 'b', 'c'], null, null, false, false, null]], + 34628 => [[['_route' => '_889'], ['a', 'b', 'c'], null, null, false, false, null]], + 34681 => [[['_route' => '_531'], ['a', 'b', 'c'], null, null, false, false, null]], + 34729 => [[['_route' => '_639'], ['a', 'b', 'c'], null, null, false, false, null]], + 34780 => [[['_route' => '_646'], ['a', 'b', 'c'], null, null, false, false, null]], + 34827 => [[['_route' => '_659'], ['a', 'b', 'c'], null, null, false, false, null]], + 34876 => [[['_route' => '_959'], ['a', 'b', 'c'], null, null, false, false, null]], + 34929 => [[['_route' => '_550'], ['a', 'b', 'c'], null, null, false, false, null]], + 34977 => [[['_route' => '_833'], ['a', 'b', 'c'], null, null, false, false, null]], + 35025 => [[['_route' => '_899'], ['a', 'b', 'c'], null, null, false, false, null]], + 35081 => [[['_route' => '_580'], ['a', 'b', 'c'], null, null, false, false, null]], + 35128 => [[['_route' => '_762'], ['a', 'b', 'c'], null, null, false, false, null]], + 35177 => [[['_route' => '_896'], ['a', 'b', 'c'], null, null, false, false, null]], + 35230 => [[['_route' => '_595'], ['a', 'b', 'c'], null, null, false, false, null]], + 35278 => [[['_route' => '_933'], ['a', 'b', 'c'], null, null, false, false, null]], + 35328 => [[['_route' => '_610'], ['a', 'b', 'c'], null, null, false, false, null]], + 35380 => [[['_route' => '_629'], ['a', 'b', 'c'], null, null, false, false, null]], + 35428 => [[['_route' => '_744'], ['a', 'b', 'c'], null, null, false, false, null]], + 35481 => [[['_route' => '_674'], ['a', 'b', 'c'], null, null, false, false, null]], + 35529 => [[['_route' => '_726'], ['a', 'b', 'c'], null, null, false, false, null]], + 35577 => [[['_route' => '_929'], ['a', 'b', 'c'], null, null, false, false, null]], + 35627 => [[['_route' => '_696'], ['a', 'b', 'c'], null, null, false, false, null]], + 35679 => [[['_route' => '_841'], ['a', 'b', 'c'], null, null, false, false, null]], + 35727 => [[['_route' => '_890'], ['a', 'b', 'c'], null, null, false, false, null]], + 35777 => [[['_route' => '_885'], ['a', 'b', 'c'], null, null, false, false, null]], + 35826 => [[['_route' => '_888'], ['a', 'b', 'c'], null, null, false, false, null]], + 35875 => [[['_route' => '_996'], ['a', 'b', 'c'], null, null, false, false, null]], + 35933 => [[['_route' => '_511'], ['a', 'b', 'c'], null, null, false, false, null]], + 35981 => [[['_route' => '_576'], ['a', 'b', 'c'], null, null, false, false, null]], + 36029 => [[['_route' => '_623'], ['a', 'b', 'c'], null, null, false, false, null]], + 36082 => [[['_route' => '_560'], ['a', 'b', 'c'], null, null, false, false, null]], + 36129 => [[['_route' => '_585'], ['a', 'b', 'c'], null, null, false, false, null]], + 36182 => [[['_route' => '_570'], ['a', 'b', 'c'], null, null, false, false, null]], + 36230 => [[['_route' => '_578'], ['a', 'b', 'c'], null, null, false, false, null]], + 36281 => [[['_route' => '_780'], ['a', 'b', 'c'], null, null, false, false, null]], + 36328 => [[['_route' => '_808'], ['a', 'b', 'c'], null, null, false, false, null]], + 36382 => [[['_route' => '_593'], ['a', 'b', 'c'], null, null, false, false, null]], + 36430 => [[['_route' => '_900'], ['a', 'b', 'c'], null, null, false, false, null]], + 36483 => [[['_route' => '_632'], ['a', 'b', 'c'], null, null, false, false, null]], + 36531 => [[['_route' => '_654'], ['a', 'b', 'c'], null, null, false, false, null]], + 36579 => [[['_route' => '_721'], ['a', 'b', 'c'], null, null, false, false, null]], + 36627 => [[['_route' => '_836'], ['a', 'b', 'c'], null, null, false, false, null]], + 36680 => [[['_route' => '_637'], ['a', 'b', 'c'], null, null, false, false, null]], + 36728 => [[['_route' => '_737'], ['a', 'b', 'c'], null, null, false, false, null]], + 36784 => [[['_route' => '_699'], ['a', 'b', 'c'], null, null, false, false, null]], + 36831 => [[['_route' => '_822'], ['a', 'b', 'c'], null, null, false, false, null]], + 36880 => [[['_route' => '_853'], ['a', 'b', 'c'], null, null, false, false, null]], + 36933 => [[['_route' => '_708'], ['a', 'b', 'c'], null, null, false, false, null]], + 36981 => [[['_route' => '_871'], ['a', 'b', 'c'], null, null, false, false, null]], + 37034 => [[['_route' => '_752'], ['a', 'b', 'c'], null, null, false, false, null]], + 37082 => [[['_route' => '_989'], ['a', 'b', 'c'], null, null, false, false, null]], + 37132 => [[['_route' => '_855'], ['a', 'b', 'c'], null, null, false, false, null]], + 37184 => [[['_route' => '_858'], ['a', 'b', 'c'], null, null, false, false, null]], + 37232 => [[['_route' => '_898'], ['a', 'b', 'c'], null, null, false, false, null]], + 37282 => [[['_route' => '_903'], ['a', 'b', 'c'], null, null, false, false, null]], + 37331 => [[['_route' => '_909'], ['a', 'b', 'c'], null, null, false, false, null]], + 37380 => [[['_route' => '_950'], ['a', 'b', 'c'], null, null, false, false, null]], + 37441 => [[['_route' => '_512'], ['a', 'b', 'c'], null, null, false, false, null]], + 37488 => [[['_route' => '_691'], ['a', 'b', 'c'], null, null, false, false, null]], + 37537 => [[['_route' => '_686'], ['a', 'b', 'c'], null, null, false, false, null]], + 37587 => [[['_route' => '_527'], ['a', 'b', 'c'], null, null, false, false, null]], + 37639 => [[['_route' => '_541'], ['a', 'b', 'c'], null, null, false, false, null]], + 37687 => [[['_route' => '_956'], ['a', 'b', 'c'], null, null, false, false, null]], + 37740 => [[['_route' => '_555'], ['a', 'b', 'c'], null, null, false, false, null]], + 37788 => [[['_route' => '_681'], ['a', 'b', 'c'], null, null, false, false, null]], + 37841 => [[['_route' => '_556'], ['a', 'b', 'c'], null, null, false, false, null]], + 37889 => [[['_route' => '_802'], ['a', 'b', 'c'], null, null, false, false, null]], + 37939 => [[['_route' => '_558'], ['a', 'b', 'c'], null, null, false, false, null]], + 37991 => [[['_route' => '_564'], ['a', 'b', 'c'], null, null, false, false, null]], + 38039 => [[['_route' => '_670'], ['a', 'b', 'c'], null, null, false, false, null]], + 38087 => [[['_route' => '_884'], ['a', 'b', 'c'], null, null, false, false, null]], + 38140 => [[['_route' => '_627'], ['a', 'b', 'c'], null, null, false, false, null]], + 38187 => [[['_route' => '_746'], ['a', 'b', 'c'], null, null, false, false, null]], + 38240 => [[['_route' => '_668'], ['a', 'b', 'c'], null, null, false, false, null]], + 38291 => [[['_route' => '_712'], ['a', 'b', 'c'], null, null, false, false, null]], + 38338 => [[['_route' => '_863'], ['a', 'b', 'c'], null, null, false, false, null]], + 38387 => [[['_route' => '_801'], ['a', 'b', 'c'], null, null, false, false, null]], + 38440 => [[['_route' => '_709'], ['a', 'b', 'c'], null, null, false, false, null]], + 38488 => [[['_route' => '_850'], ['a', 'b', 'c'], null, null, false, false, null]], + 38536 => [[['_route' => '_918'], ['a', 'b', 'c'], null, null, false, false, null]], + 38586 => [[['_route' => '_803'], ['a', 'b', 'c'], null, null, false, false, null]], + 38638 => [[['_route' => '_864'], ['a', 'b', 'c'], null, null, false, false, null]], + 38686 => [[['_route' => '_880'], ['a', 'b', 'c'], null, null, false, false, null]], + 38734 => [[['_route' => '_927'], ['a', 'b', 'c'], null, null, false, false, null]], + 38787 => [[['_route' => '_930'], ['a', 'b', 'c'], null, null, false, false, null]], + 38835 => [[['_route' => '_951'], ['a', 'b', 'c'], null, null, false, false, null]], + 38883 => [[['_route' => '_963'], ['a', 'b', 'c'], null, null, false, false, null]], + 38942 => [[['_route' => '_519'], ['a', 'b', 'c'], null, null, false, false, null]], + 38990 => [[['_route' => '_823'], ['a', 'b', 'c'], null, null, false, false, null]], + 39038 => [[['_route' => '_954'], ['a', 'b', 'c'], null, null, false, false, null]], + 39091 => [[['_route' => '_525'], ['a', 'b', 'c'], null, null, false, false, null]], + 39139 => [[['_route' => '_991'], ['a', 'b', 'c'], null, null, false, false, null]], + 39189 => [[['_route' => '_536'], ['a', 'b', 'c'], null, null, false, false, null]], + 39241 => [[['_route' => '_545'], ['a', 'b', 'c'], null, null, false, false, null]], + 39289 => [[['_route' => '_944'], ['a', 'b', 'c'], null, null, false, false, null]], + 39342 => [[['_route' => '_557'], ['a', 'b', 'c'], null, null, false, false, null]], + 39390 => [[['_route' => '_783'], ['a', 'b', 'c'], null, null, false, false, null]], + 39438 => [[['_route' => '_807'], ['a', 'b', 'c'], null, null, false, false, null]], + 39491 => [[['_route' => '_586'], ['a', 'b', 'c'], null, null, false, false, null]], + 39539 => [[['_route' => '_711'], ['a', 'b', 'c'], null, null, false, false, null]], + 39592 => [[['_route' => '_598'], ['a', 'b', 'c'], null, null, false, false, null]], + 39640 => [[['_route' => '_635'], ['a', 'b', 'c'], null, null, false, false, null]], + 39688 => [[['_route' => '_983'], ['a', 'b', 'c'], null, null, false, false, null]], + 39741 => [[['_route' => '_634'], ['a', 'b', 'c'], null, null, false, false, null]], + 39789 => [[['_route' => '_641'], ['a', 'b', 'c'], null, null, false, false, null]], + 39840 => [[['_route' => '_779'], ['a', 'b', 'c'], null, null, false, false, null]], + 39887 => [[['_route' => '_876'], ['a', 'b', 'c'], null, null, false, false, null]], + 39936 => [[['_route' => '_811'], ['a', 'b', 'c'], null, null, false, false, null]], + 39984 => [[['_route' => '_824'], ['a', 'b', 'c'], null, null, false, false, null]], + 40037 => [[['_route' => '_660'], ['a', 'b', 'c'], null, null, false, false, null]], + 40085 => [[['_route' => '_789'], ['a', 'b', 'c'], null, null, false, false, null]], + 40138 => [[['_route' => '_733'], ['a', 'b', 'c'], null, null, false, false, null]], + 40186 => [[['_route' => '_735'], ['a', 'b', 'c'], null, null, false, false, null]], + 40234 => [[['_route' => '_882'], ['a', 'b', 'c'], null, null, false, false, null]], + 40282 => [[['_route' => '_967'], ['a', 'b', 'c'], null, null, false, false, null]], + 40332 => [[['_route' => '_736'], ['a', 'b', 'c'], null, null, false, false, null]], + 40381 => [[['_route' => '_753'], ['a', 'b', 'c'], null, null, false, false, null]], + 40430 => [[['_route' => '_786'], ['a', 'b', 'c'], null, null, false, false, null]], + 40479 => [[['_route' => '_907'], ['a', 'b', 'c'], null, null, false, false, null]], + 40528 => [[['_route' => '_920'], ['a', 'b', 'c'], null, null, false, false, null]], + 40577 => [[['_route' => '_971'], ['a', 'b', 'c'], null, null, false, false, null]], + 40635 => [[['_route' => '_520'], ['a', 'b', 'c'], null, null, false, false, null]], + 40683 => [[['_route' => '_891'], ['a', 'b', 'c'], null, null, false, false, null]], + 40739 => [[['_route' => '_534'], ['a', 'b', 'c'], null, null, false, false, null]], + 40785 => [[['_route' => '_602'], ['a', 'b', 'c'], null, null, false, false, null]], + 40834 => [[['_route' => '_605'], ['a', 'b', 'c'], null, null, false, false, null]], + 40882 => [[['_route' => '_979'], ['a', 'b', 'c'], null, null, false, false, null]], + 40932 => [[['_route' => '_547'], ['a', 'b', 'c'], null, null, false, false, null]], + 40987 => [[['_route' => '_549'], ['a', 'b', 'c'], null, null, false, false, null]], + 41034 => [[['_route' => '_755'], ['a', 'b', 'c'], null, null, false, false, null]], + 41083 => [[['_route' => '_922'], ['a', 'b', 'c'], null, null, false, false, null]], + 41131 => [[['_route' => '_977'], ['a', 'b', 'c'], null, null, false, false, null]], + 41184 => [[['_route' => '_565'], ['a', 'b', 'c'], null, null, false, false, null]], + 41232 => [[['_route' => '_926'], ['a', 'b', 'c'], null, null, false, false, null]], + 41282 => [[['_route' => '_571'], ['a', 'b', 'c'], null, null, false, false, null]], + 41331 => [[['_route' => '_581'], ['a', 'b', 'c'], null, null, false, false, null]], + 41380 => [[['_route' => '_619'], ['a', 'b', 'c'], null, null, false, false, null]], + 41429 => [[['_route' => '_636'], ['a', 'b', 'c'], null, null, false, false, null]], + 41481 => [[['_route' => '_679'], ['a', 'b', 'c'], null, null, false, false, null]], + 41529 => [[['_route' => '_866'], ['a', 'b', 'c'], null, null, false, false, null]], + 41577 => [[['_route' => '_973'], ['a', 'b', 'c'], null, null, false, false, null]], + 41630 => [[['_route' => '_690'], ['a', 'b', 'c'], null, null, false, false, null]], + 41678 => [[['_route' => '_775'], ['a', 'b', 'c'], null, null, false, false, null]], + 41731 => [[['_route' => '_722'], ['a', 'b', 'c'], null, null, false, false, null]], + 41779 => [[['_route' => '_906'], ['a', 'b', 'c'], null, null, false, false, null]], + 41827 => [[['_route' => '_946'], ['a', 'b', 'c'], null, null, false, false, null]], + 41877 => [[['_route' => '_788'], ['a', 'b', 'c'], null, null, false, false, null]], + 41929 => [[['_route' => '_828'], ['a', 'b', 'c'], null, null, false, false, null]], + 41977 => [[['_route' => '_892'], ['a', 'b', 'c'], null, null, false, false, null]], + 42025 => [[['_route' => '_972'], ['a', 'b', 'c'], null, null, false, false, null]], + 42075 => [[['_route' => '_829'], ['a', 'b', 'c'], null, null, false, false, null]], + 42127 => [[['_route' => '_923'], ['a', 'b', 'c'], null, null, false, false, null]], + 42175 => [[['_route' => '_947'], ['a', 'b', 'c'], null, null, false, false, null]], + 42234 => [[['_route' => '_526'], ['a', 'b', 'c'], null, null, false, false, null]], + 42282 => [[['_route' => '_614'], ['a', 'b', 'c'], null, null, false, false, null]], + 42330 => [[['_route' => '_621'], ['a', 'b', 'c'], null, null, false, false, null]], + 42383 => [[['_route' => '_543'], ['a', 'b', 'c'], null, null, false, false, null]], + 42431 => [[['_route' => '_812'], ['a', 'b', 'c'], null, null, false, false, null]], + 42487 => [[['_route' => '_548'], ['a', 'b', 'c'], null, null, false, false, null]], + 42534 => [[['_route' => '_747'], ['a', 'b', 'c'], null, null, false, false, null]], + 42583 => [[['_route' => '_715'], ['a', 'b', 'c'], null, null, false, false, null]], + 42631 => [[['_route' => '_940'], ['a', 'b', 'c'], null, null, false, false, null]], + 42684 => [[['_route' => '_563'], ['a', 'b', 'c'], null, null, false, false, null]], + 42732 => [[['_route' => '_611'], ['a', 'b', 'c'], null, null, false, false, null]], + 42780 => [[['_route' => '_830'], ['a', 'b', 'c'], null, null, false, false, null]], + 42833 => [[['_route' => '_569'], ['a', 'b', 'c'], null, null, false, false, null]], + 42881 => [[['_route' => '_908'], ['a', 'b', 'c'], null, null, false, false, null]], + 42929 => [[['_route' => '_913'], ['a', 'b', 'c'], null, null, false, false, null]], + 42982 => [[['_route' => '_644'], ['a', 'b', 'c'], null, null, false, false, null]], + 43030 => [[['_route' => '_776'], ['a', 'b', 'c'], null, null, false, false, null]], + 43078 => [[['_route' => '_856'], ['a', 'b', 'c'], null, null, false, false, null]], + 43131 => [[['_route' => '_650'], ['a', 'b', 'c'], null, null, false, false, null]], + 43179 => [[['_route' => '_761'], ['a', 'b', 'c'], null, null, false, false, null]], + 43232 => [[['_route' => '_663'], ['a', 'b', 'c'], null, null, false, false, null]], + 43280 => [[['_route' => '_754'], ['a', 'b', 'c'], null, null, false, false, null]], + 43333 => [[['_route' => '_665'], ['a', 'b', 'c'], null, null, false, false, null]], + 43381 => [[['_route' => '_805'], ['a', 'b', 'c'], null, null, false, false, null]], + 43429 => [[['_route' => '_846'], ['a', 'b', 'c'], null, null, false, false, null]], + 43477 => [[['_route' => '_857'], ['a', 'b', 'c'], null, null, false, false, null]], + 43530 => [[['_route' => '_675'], ['a', 'b', 'c'], null, null, false, false, null]], + 43578 => [[['_route' => '_839'], ['a', 'b', 'c'], null, null, false, false, null]], + 43626 => [[['_route' => '_968'], ['a', 'b', 'c'], null, null, false, false, null]], + 43676 => [[['_route' => '_697'], ['a', 'b', 'c'], null, null, false, false, null]], + 43728 => [[['_route' => '_725'], ['a', 'b', 'c'], null, null, false, false, null]], + 43776 => [[['_route' => '_794'], ['a', 'b', 'c'], null, null, false, false, null]], + 43829 => [[['_route' => '_773'], ['a', 'b', 'c'], null, null, false, false, null]], + 43877 => [[['_route' => '_992'], ['a', 'b', 'c'], null, null, false, false, null]], + 43930 => [[['_route' => '_901'], ['a', 'b', 'c'], null, null, false, false, null]], + 43978 => [[['_route' => '_970'], ['a', 'b', 'c'], null, null, false, false, null]], + 44028 => [[['_route' => '_964'], ['a', 'b', 'c'], null, null, false, false, null]], + 44086 => [[['_route' => '_530'], ['a', 'b', 'c'], null, null, false, false, null]], + 44134 => [[['_route' => '_703'], ['a', 'b', 'c'], null, null, false, false, null]], + 44187 => [[['_route' => '_533'], ['a', 'b', 'c'], null, null, false, false, null]], + 44235 => [[['_route' => '_739'], ['a', 'b', 'c'], null, null, false, false, null]], + 44283 => [[['_route' => '_791'], ['a', 'b', 'c'], null, null, false, false, null]], + 44331 => [[['_route' => '_987'], ['a', 'b', 'c'], null, null, false, false, null]], + 44384 => [[['_route' => '_566'], ['a', 'b', 'c'], null, null, false, false, null]], + 44432 => [[['_route' => '_592'], ['a', 'b', 'c'], null, null, false, false, null]], + 44488 => [[['_route' => '_568'], ['a', 'b', 'c'], null, null, false, false, null]], + 44534 => [[['_route' => '_868'], ['a', 'b', 'c'], null, null, false, false, null]], + 44583 => [[['_route' => '_878'], ['a', 'b', 'c'], null, null, false, false, null]], + 44636 => [[['_route' => '_588'], ['a', 'b', 'c'], null, null, false, false, null]], + 44684 => [[['_route' => '_793'], ['a', 'b', 'c'], null, null, false, false, null]], + 44732 => [[['_route' => '_917'], ['a', 'b', 'c'], null, null, false, false, null]], + 44785 => [[['_route' => '_600'], ['a', 'b', 'c'], null, null, false, false, null]], + 44833 => [[['_route' => '_728'], ['a', 'b', 'c'], null, null, false, false, null]], + 44886 => [[['_route' => '_603'], ['a', 'b', 'c'], null, null, false, false, null]], + 44934 => [[['_route' => '_765'], ['a', 'b', 'c'], null, null, false, false, null]], + 44987 => [[['_route' => '_607'], ['a', 'b', 'c'], null, null, false, false, null]], + 45035 => [[['_route' => '_676'], ['a', 'b', 'c'], null, null, false, false, null]], + 45083 => [[['_route' => '_804'], ['a', 'b', 'c'], null, null, false, false, null]], + 45136 => [[['_route' => '_609'], ['a', 'b', 'c'], null, null, false, false, null]], + 45184 => [[['_route' => '_961'], ['a', 'b', 'c'], null, null, false, false, null]], + 45232 => [[['_route' => '_980'], ['a', 'b', 'c'], null, null, false, false, null]], + 45282 => [[['_route' => '_714'], ['a', 'b', 'c'], null, null, false, false, null]], + 45334 => [[['_route' => '_730'], ['a', 'b', 'c'], null, null, false, false, null]], + 45382 => [[['_route' => '_806'], ['a', 'b', 'c'], null, null, false, false, null]], + 45430 => [[['_route' => '_825'], ['a', 'b', 'c'], null, null, false, false, null]], + 45478 => [[['_route' => '_879'], ['a', 'b', 'c'], null, null, false, false, null]], + 45526 => [[['_route' => '_893'], ['a', 'b', 'c'], null, null, false, false, null]], + 45576 => [[['_route' => '_928'], ['a', 'b', 'c'], null, null, false, false, null]], + 45628 => [[['_route' => '_932'], ['a', 'b', 'c'], null, null, false, false, null]], + 45676 => [[['_route' => '_958'], ['a', 'b', 'c'], null, null, false, false, null]], + 45726 => [[['_route' => '_984'], ['a', 'b', 'c'], null, null, false, false, null]], + 45784 => [[['_route' => '_538'], ['a', 'b', 'c'], null, null, false, false, null]], + 45832 => [[['_route' => '_993'], ['a', 'b', 'c'], null, null, false, false, null]], + 45882 => [[['_route' => '_542'], ['a', 'b', 'c'], null, null, false, false, null]], + 45934 => [[['_route' => '_551'], ['a', 'b', 'c'], null, null, false, false, null]], + 45982 => [[['_route' => '_687'], ['a', 'b', 'c'], null, null, false, false, null]], + 46030 => [[['_route' => '_724'], ['a', 'b', 'c'], null, null, false, false, null]], + 46078 => [[['_route' => '_925'], ['a', 'b', 'c'], null, null, false, false, null]], + 46131 => [[['_route' => '_587'], ['a', 'b', 'c'], null, null, false, false, null]], + 46179 => [[['_route' => '_914'], ['a', 'b', 'c'], null, null, false, false, null]], + 46229 => [[['_route' => '_616'], ['a', 'b', 'c'], null, null, false, false, null]], + 46284 => [[['_route' => '_677'], ['a', 'b', 'c'], null, null, false, false, null]], + 46331 => [[['_route' => '_815'], ['a', 'b', 'c'], null, null, false, false, null]], + 46380 => [[['_route' => '_781'], ['a', 'b', 'c'], null, null, false, false, null]], + 46430 => [[['_route' => '_717'], ['a', 'b', 'c'], null, null, false, false, null]], + 46482 => [[['_route' => '_782'], ['a', 'b', 'c'], null, null, false, false, null]], + 46530 => [[['_route' => '_832'], ['a', 'b', 'c'], null, null, false, false, null]], + 46583 => [[['_route' => '_795'], ['a', 'b', 'c'], null, null, false, false, null]], + 46631 => [[['_route' => '_887'], ['a', 'b', 'c'], null, null, false, false, null]], + 46681 => [[['_route' => '_800'], ['a', 'b', 'c'], null, null, false, false, null]], + 46730 => [[['_route' => '_826'], ['a', 'b', 'c'], null, null, false, false, null]], + 46779 => [[['_route' => '_881'], ['a', 'b', 'c'], null, null, false, false, null]], + 46828 => [[['_route' => '_886'], ['a', 'b', 'c'], null, null, false, false, null]], + 46877 => [[['_route' => '_938'], ['a', 'b', 'c'], null, null, false, false, null]], + 46935 => [[['_route' => '_540'], ['a', 'b', 'c'], null, null, false, false, null]], + 46983 => [[['_route' => '_643'], ['a', 'b', 'c'], null, null, false, false, null]], + 47033 => [[['_route' => '_544'], ['a', 'b', 'c'], null, null, false, false, null]], + 47082 => [[['_route' => '_552'], ['a', 'b', 'c'], null, null, false, false, null]], + 47134 => [[['_route' => '_567'], ['a', 'b', 'c'], null, null, false, false, null]], + 47182 => [[['_route' => '_608'], ['a', 'b', 'c'], null, null, false, false, null]], + 47230 => [[['_route' => '_698'], ['a', 'b', 'c'], null, null, false, false, null]], + 47278 => [[['_route' => '_988'], ['a', 'b', 'c'], null, null, false, false, null]], + 47331 => [[['_route' => '_583'], ['a', 'b', 'c'], null, null, false, false, null]], + 47379 => [[['_route' => '_998'], ['a', 'b', 'c'], null, null, false, false, null]], + 47432 => [[['_route' => '_604'], ['a', 'b', 'c'], null, null, false, false, null]], + 47480 => [[['_route' => '_630'], ['a', 'b', 'c'], null, null, false, false, null]], + 47528 => [[['_route' => '_706'], ['a', 'b', 'c'], null, null, false, false, null]], + 47576 => [[['_route' => '_976'], ['a', 'b', 'c'], null, null, false, false, null]], + 47629 => [[['_route' => '_673'], ['a', 'b', 'c'], null, null, false, false, null]], + 47677 => [[['_route' => '_678'], ['a', 'b', 'c'], null, null, false, false, null]], + 47725 => [[['_route' => '_931'], ['a', 'b', 'c'], null, null, false, false, null]], + 47775 => [[['_route' => '_751'], ['a', 'b', 'c'], null, null, false, false, null]], + 47824 => [[['_route' => '_766'], ['a', 'b', 'c'], null, null, false, false, null]], + 47876 => [[['_route' => '_792'], ['a', 'b', 'c'], null, null, false, false, null]], + 47924 => [[['_route' => '_814'], ['a', 'b', 'c'], null, null, false, false, null]], + 47974 => [[['_route' => '_798'], ['a', 'b', 'c'], null, null, false, false, null]], + 48026 => [[['_route' => '_851'], ['a', 'b', 'c'], null, null, false, false, null]], + 48074 => [[['_route' => '_941'], ['a', 'b', 'c'], null, null, false, false, null]], + 48122 => [[['_route' => '_953'], ['a', 'b', 'c'], null, null, false, false, null]], + 48170 => [[['_route' => '_975'], ['a', 'b', 'c'], null, null, false, false, null]], + 48220 => [[['_route' => '_873'], ['a', 'b', 'c'], null, null, false, false, null]], + 48269 => [[['_route' => '_936'], ['a', 'b', 'c'], null, null, false, false, null]], + 48318 => [[['_route' => '_994'], ['a', 'b', 'c'], null, null, false, false, null]], + 48376 => [[['_route' => '_562'], ['a', 'b', 'c'], null, null, false, false, null]], + 48424 => [[['_route' => '_770'], ['a', 'b', 'c'], null, null, false, false, null]], + 48475 => [[['_route' => '_774'], ['a', 'b', 'c'], null, null, false, false, null]], + 48522 => [[['_route' => '_966'], ['a', 'b', 'c'], null, null, false, false, null]], + 48573 => [[['_route' => '_582'], ['a', 'b', 'c'], null, null, false, false, null]], + 48625 => [[['_route' => '_606'], ['a', 'b', 'c'], null, null, false, false, null]], + 48673 => [[['_route' => '_648'], ['a', 'b', 'c'], null, null, false, false, null]], + 48723 => [[['_route' => '_624'], ['a', 'b', 'c'], null, null, false, false, null]], + 48775 => [[['_route' => '_626'], ['a', 'b', 'c'], null, null, false, false, null]], + 48823 => [[['_route' => '_821'], ['a', 'b', 'c'], null, null, false, false, null]], + 48873 => [[['_route' => '_628'], ['a', 'b', 'c'], null, null, false, false, null]], + 48922 => [[['_route' => '_638'], ['a', 'b', 'c'], null, null, false, false, null]], + 48974 => [[['_route' => '_640'], ['a', 'b', 'c'], null, null, false, false, null]], + 49022 => [[['_route' => '_990'], ['a', 'b', 'c'], null, null, false, false, null]], + 49072 => [[['_route' => '_705'], ['a', 'b', 'c'], null, null, false, false, null]], + 49121 => [[['_route' => '_757'], ['a', 'b', 'c'], null, null, false, false, null]], + 49176 => [[['_route' => '_785'], ['a', 'b', 'c'], null, null, false, false, null]], + 49223 => [[['_route' => '_875'], ['a', 'b', 'c'], null, null, false, false, null]], + 49270 => [[['_route' => '_894'], ['a', 'b', 'c'], null, null, false, false, null]], + 49319 => [[['_route' => '_945'], ['a', 'b', 'c'], null, null, false, false, null]], + 49375 => [[['_route' => '_816'], ['a', 'b', 'c'], null, null, false, false, null]], + 49422 => [[['_route' => '_872'], ['a', 'b', 'c'], null, null, false, false, null]], + 49471 => [[['_route' => '_921'], ['a', 'b', 'c'], null, null, false, false, null]], + 49519 => [[['_route' => '_960'], ['a', 'b', 'c'], null, null, false, false, null]], + 49567 => [[['_route' => '_974'], ['a', 'b', 'c'], null, null, false, false, null]], + 49620 => [[['_route' => '_835'], ['a', 'b', 'c'], null, null, false, false, null]], + 49668 => [[['_route' => '_934'], ['a', 'b', 'c'], null, null, false, false, null]], + 49718 => [ + [['_route' => '_869'], ['a', 'b', 'c'], null, null, false, false, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher11.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher11.php new file mode 100644 index 000000000000..dc0e5f5545eb --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher11.php @@ -0,0 +1,64 @@ + '{^(?' + .'|/(en|fr)/(?' + .'|admin/post(?' + .'|(*:32)' + .'|/(?' + .'|new(*:46)' + .'|(\\d+)(*:58)' + .'|(\\d+)/edit(*:75)' + .'|(\\d+)/delete(*:94)' + .')' + .')' + .'|blog(?' + .'|(*:110)' + .'|/(?' + .'|rss\\.xml(*:130)' + .'|p(?' + .'|age/([^/]++)(*:154)' + .'|osts/([^/]++)(*:175)' + .')' + .'|comments/(\\d+)/new(*:202)' + .'|search(*:216)' + .')' + .')' + .'|log(?' + .'|in(*:234)' + .'|out(*:245)' + .')' + .')' + .'|/(en|fr)?(*:264)' + .')/?$}sD', + ], + [ // $dynamicRoutes + 32 => [[['_route' => 'a', '_locale' => 'en'], ['_locale'], null, null, true, false, null]], + 46 => [[['_route' => 'b', '_locale' => 'en'], ['_locale'], null, null, false, false, null]], + 58 => [[['_route' => 'c', '_locale' => 'en'], ['_locale', 'id'], null, null, false, true, null]], + 75 => [[['_route' => 'd', '_locale' => 'en'], ['_locale', 'id'], null, null, false, false, null]], + 94 => [[['_route' => 'e', '_locale' => 'en'], ['_locale', 'id'], null, null, false, false, null]], + 110 => [[['_route' => 'f', '_locale' => 'en'], ['_locale'], null, null, true, false, null]], + 130 => [[['_route' => 'g', '_locale' => 'en'], ['_locale'], null, null, false, false, null]], + 154 => [[['_route' => 'h', '_locale' => 'en'], ['_locale', 'page'], null, null, false, true, null]], + 175 => [[['_route' => 'i', '_locale' => 'en'], ['_locale', 'page'], null, null, false, true, null]], + 202 => [[['_route' => 'j', '_locale' => 'en'], ['_locale', 'id'], null, null, false, false, null]], + 216 => [[['_route' => 'k', '_locale' => 'en'], ['_locale'], null, null, false, false, null]], + 234 => [[['_route' => 'l', '_locale' => 'en'], ['_locale'], null, null, false, false, null]], + 245 => [[['_route' => 'm', '_locale' => 'en'], ['_locale'], null, null, false, false, null]], + 264 => [ + [['_route' => 'n', '_locale' => 'en'], ['_locale'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher12.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher12.php new file mode 100644 index 000000000000..a675d84a4327 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher12.php @@ -0,0 +1,44 @@ + '{^(?' + .'|/abc([^/]++)/(?' + .'|1(?' + .'|(*:27)' + .'|0(?' + .'|(*:38)' + .'|0(*:46)' + .')' + .')' + .'|2(?' + .'|(*:59)' + .'|0(?' + .'|(*:70)' + .'|0(*:78)' + .')' + .')' + .')' + .')/?$}sD', + ], + [ // $dynamicRoutes + 27 => [[['_route' => 'r1'], ['foo'], null, null, false, false, null]], + 38 => [[['_route' => 'r10'], ['foo'], null, null, false, false, null]], + 46 => [[['_route' => 'r100'], ['foo'], null, null, false, false, null]], + 59 => [[['_route' => 'r2'], ['foo'], null, null, false, false, null]], + 70 => [[['_route' => 'r20'], ['foo'], null, null, false, false, null]], + 78 => [ + [['_route' => 'r200'], ['foo'], null, null, false, false, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher13.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher13.php new file mode 100644 index 000000000000..63252943df31 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher13.php @@ -0,0 +1,29 @@ + '{^(?' + .'|(?i:([^\\.]++)\\.exampple\\.com)\\.(?' + .'|/abc([^/]++)(?' + .'|(*:56)' + .')' + .')' + .')/?$}sD', + ], + [ // $dynamicRoutes + 56 => [ + [['_route' => 'r1'], ['foo', 'foo'], null, null, false, true, null], + [['_route' => 'r2'], ['foo', 'foo'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher2.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher2.php new file mode 100644 index 000000000000..13629954a8d1 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher2.php @@ -0,0 +1,110 @@ + [[['_route' => 'baz'], null, null, null, false, false, null]], + '/test/baz.html' => [[['_route' => 'baz2'], null, null, null, false, false, null]], + '/test/baz3' => [[['_route' => 'baz3'], null, null, null, true, false, null]], + '/foofoo' => [[['_route' => 'foofoo', 'def' => 'test'], null, null, null, false, false, null]], + '/spa ce' => [[['_route' => 'space'], null, null, null, false, false, null]], + '/multi/new' => [[['_route' => 'overridden2'], null, null, null, false, false, null]], + '/multi/hey' => [[['_route' => 'hey'], null, null, null, true, false, null]], + '/ababa' => [[['_route' => 'ababa'], null, null, null, false, false, null]], + '/route1' => [[['_route' => 'route1'], 'a.example.com', null, null, false, false, null]], + '/c2/route2' => [[['_route' => 'route2'], 'a.example.com', null, null, false, false, null]], + '/route4' => [[['_route' => 'route4'], 'a.example.com', null, null, false, false, null]], + '/c2/route3' => [[['_route' => 'route3'], 'b.example.com', null, null, false, false, null]], + '/route5' => [[['_route' => 'route5'], 'c.example.com', null, null, false, false, null]], + '/route6' => [[['_route' => 'route6'], null, null, null, false, false, null]], + '/route11' => [[['_route' => 'route11'], '#^(?P[^\\.]++)\\.example\\.com$#sDi', null, null, false, false, null]], + '/route12' => [[['_route' => 'route12', 'var1' => 'val'], '#^(?P[^\\.]++)\\.example\\.com$#sDi', null, null, false, false, null]], + '/route17' => [[['_route' => 'route17'], null, null, null, false, false, null]], + '/secure' => [[['_route' => 'secure'], null, null, ['https' => 0], false, false, null]], + '/nonsecure' => [[['_route' => 'nonsecure'], null, null, ['http' => 0], false, false, null]], + ], + [ // $regexpList + 0 => '{^(?' + .'|(?:(?:[^./]*+\\.)++)(?' + .'|/foo/(baz|symfony)(*:47)' + .'|/bar(?' + .'|/([^/]++)(*:70)' + .'|head/([^/]++)(*:90)' + .')' + .'|/test/([^/]++)(?' + .'|(*:115)' + .')' + .'|/([\']+)(*:131)' + .'|/a/(?' + .'|b\'b/([^/]++)(?' + .'|(*:160)' + .'|(*:168)' + .')' + .'|(.*)(*:181)' + .'|b\'b/([^/]++)(?' + .'|(*:204)' + .'|(*:212)' + .')' + .')' + .'|/multi/hello(?:/([^/]++))?(*:248)' + .'|/([^/]++)/b/([^/]++)(?' + .'|(*:279)' + .'|(*:287)' + .')' + .'|/aba/([^/]++)(*:309)' + .')|(?i:([^\\.]++)\\.example\\.com)\\.(?' + .'|/route1(?' + .'|3/([^/]++)(*:371)' + .'|4/([^/]++)(*:389)' + .')' + .')|(?i:c\\.example\\.com)\\.(?' + .'|/route15/([^/]++)(*:441)' + .')|(?:(?:[^./]*+\\.)++)(?' + .'|/route16/([^/]++)(*:489)' + .'|/a/(?' + .'|a\\.\\.\\.(*:510)' + .'|b/(?' + .'|([^/]++)(*:531)' + .'|c/([^/]++)(*:549)' + .')' + .')' + .')' + .')/?$}sD', + ], + [ // $dynamicRoutes + 47 => [[['_route' => 'foo', 'def' => 'test'], ['bar'], null, null, false, true, null]], + 70 => [[['_route' => 'bar'], ['foo'], ['GET' => 0, 'HEAD' => 1], null, false, true, null]], + 90 => [[['_route' => 'barhead'], ['foo'], ['GET' => 0], null, false, true, null]], + 115 => [ + [['_route' => 'baz4'], ['foo'], null, null, true, true, null], + [['_route' => 'baz5'], ['foo'], ['POST' => 0], null, true, true, null], + [['_route' => 'baz.baz6'], ['foo'], ['PUT' => 0], null, true, true, null], + ], + 131 => [[['_route' => 'quoter'], ['quoter'], null, null, false, true, null]], + 160 => [[['_route' => 'foo1'], ['foo'], ['PUT' => 0], null, false, true, null]], + 168 => [[['_route' => 'bar1'], ['bar'], null, null, false, true, null]], + 181 => [[['_route' => 'overridden'], ['var'], null, null, false, true, null]], + 204 => [[['_route' => 'foo2'], ['foo1'], null, null, false, true, null]], + 212 => [[['_route' => 'bar2'], ['bar1'], null, null, false, true, null]], + 248 => [[['_route' => 'helloWorld', 'who' => 'World!'], ['who'], null, null, false, true, null]], + 279 => [[['_route' => 'foo3'], ['_locale', 'foo'], null, null, false, true, null]], + 287 => [[['_route' => 'bar3'], ['_locale', 'bar'], null, null, false, true, null]], + 309 => [[['_route' => 'foo4'], ['foo'], null, null, false, true, null]], + 371 => [[['_route' => 'route13'], ['var1', 'name'], null, null, false, true, null]], + 389 => [[['_route' => 'route14', 'var1' => 'val'], ['var1', 'name'], null, null, false, true, null]], + 441 => [[['_route' => 'route15'], ['name'], null, null, false, true, null]], + 489 => [[['_route' => 'route16', 'var1' => 'val'], ['name'], null, null, false, true, null]], + 510 => [[['_route' => 'a'], [], null, null, false, false, null]], + 531 => [[['_route' => 'b'], ['var'], null, null, false, true, null]], + 549 => [ + [['_route' => 'c'], ['var'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher3.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher3.php new file mode 100644 index 000000000000..4fe52b3c83ca --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher3.php @@ -0,0 +1,30 @@ + [[['_route' => 'static'], null, null, null, false, false, null]], + '/with-condition' => [[['_route' => 'with-condition'], null, null, null, false, false, -1]], + ], + [ // $regexpList + 0 => '{^(?' + .'|/rootprefix/([^/]++)(*:27)' + .')/?$}sD', + ], + [ // $dynamicRoutes + 27 => [ + [['_route' => 'dynamic'], ['var'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ], + static function ($condition, $context, $request) { // $checkCondition + switch ($condition) { + case -1: return ($context->getMethod() == "GET"); + } + }, +]; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher4.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher4.php new file mode 100644 index 000000000000..d0a354a93e63 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher4.php @@ -0,0 +1,25 @@ + [[['_route' => 'just_head'], null, ['HEAD' => 0], null, false, false, null]], + '/head_and_get' => [[['_route' => 'head_and_get'], null, ['HEAD' => 0, 'GET' => 1], null, false, false, null]], + '/get_and_head' => [[['_route' => 'get_and_head'], null, ['GET' => 0, 'HEAD' => 1], null, false, false, null]], + '/post_and_head' => [[['_route' => 'post_and_head'], null, ['POST' => 0, 'HEAD' => 1], null, false, false, null]], + '/put_and_post' => [ + [['_route' => 'put_and_post'], null, ['PUT' => 0, 'POST' => 1], null, false, false, null], + [['_route' => 'put_and_get_and_head'], null, ['PUT' => 0, 'GET' => 1, 'HEAD' => 2], null, false, false, null], + ], + ], + [ // $regexpList + ], + [ // $dynamicRoutes + ], + null, // $checkCondition +]; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher5.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher5.php new file mode 100644 index 000000000000..35c650978e1a --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher5.php @@ -0,0 +1,38 @@ + [[['_route' => 'a_first'], null, null, null, false, false, null]], + '/a/22' => [[['_route' => 'a_second'], null, null, null, false, false, null]], + '/a/333' => [[['_route' => 'a_third'], null, null, null, false, false, null]], + '/a/44' => [[['_route' => 'a_fourth'], null, null, null, true, false, null]], + '/a/55' => [[['_route' => 'a_fifth'], null, null, null, true, false, null]], + '/a/66' => [[['_route' => 'a_sixth'], null, null, null, true, false, null]], + '/nested/group/a' => [[['_route' => 'nested_a'], null, null, null, true, false, null]], + '/nested/group/b' => [[['_route' => 'nested_b'], null, null, null, true, false, null]], + '/nested/group/c' => [[['_route' => 'nested_c'], null, null, null, true, false, null]], + '/slashed/group' => [[['_route' => 'slashed_a'], null, null, null, true, false, null]], + '/slashed/group/b' => [[['_route' => 'slashed_b'], null, null, null, true, false, null]], + '/slashed/group/c' => [[['_route' => 'slashed_c'], null, null, null, true, false, null]], + ], + [ // $regexpList + 0 => '{^(?' + .'|/([^/]++)(*:16)' + .'|/nested/([^/]++)(*:39)' + .')/?$}sD', + ], + [ // $dynamicRoutes + 16 => [[['_route' => 'a_wildcard'], ['param'], null, null, false, true, null]], + 39 => [ + [['_route' => 'nested_wildcard'], ['param'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher6.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher6.php new file mode 100644 index 000000000000..571e288a8f95 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher6.php @@ -0,0 +1,50 @@ + [[['_route' => 'simple_trailing_slash_no_methods'], null, null, null, true, false, null]], + '/trailing/simple/get-method' => [[['_route' => 'simple_trailing_slash_GET_method'], null, ['GET' => 0], null, true, false, null]], + '/trailing/simple/head-method' => [[['_route' => 'simple_trailing_slash_HEAD_method'], null, ['HEAD' => 0], null, true, false, null]], + '/trailing/simple/post-method' => [[['_route' => 'simple_trailing_slash_POST_method'], null, ['POST' => 0], null, true, false, null]], + '/not-trailing/simple/no-methods' => [[['_route' => 'simple_not_trailing_slash_no_methods'], null, null, null, false, false, null]], + '/not-trailing/simple/get-method' => [[['_route' => 'simple_not_trailing_slash_GET_method'], null, ['GET' => 0], null, false, false, null]], + '/not-trailing/simple/head-method' => [[['_route' => 'simple_not_trailing_slash_HEAD_method'], null, ['HEAD' => 0], null, false, false, null]], + '/not-trailing/simple/post-method' => [[['_route' => 'simple_not_trailing_slash_POST_method'], null, ['POST' => 0], null, false, false, null]], + ], + [ // $regexpList + 0 => '{^(?' + .'|/trailing/regex/(?' + .'|no\\-methods/([^/]++)(*:46)' + .'|get\\-method/([^/]++)(*:73)' + .'|head\\-method/([^/]++)(*:101)' + .'|post\\-method/([^/]++)(*:130)' + .')' + .'|/not\\-trailing/regex/(?' + .'|no\\-methods/([^/]++)(*:183)' + .'|get\\-method/([^/]++)(*:211)' + .'|head\\-method/([^/]++)(*:240)' + .'|post\\-method/([^/]++)(*:269)' + .')' + .')/?$}sD', + ], + [ // $dynamicRoutes + 46 => [[['_route' => 'regex_trailing_slash_no_methods'], ['param'], null, null, true, true, null]], + 73 => [[['_route' => 'regex_trailing_slash_GET_method'], ['param'], ['GET' => 0], null, true, true, null]], + 101 => [[['_route' => 'regex_trailing_slash_HEAD_method'], ['param'], ['HEAD' => 0], null, true, true, null]], + 130 => [[['_route' => 'regex_trailing_slash_POST_method'], ['param'], ['POST' => 0], null, true, true, null]], + 183 => [[['_route' => 'regex_not_trailing_slash_no_methods'], ['param'], null, null, false, true, null]], + 211 => [[['_route' => 'regex_not_trailing_slash_GET_method'], ['param'], ['GET' => 0], null, false, true, null]], + 240 => [[['_route' => 'regex_not_trailing_slash_HEAD_method'], ['param'], ['HEAD' => 0], null, false, true, null]], + 269 => [ + [['_route' => 'regex_not_trailing_slash_POST_method'], ['param'], ['POST' => 0], null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher7.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher7.php new file mode 100644 index 000000000000..571e288a8f95 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher7.php @@ -0,0 +1,50 @@ + [[['_route' => 'simple_trailing_slash_no_methods'], null, null, null, true, false, null]], + '/trailing/simple/get-method' => [[['_route' => 'simple_trailing_slash_GET_method'], null, ['GET' => 0], null, true, false, null]], + '/trailing/simple/head-method' => [[['_route' => 'simple_trailing_slash_HEAD_method'], null, ['HEAD' => 0], null, true, false, null]], + '/trailing/simple/post-method' => [[['_route' => 'simple_trailing_slash_POST_method'], null, ['POST' => 0], null, true, false, null]], + '/not-trailing/simple/no-methods' => [[['_route' => 'simple_not_trailing_slash_no_methods'], null, null, null, false, false, null]], + '/not-trailing/simple/get-method' => [[['_route' => 'simple_not_trailing_slash_GET_method'], null, ['GET' => 0], null, false, false, null]], + '/not-trailing/simple/head-method' => [[['_route' => 'simple_not_trailing_slash_HEAD_method'], null, ['HEAD' => 0], null, false, false, null]], + '/not-trailing/simple/post-method' => [[['_route' => 'simple_not_trailing_slash_POST_method'], null, ['POST' => 0], null, false, false, null]], + ], + [ // $regexpList + 0 => '{^(?' + .'|/trailing/regex/(?' + .'|no\\-methods/([^/]++)(*:46)' + .'|get\\-method/([^/]++)(*:73)' + .'|head\\-method/([^/]++)(*:101)' + .'|post\\-method/([^/]++)(*:130)' + .')' + .'|/not\\-trailing/regex/(?' + .'|no\\-methods/([^/]++)(*:183)' + .'|get\\-method/([^/]++)(*:211)' + .'|head\\-method/([^/]++)(*:240)' + .'|post\\-method/([^/]++)(*:269)' + .')' + .')/?$}sD', + ], + [ // $dynamicRoutes + 46 => [[['_route' => 'regex_trailing_slash_no_methods'], ['param'], null, null, true, true, null]], + 73 => [[['_route' => 'regex_trailing_slash_GET_method'], ['param'], ['GET' => 0], null, true, true, null]], + 101 => [[['_route' => 'regex_trailing_slash_HEAD_method'], ['param'], ['HEAD' => 0], null, true, true, null]], + 130 => [[['_route' => 'regex_trailing_slash_POST_method'], ['param'], ['POST' => 0], null, true, true, null]], + 183 => [[['_route' => 'regex_not_trailing_slash_no_methods'], ['param'], null, null, false, true, null]], + 211 => [[['_route' => 'regex_not_trailing_slash_GET_method'], ['param'], ['GET' => 0], null, false, true, null]], + 240 => [[['_route' => 'regex_not_trailing_slash_HEAD_method'], ['param'], ['HEAD' => 0], null, false, true, null]], + 269 => [ + [['_route' => 'regex_not_trailing_slash_POST_method'], ['param'], ['POST' => 0], null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher8.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher8.php new file mode 100644 index 000000000000..461789590ef0 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher8.php @@ -0,0 +1,32 @@ + '{^(?' + .'|/(a)(*:11)' + .')/?$}sD', + 11 => '{^(?' + .'|/(.)(*:22)' + .')/?$}sDu', + 22 => '{^(?' + .'|/(.)(*:33)' + .')/?$}sD', + ], + [ // $dynamicRoutes + 11 => [[['_route' => 'a'], ['a'], null, null, false, true, null]], + 22 => [[['_route' => 'b'], ['a'], null, null, false, true, null]], + 33 => [ + [['_route' => 'c'], ['a'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher9.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher9.php new file mode 100644 index 000000000000..da1c8a706fd0 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/compiled_url_matcher9.php @@ -0,0 +1,22 @@ + [ + [['_route' => 'a'], '#^(?P[^\\.]++)\\.e\\.c\\.b\\.a$#sDi', null, null, false, false, null], + [['_route' => 'c'], '#^(?P[^\\.]++)\\.e\\.c\\.b\\.a$#sDi', null, null, false, false, null], + [['_route' => 'b'], 'd.c.b.a', null, null, false, false, null], + ], + ], + [ // $regexpList + ], + [ // $dynamicRoutes + ], + null, // $checkCondition +]; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher0.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher0.php index e1466356faa2..df09938d61b5 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher0.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher0.php @@ -1,6 +1,6 @@ [[['_route' => 'route16', 'var1' => 'val'], ['name'], null, null, false, true, null]], 510 => [[['_route' => 'a'], [], null, null, false, false, null]], 531 => [[['_route' => 'b'], ['var'], null, null, false, true, null]], - 549 => [[['_route' => 'c'], ['var'], null, null, false, true, null]], + 549 => [ + [['_route' => 'c'], ['var'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], ]; } } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher10.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher10.php index d93459c4c979..232030cc48d0 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher10.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher10.php @@ -1,6 +1,6 @@ [[['_route' => '_974'], ['a', 'b', 'c'], null, null, false, false, null]], 49620 => [[['_route' => '_835'], ['a', 'b', 'c'], null, null, false, false, null]], 49668 => [[['_route' => '_934'], ['a', 'b', 'c'], null, null, false, false, null]], - 49718 => [[['_route' => '_869'], ['a', 'b', 'c'], null, null, false, false, null]], + 49718 => [ + [['_route' => '_869'], ['a', 'b', 'c'], null, null, false, false, null], + [null, null, null, null, false, false, 0], + ], ]; } } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher11.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher11.php index e9ff494a0c92..c3929d6e6305 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher11.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher11.php @@ -1,6 +1,6 @@ [[['_route' => 'k', '_locale' => 'en'], ['_locale'], null, null, false, false, null]], 234 => [[['_route' => 'l', '_locale' => 'en'], ['_locale'], null, null, false, false, null]], 245 => [[['_route' => 'm', '_locale' => 'en'], ['_locale'], null, null, false, false, null]], - 264 => [[['_route' => 'n', '_locale' => 'en'], ['_locale'], null, null, false, true, null]], + 264 => [ + [['_route' => 'n', '_locale' => 'en'], ['_locale'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], ]; } } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher12.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher12.php index cd88785a07be..77e52992deca 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher12.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher12.php @@ -1,6 +1,6 @@ [[['_route' => 'r100'], ['foo'], null, null, false, false, null]], 59 => [[['_route' => 'r2'], ['foo'], null, null, false, false, null]], 70 => [[['_route' => 'r20'], ['foo'], null, null, false, false, null]], - 78 => [[['_route' => 'r200'], ['foo'], null, null, false, false, null]], + 78 => [ + [['_route' => 'r200'], ['foo'], null, null, false, false, null], + [null, null, null, null, false, false, 0], + ], ]; } } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher13.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher13.php index 310b9c55dee4..8e54cc87580e 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher13.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher13.php @@ -1,6 +1,6 @@ [ [['_route' => 'r1'], ['foo', 'foo'], null, null, false, true, null], [['_route' => 'r2'], ['foo', 'foo'], null, null, false, true, null], + [null, null, null, null, false, false, 0], ], ]; } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php index 397a68d82fb2..155882448d1e 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php @@ -1,6 +1,6 @@ [[['_route' => 'route16', 'var1' => 'val'], ['name'], null, null, false, true, null]], 510 => [[['_route' => 'a'], [], null, null, false, false, null]], 531 => [[['_route' => 'b'], ['var'], null, null, false, true, null]], - 549 => [[['_route' => 'c'], ['var'], null, null, false, true, null]], + 549 => [ + [['_route' => 'c'], ['var'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], ]; } } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php index 0792a8f3be34..efafbb24695e 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php @@ -1,6 +1,6 @@ dynamicRoutes = [ - 27 => [[['_route' => 'dynamic'], ['var'], null, null, false, true, null]], + 27 => [ + [['_route' => 'dynamic'], ['var'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], ]; $this->checkCondition = static function ($condition, $context, $request) { switch ($condition) { diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php index 4b0dc156a359..605901cda28c 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php @@ -1,6 +1,6 @@ dynamicRoutes = [ 16 => [[['_route' => 'a_wildcard'], ['param'], null, null, false, true, null]], - 39 => [[['_route' => 'nested_wildcard'], ['param'], null, null, false, true, null]], + 39 => [ + [['_route' => 'nested_wildcard'], ['param'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], ]; } } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher6.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher6.php index f99c8fe60662..850b3bb53282 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher6.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher6.php @@ -1,6 +1,6 @@ [[['_route' => 'regex_not_trailing_slash_no_methods'], ['param'], null, null, false, true, null]], 211 => [[['_route' => 'regex_not_trailing_slash_GET_method'], ['param'], ['GET' => 0], null, false, true, null]], 240 => [[['_route' => 'regex_not_trailing_slash_HEAD_method'], ['param'], ['HEAD' => 0], null, false, true, null]], - 269 => [[['_route' => 'regex_not_trailing_slash_POST_method'], ['param'], ['POST' => 0], null, false, true, null]], + 269 => [ + [['_route' => 'regex_not_trailing_slash_POST_method'], ['param'], ['POST' => 0], null, false, true, null], + [null, null, null, null, false, false, 0], + ], ]; } } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php index f44b13bce91d..3f07f80017c2 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php @@ -1,6 +1,6 @@ [[['_route' => 'regex_not_trailing_slash_no_methods'], ['param'], null, null, false, true, null]], 211 => [[['_route' => 'regex_not_trailing_slash_GET_method'], ['param'], ['GET' => 0], null, false, true, null]], 240 => [[['_route' => 'regex_not_trailing_slash_HEAD_method'], ['param'], ['HEAD' => 0], null, false, true, null]], - 269 => [[['_route' => 'regex_not_trailing_slash_POST_method'], ['param'], ['POST' => 0], null, false, true, null]], + 269 => [ + [['_route' => 'regex_not_trailing_slash_POST_method'], ['param'], ['POST' => 0], null, false, true, null], + [null, null, null, null, false, false, 0], + ], ]; } } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher8.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher8.php index ffac5d2d9252..3ae962b8edaa 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher8.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher8.php @@ -1,6 +1,6 @@ dynamicRoutes = [ 11 => [[['_route' => 'a'], ['a'], null, null, false, true, null]], 22 => [[['_route' => 'b'], ['a'], null, null, false, true, null]], - 33 => [[['_route' => 'c'], ['a'], null, null, false, true, null]], + 33 => [ + [['_route' => 'c'], ['a'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], ]; } } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher9.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher9.php index 5716496149ed..e233cd1ca953 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher9.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher9.php @@ -1,6 +1,6 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Generator\Dumper; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Routing\Generator\CompiledUrlGenerator; +use Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +class CompiledUrlGeneratorDumperTest extends TestCase +{ + /** + * @var RouteCollection + */ + private $routeCollection; + + /** + * @var CompiledUrlGeneratorDumper + */ + private $generatorDumper; + + /** + * @var string + */ + private $testTmpFilepath; + + /** + * @var string + */ + private $largeTestTmpFilepath; + + protected function setUp() + { + parent::setUp(); + + $this->routeCollection = new RouteCollection(); + $this->generatorDumper = new CompiledUrlGeneratorDumper($this->routeCollection); + $this->testTmpFilepath = sys_get_temp_dir().'/php_generator.'.$this->getName().'.php'; + $this->largeTestTmpFilepath = sys_get_temp_dir().'/php_generator.'.$this->getName().'.large.php'; + @unlink($this->testTmpFilepath); + @unlink($this->largeTestTmpFilepath); + } + + protected function tearDown() + { + parent::tearDown(); + + @unlink($this->testTmpFilepath); + + $this->routeCollection = null; + $this->generatorDumper = null; + $this->testTmpFilepath = null; + } + + public function testDumpWithRoutes() + { + $this->routeCollection->add('Test', new Route('/testing/{foo}')); + $this->routeCollection->add('Test2', new Route('/testing2')); + + file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump()); + + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext('/app.php')); + + $absoluteUrlWithParameter = $projectUrlGenerator->generate('Test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_URL); + $absoluteUrlWithoutParameter = $projectUrlGenerator->generate('Test2', [], UrlGeneratorInterface::ABSOLUTE_URL); + $relativeUrlWithParameter = $projectUrlGenerator->generate('Test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_PATH); + $relativeUrlWithoutParameter = $projectUrlGenerator->generate('Test2', [], UrlGeneratorInterface::ABSOLUTE_PATH); + + $this->assertEquals('http://localhost/app.php/testing/bar', $absoluteUrlWithParameter); + $this->assertEquals('http://localhost/app.php/testing2', $absoluteUrlWithoutParameter); + $this->assertEquals('/app.php/testing/bar', $relativeUrlWithParameter); + $this->assertEquals('/app.php/testing2', $relativeUrlWithoutParameter); + } + + public function testDumpWithSimpleLocalizedRoutes() + { + $this->routeCollection->add('test', (new Route('/foo'))); + $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(); + file_put_contents($this->testTmpFilepath, $code); + + $context = new RequestContext('/app.php'); + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, $context, null, 'en'); + + $urlWithDefaultLocale = $projectUrlGenerator->generate('test'); + $urlWithSpecifiedLocale = $projectUrlGenerator->generate('test', ['_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); + + // test with full route name + $this->assertEquals('/app.php/testing/is/fun', $projectUrlGenerator->generate('test.en')); + + $context->setParameter('_locale', 'de_DE'); + // test that it fall backs to another route when there is no matching localized route + $this->assertEquals('/app.php/foo', $projectUrlGenerator->generate('test')); + } + + /** + * @expectedException \Symfony\Component\Routing\Exception\RouteNotFoundException + * @expectedExceptionMessage Unable to generate a URL for the named route "test" as such route does not exist. + */ + public function testDumpWithRouteNotFoundLocalizedRoutes() + { + $this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'test')); + + $code = $this->generatorDumper->dump(); + file_put_contents($this->testTmpFilepath, $code); + + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext('/app.php'), null, 'pl_PL'); + $projectUrlGenerator->generate('test'); + } + + public function testDumpWithFallbackLocaleLocalizedRoutes() + { + $this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_canonical_route', 'test')); + $this->routeCollection->add('test.nl', (new Route('/testen/is/leuk'))->setDefault('_canonical_route', 'test')); + $this->routeCollection->add('test.fr', (new Route('/tester/est/amusant'))->setDefault('_canonical_route', 'test')); + + $code = $this->generatorDumper->dump(); + file_put_contents($this->testTmpFilepath, $code); + + $context = new RequestContext('/app.php'); + $context->setParameter('_locale', 'en_GB'); + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, $context, null, null); + + // test with context _locale + $this->assertEquals('/app.php/testing/is/fun', $projectUrlGenerator->generate('test')); + // test with parameters _locale + $this->assertEquals('/app.php/testen/is/leuk', $projectUrlGenerator->generate('test', ['_locale' => 'nl_BE'])); + + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext('/app.php'), null, 'fr_CA'); + // test with default locale + $this->assertEquals('/app.php/tester/est/amusant', $projectUrlGenerator->generate('test')); + } + + public function testDumpWithTooManyRoutes() + { + $this->routeCollection->add('Test', new Route('/testing/{foo}')); + for ($i = 0; $i < 32769; ++$i) { + $this->routeCollection->add('route_'.$i, new Route('/route_'.$i)); + } + $this->routeCollection->add('Test2', new Route('/testing2')); + + file_put_contents($this->largeTestTmpFilepath, $this->generatorDumper->dump()); + $this->routeCollection = $this->generatorDumper = null; + + $projectUrlGenerator = new CompiledUrlGenerator(require $this->largeTestTmpFilepath, new RequestContext('/app.php')); + + $absoluteUrlWithParameter = $projectUrlGenerator->generate('Test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_URL); + $absoluteUrlWithoutParameter = $projectUrlGenerator->generate('Test2', [], UrlGeneratorInterface::ABSOLUTE_URL); + $relativeUrlWithParameter = $projectUrlGenerator->generate('Test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_PATH); + $relativeUrlWithoutParameter = $projectUrlGenerator->generate('Test2', [], UrlGeneratorInterface::ABSOLUTE_PATH); + + $this->assertEquals('http://localhost/app.php/testing/bar', $absoluteUrlWithParameter); + $this->assertEquals('http://localhost/app.php/testing2', $absoluteUrlWithoutParameter); + $this->assertEquals('/app.php/testing/bar', $relativeUrlWithParameter); + $this->assertEquals('/app.php/testing2', $relativeUrlWithoutParameter); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testDumpWithoutRoutes() + { + file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump()); + + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext('/app.php')); + + $projectUrlGenerator->generate('Test', []); + } + + /** + * @expectedException \Symfony\Component\Routing\Exception\RouteNotFoundException + */ + public function testGenerateNonExistingRoute() + { + $this->routeCollection->add('Test', new Route('/test')); + + file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump()); + + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext()); + $url = $projectUrlGenerator->generate('NonExisting', []); + } + + public function testDumpForRouteWithDefaults() + { + $this->routeCollection->add('Test', new Route('/testing/{foo}', ['foo' => 'bar'])); + + file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump()); + + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext()); + $url = $projectUrlGenerator->generate('Test', []); + + $this->assertEquals('/testing', $url); + } + + public function testDumpWithSchemeRequirement() + { + $this->routeCollection->add('Test1', new Route('/testing', [], [], [], '', ['ftp', 'https'])); + + file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump()); + + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext('/app.php')); + + $absoluteUrl = $projectUrlGenerator->generate('Test1', [], UrlGeneratorInterface::ABSOLUTE_URL); + $relativeUrl = $projectUrlGenerator->generate('Test1', [], UrlGeneratorInterface::ABSOLUTE_PATH); + + $this->assertEquals('ftp://localhost/app.php/testing', $absoluteUrl); + $this->assertEquals('ftp://localhost/app.php/testing', $relativeUrl); + + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext('/app.php', 'GET', 'localhost', 'https')); + + $absoluteUrl = $projectUrlGenerator->generate('Test1', [], UrlGeneratorInterface::ABSOLUTE_URL); + $relativeUrl = $projectUrlGenerator->generate('Test1', [], UrlGeneratorInterface::ABSOLUTE_PATH); + + $this->assertEquals('https://localhost/app.php/testing', $absoluteUrl); + $this->assertEquals('/app.php/testing', $relativeUrl); + } +} diff --git a/src/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php b/src/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php index f38e30de98fc..0dcf2e863538 100644 --- a/src/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php +++ b/src/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php @@ -18,6 +18,9 @@ use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; +/** + * @group legacy + */ class PhpGeneratorDumperTest extends TestCase { /** diff --git a/src/Symfony/Component/Routing/Tests/Matcher/CompiledRedirectableUrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/CompiledRedirectableUrlMatcherTest.php new file mode 100644 index 000000000000..7fb7dfef9e97 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Matcher/CompiledRedirectableUrlMatcherTest.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Matcher; + +use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; +use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\RouteCollection; + +class CompiledRedirectableUrlMatcherTest extends RedirectableUrlMatcherTest +{ + protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) + { + $dumper = new CompiledUrlMatcherDumper($routes); + $compiledRoutes = $dumper->getCompiledRoutes(); + + return $this->getMockBuilder(TestCompiledRedirectableUrlMatcher::class) + ->setConstructorArgs([$compiledRoutes, $context ?: new RequestContext()]) + ->setMethods(['redirect']) + ->getMock(); + } +} + +class TestCompiledRedirectableUrlMatcher extends CompiledUrlMatcher implements RedirectableUrlMatcherInterface +{ + public function redirect($path, $route, $scheme = null) + { + return []; + } +} diff --git a/src/Symfony/Component/Routing/Tests/Matcher/CompiledUrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/CompiledUrlMatcherTest.php new file mode 100644 index 000000000000..0a93f5ee7531 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Matcher/CompiledUrlMatcherTest.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Matcher; + +use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\RouteCollection; + +class CompiledUrlMatcherTest extends UrlMatcherTest +{ + protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) + { + $dumper = new CompiledUrlMatcherDumper($routes); + + return new CompiledUrlMatcher($dumper->getCompiledRoutes(), $context ?: new RequestContext()); + } +} diff --git a/src/Symfony/Component/Routing/Tests/Matcher/DumpedRedirectableUrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/DumpedRedirectableUrlMatcherTest.php index 235e47768f50..aed006f710c0 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/DumpedRedirectableUrlMatcherTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/DumpedRedirectableUrlMatcherTest.php @@ -17,6 +17,9 @@ use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\RouteCollection; +/** + * @group legacy + */ class DumpedRedirectableUrlMatcherTest extends RedirectableUrlMatcherTest { protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) diff --git a/src/Symfony/Component/Routing/Tests/Matcher/DumpedUrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/DumpedUrlMatcherTest.php index dcf2185888c7..1766c04d7ed1 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/DumpedUrlMatcherTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/DumpedUrlMatcherTest.php @@ -15,6 +15,9 @@ use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\RouteCollection; +/** + * @group legacy + */ class DumpedUrlMatcherTest extends UrlMatcherTest { protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) diff --git a/src/Symfony/Component/Routing/Tests/Matcher/Dumper/CompiledUrlMatcherDumperTest.php b/src/Symfony/Component/Routing/Tests/Matcher/Dumper/CompiledUrlMatcherDumperTest.php new file mode 100644 index 000000000000..ad9c8376f72c --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Matcher/Dumper/CompiledUrlMatcherDumperTest.php @@ -0,0 +1,496 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Matcher\Dumper; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; +use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +class CompiledUrlMatcherDumperTest extends TestCase +{ + /** + * @var string + */ + private $dumpPath; + + protected function setUp() + { + parent::setUp(); + + $this->dumpPath = sys_get_temp_dir().\DIRECTORY_SEPARATOR.'php_matcher.'.uniqid('CompiledUrlMatcher').'.php'; + } + + protected function tearDown() + { + parent::tearDown(); + + @unlink($this->dumpPath); + } + + public function testRedirectPreservesUrlEncoding() + { + $collection = new RouteCollection(); + $collection->add('foo', new Route('/foo:bar/')); + + $matcher = $this->generateDumpedMatcher($collection); + $matcher->expects($this->once())->method('redirect')->with('/foo%3Abar/', 'foo')->willReturn([]); + + $matcher->match('/foo%3Abar'); + } + + /** + * @dataProvider getRouteCollections + */ + public function testDump(RouteCollection $collection, $fixture) + { + $basePath = __DIR__.'/../../Fixtures/dumper/'; + + $dumper = new CompiledUrlMatcherDumper($collection); + $this->assertStringEqualsFile($basePath.$fixture, $dumper->dump()); + } + + public function getRouteCollections() + { + /* test case 1 */ + + $collection = new RouteCollection(); + + $collection->add('overridden', new Route('/overridden')); + + // defaults and requirements + $collection->add('foo', new Route( + '/foo/{bar}', + ['def' => 'test'], + ['bar' => 'baz|symfony'] + )); + // method requirement + $collection->add('bar', new Route( + '/bar/{foo}', + [], + [], + [], + '', + [], + ['GET', 'head'] + )); + // GET method requirement automatically adds HEAD as valid + $collection->add('barhead', new Route( + '/barhead/{foo}', + [], + [], + [], + '', + [], + ['GET'] + )); + // simple + $collection->add('baz', new Route( + '/test/baz' + )); + // simple with extension + $collection->add('baz2', new Route( + '/test/baz.html' + )); + // trailing slash + $collection->add('baz3', new Route( + '/test/baz3/' + )); + // trailing slash with variable + $collection->add('baz4', new Route( + '/test/{foo}/' + )); + // trailing slash and method + $collection->add('baz5', new Route( + '/test/{foo}/', + [], + [], + [], + '', + [], + ['post'] + )); + // complex name + $collection->add('baz.baz6', new Route( + '/test/{foo}/', + [], + [], + [], + '', + [], + ['put'] + )); + // defaults without variable + $collection->add('foofoo', new Route( + '/foofoo', + ['def' => 'test'] + )); + // pattern with quotes + $collection->add('quoter', new Route( + '/{quoter}', + [], + ['quoter' => '[\']+'] + )); + // space in pattern + $collection->add('space', new Route( + '/spa ce' + )); + + // prefixes + $collection1 = new RouteCollection(); + $collection1->add('overridden', new Route('/overridden1')); + $collection1->add('foo1', (new Route('/{foo}'))->setMethods('PUT')); + $collection1->add('bar1', new Route('/{bar}')); + $collection1->addPrefix('/b\'b'); + $collection2 = new RouteCollection(); + $collection2->addCollection($collection1); + $collection2->add('overridden', new Route('/{var}', [], ['var' => '.*'])); + $collection1 = new RouteCollection(); + $collection1->add('foo2', new Route('/{foo1}')); + $collection1->add('bar2', new Route('/{bar1}')); + $collection1->addPrefix('/b\'b'); + $collection2->addCollection($collection1); + $collection2->addPrefix('/a'); + $collection->addCollection($collection2); + + // overridden through addCollection() and multiple sub-collections with no own prefix + $collection1 = new RouteCollection(); + $collection1->add('overridden2', new Route('/old')); + $collection1->add('helloWorld', new Route('/hello/{who}', ['who' => 'World!'])); + $collection2 = new RouteCollection(); + $collection3 = new RouteCollection(); + $collection3->add('overridden2', new Route('/new')); + $collection3->add('hey', new Route('/hey/')); + $collection2->addCollection($collection3); + $collection1->addCollection($collection2); + $collection1->addPrefix('/multi'); + $collection->addCollection($collection1); + + // "dynamic" prefix + $collection1 = new RouteCollection(); + $collection1->add('foo3', new Route('/{foo}')); + $collection1->add('bar3', new Route('/{bar}')); + $collection1->addPrefix('/b'); + $collection1->addPrefix('{_locale}'); + $collection->addCollection($collection1); + + // route between collections + $collection->add('ababa', new Route('/ababa')); + + // collection with static prefix but only one route + $collection1 = new RouteCollection(); + $collection1->add('foo4', new Route('/{foo}')); + $collection1->addPrefix('/aba'); + $collection->addCollection($collection1); + + // prefix and host + + $collection1 = new RouteCollection(); + + $route1 = new Route('/route1', [], [], [], 'a.example.com'); + $collection1->add('route1', $route1); + + $route2 = new Route('/c2/route2', [], [], [], 'a.example.com'); + $collection1->add('route2', $route2); + + $route3 = new Route('/c2/route3', [], [], [], 'b.example.com'); + $collection1->add('route3', $route3); + + $route4 = new Route('/route4', [], [], [], 'a.example.com'); + $collection1->add('route4', $route4); + + $route5 = new Route('/route5', [], [], [], 'c.example.com'); + $collection1->add('route5', $route5); + + $route6 = new Route('/route6', [], [], [], null); + $collection1->add('route6', $route6); + + $collection->addCollection($collection1); + + // host and variables + + $collection1 = new RouteCollection(); + + $route11 = new Route('/route11', [], [], [], '{var1}.example.com'); + $collection1->add('route11', $route11); + + $route12 = new Route('/route12', ['var1' => 'val'], [], [], '{var1}.example.com'); + $collection1->add('route12', $route12); + + $route13 = new Route('/route13/{name}', [], [], [], '{var1}.example.com'); + $collection1->add('route13', $route13); + + $route14 = new Route('/route14/{name}', ['var1' => 'val'], [], [], '{var1}.example.com'); + $collection1->add('route14', $route14); + + $route15 = new Route('/route15/{name}', [], [], [], 'c.example.com'); + $collection1->add('route15', $route15); + + $route16 = new Route('/route16/{name}', ['var1' => 'val'], [], [], null); + $collection1->add('route16', $route16); + + $route17 = new Route('/route17', [], [], [], null); + $collection1->add('route17', $route17); + + $collection->addCollection($collection1); + + // multiple sub-collections with a single route and a prefix each + $collection1 = new RouteCollection(); + $collection1->add('a', new Route('/a...')); + $collection2 = new RouteCollection(); + $collection2->add('b', new Route('/{var}')); + $collection3 = new RouteCollection(); + $collection3->add('c', new Route('/{var}')); + $collection3->addPrefix('/c'); + $collection2->addCollection($collection3); + $collection2->addPrefix('/b'); + $collection1->addCollection($collection2); + $collection1->addPrefix('/a'); + $collection->addCollection($collection1); + + /* test case 2 */ + + $redirectCollection = clone $collection; + + // force HTTPS redirection + $redirectCollection->add('secure', new Route( + '/secure', + [], + [], + [], + '', + ['https'] + )); + + // force HTTP redirection + $redirectCollection->add('nonsecure', new Route( + '/nonsecure', + [], + [], + [], + '', + ['http'] + )); + + /* test case 3 */ + + $rootprefixCollection = new RouteCollection(); + $rootprefixCollection->add('static', new Route('/test')); + $rootprefixCollection->add('dynamic', new Route('/{var}')); + $rootprefixCollection->addPrefix('rootprefix'); + $route = new Route('/with-condition'); + $route->setCondition('context.getMethod() == "GET"'); + $rootprefixCollection->add('with-condition', $route); + + /* test case 4 */ + $headMatchCasesCollection = new RouteCollection(); + $headMatchCasesCollection->add('just_head', new Route( + '/just_head', + [], + [], + [], + '', + [], + ['HEAD'] + )); + $headMatchCasesCollection->add('head_and_get', new Route( + '/head_and_get', + [], + [], + [], + '', + [], + ['HEAD', 'GET'] + )); + $headMatchCasesCollection->add('get_and_head', new Route( + '/get_and_head', + [], + [], + [], + '', + [], + ['GET', 'HEAD'] + )); + $headMatchCasesCollection->add('post_and_head', new Route( + '/post_and_head', + [], + [], + [], + '', + [], + ['POST', 'HEAD'] + )); + $headMatchCasesCollection->add('put_and_post', new Route( + '/put_and_post', + [], + [], + [], + '', + [], + ['PUT', 'POST'] + )); + $headMatchCasesCollection->add('put_and_get_and_head', new Route( + '/put_and_post', + [], + [], + [], + '', + [], + ['PUT', 'GET', 'HEAD'] + )); + + /* test case 5 */ + $groupOptimisedCollection = new RouteCollection(); + $groupOptimisedCollection->add('a_first', new Route('/a/11')); + $groupOptimisedCollection->add('a_second', new Route('/a/22')); + $groupOptimisedCollection->add('a_third', new Route('/a/333')); + $groupOptimisedCollection->add('a_wildcard', new Route('/{param}')); + $groupOptimisedCollection->add('a_fourth', new Route('/a/44/')); + $groupOptimisedCollection->add('a_fifth', new Route('/a/55/')); + $groupOptimisedCollection->add('a_sixth', new Route('/a/66/')); + $groupOptimisedCollection->add('nested_wildcard', new Route('/nested/{param}')); + $groupOptimisedCollection->add('nested_a', new Route('/nested/group/a/')); + $groupOptimisedCollection->add('nested_b', new Route('/nested/group/b/')); + $groupOptimisedCollection->add('nested_c', new Route('/nested/group/c/')); + + $groupOptimisedCollection->add('slashed_a', new Route('/slashed/group/')); + $groupOptimisedCollection->add('slashed_b', new Route('/slashed/group/b/')); + $groupOptimisedCollection->add('slashed_c', new Route('/slashed/group/c/')); + + /* test case 6 & 7 */ + $trailingSlashCollection = new RouteCollection(); + $trailingSlashCollection->add('simple_trailing_slash_no_methods', new Route('/trailing/simple/no-methods/', [], [], [], '', [], [])); + $trailingSlashCollection->add('simple_trailing_slash_GET_method', new Route('/trailing/simple/get-method/', [], [], [], '', [], ['GET'])); + $trailingSlashCollection->add('simple_trailing_slash_HEAD_method', new Route('/trailing/simple/head-method/', [], [], [], '', [], ['HEAD'])); + $trailingSlashCollection->add('simple_trailing_slash_POST_method', new Route('/trailing/simple/post-method/', [], [], [], '', [], ['POST'])); + $trailingSlashCollection->add('regex_trailing_slash_no_methods', new Route('/trailing/regex/no-methods/{param}/', [], [], [], '', [], [])); + $trailingSlashCollection->add('regex_trailing_slash_GET_method', new Route('/trailing/regex/get-method/{param}/', [], [], [], '', [], ['GET'])); + $trailingSlashCollection->add('regex_trailing_slash_HEAD_method', new Route('/trailing/regex/head-method/{param}/', [], [], [], '', [], ['HEAD'])); + $trailingSlashCollection->add('regex_trailing_slash_POST_method', new Route('/trailing/regex/post-method/{param}/', [], [], [], '', [], ['POST'])); + + $trailingSlashCollection->add('simple_not_trailing_slash_no_methods', new Route('/not-trailing/simple/no-methods', [], [], [], '', [], [])); + $trailingSlashCollection->add('simple_not_trailing_slash_GET_method', new Route('/not-trailing/simple/get-method', [], [], [], '', [], ['GET'])); + $trailingSlashCollection->add('simple_not_trailing_slash_HEAD_method', new Route('/not-trailing/simple/head-method', [], [], [], '', [], ['HEAD'])); + $trailingSlashCollection->add('simple_not_trailing_slash_POST_method', new Route('/not-trailing/simple/post-method', [], [], [], '', [], ['POST'])); + $trailingSlashCollection->add('regex_not_trailing_slash_no_methods', new Route('/not-trailing/regex/no-methods/{param}', [], [], [], '', [], [])); + $trailingSlashCollection->add('regex_not_trailing_slash_GET_method', new Route('/not-trailing/regex/get-method/{param}', [], [], [], '', [], ['GET'])); + $trailingSlashCollection->add('regex_not_trailing_slash_HEAD_method', new Route('/not-trailing/regex/head-method/{param}', [], [], [], '', [], ['HEAD'])); + $trailingSlashCollection->add('regex_not_trailing_slash_POST_method', new Route('/not-trailing/regex/post-method/{param}', [], [], [], '', [], ['POST'])); + + /* test case 8 */ + $unicodeCollection = new RouteCollection(); + $unicodeCollection->add('a', new Route('/{a}', [], ['a' => 'a'], ['utf8' => false])); + $unicodeCollection->add('b', new Route('/{a}', [], ['a' => '.'], ['utf8' => true])); + $unicodeCollection->add('c', new Route('/{a}', [], ['a' => '.'], ['utf8' => false])); + + /* test case 9 */ + $hostTreeCollection = new RouteCollection(); + $hostTreeCollection->add('a', (new Route('/'))->setHost('{d}.e.c.b.a')); + $hostTreeCollection->add('b', (new Route('/'))->setHost('d.c.b.a')); + $hostTreeCollection->add('c', (new Route('/'))->setHost('{e}.e.c.b.a')); + + /* test case 10 */ + $chunkedCollection = new RouteCollection(); + for ($i = 0; $i < 1000; ++$i) { + $h = substr(md5($i), 0, 6); + $chunkedCollection->add('_'.$i, new Route('/'.$h.'/{a}/{b}/{c}/'.$h)); + } + + /* test case 11 */ + $demoCollection = new RouteCollection(); + $demoCollection->add('a', new Route('/admin/post/')); + $demoCollection->add('b', new Route('/admin/post/new')); + $demoCollection->add('c', (new Route('/admin/post/{id}'))->setRequirements(['id' => '\d+'])); + $demoCollection->add('d', (new Route('/admin/post/{id}/edit'))->setRequirements(['id' => '\d+'])); + $demoCollection->add('e', (new Route('/admin/post/{id}/delete'))->setRequirements(['id' => '\d+'])); + $demoCollection->add('f', new Route('/blog/')); + $demoCollection->add('g', new Route('/blog/rss.xml')); + $demoCollection->add('h', (new Route('/blog/page/{page}'))->setRequirements(['id' => '\d+'])); + $demoCollection->add('i', (new Route('/blog/posts/{page}'))->setRequirements(['id' => '\d+'])); + $demoCollection->add('j', (new Route('/blog/comments/{id}/new'))->setRequirements(['id' => '\d+'])); + $demoCollection->add('k', new Route('/blog/search')); + $demoCollection->add('l', new Route('/login')); + $demoCollection->add('m', new Route('/logout')); + $demoCollection->addPrefix('/{_locale}'); + $demoCollection->add('n', new Route('/{_locale}')); + $demoCollection->addRequirements(['_locale' => 'en|fr']); + $demoCollection->addDefaults(['_locale' => 'en']); + + /* test case 12 */ + $suffixCollection = new RouteCollection(); + $suffixCollection->add('r1', new Route('abc{foo}/1')); + $suffixCollection->add('r2', new Route('abc{foo}/2')); + $suffixCollection->add('r10', new Route('abc{foo}/10')); + $suffixCollection->add('r20', new Route('abc{foo}/20')); + $suffixCollection->add('r100', new Route('abc{foo}/100')); + $suffixCollection->add('r200', new Route('abc{foo}/200')); + + /* test case 13 */ + $hostCollection = new RouteCollection(); + $hostCollection->add('r1', (new Route('abc{foo}'))->setHost('{foo}.exampple.com')); + $hostCollection->add('r2', (new Route('abc{foo}'))->setHost('{foo}.exampple.com')); + + return [ + [new RouteCollection(), 'compiled_url_matcher0.php'], + [$collection, 'compiled_url_matcher1.php'], + [$redirectCollection, 'compiled_url_matcher2.php'], + [$rootprefixCollection, 'compiled_url_matcher3.php'], + [$headMatchCasesCollection, 'compiled_url_matcher4.php'], + [$groupOptimisedCollection, 'compiled_url_matcher5.php'], + [$trailingSlashCollection, 'compiled_url_matcher6.php'], + [$trailingSlashCollection, 'compiled_url_matcher7.php'], + [$unicodeCollection, 'compiled_url_matcher8.php'], + [$hostTreeCollection, 'compiled_url_matcher9.php'], + [$chunkedCollection, 'compiled_url_matcher10.php'], + [$demoCollection, 'compiled_url_matcher11.php'], + [$suffixCollection, 'compiled_url_matcher12.php'], + [$hostCollection, 'compiled_url_matcher13.php'], + ]; + } + + private function generateDumpedMatcher(RouteCollection $collection) + { + $dumper = new CompiledUrlMatcherDumper($collection); + $code = $dumper->dump(); + + file_put_contents($this->dumpPath, $code); + $compiledRoutes = require $this->dumpPath; + + return $this->getMockBuilder(TestCompiledUrlMatcher::class) + ->setConstructorArgs([$compiledRoutes, new RequestContext()]) + ->setMethods(['redirect']) + ->getMock(); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Symfony\Component\Routing\Route cannot contain objects + */ + public function testGenerateDumperMatcherWithObject() + { + $routeCollection = new RouteCollection(); + $routeCollection->add('_', new Route('/', [new \stdClass()])); + $dumper = new CompiledUrlMatcherDumper($routeCollection); + $dumper->dump(); + } +} + +class TestCompiledUrlMatcher extends CompiledUrlMatcher implements RedirectableUrlMatcherInterface +{ + public function redirect($path, $route, $scheme = null) + { + return []; + } +} diff --git a/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php b/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php index a85ac67ae2c7..93d34edbb701 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php @@ -19,6 +19,9 @@ use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; +/** + * @group legacy + */ class PhpMatcherDumperTest extends TestCase { /**