vendor/symfony/routing/Matcher/Dumper/PhpMatcherTrait.php line 67

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\Routing\Matcher\Dumper;
  11. use Symfony\Component\Routing\Exception\MethodNotAllowedException;
  12. use Symfony\Component\Routing\Exception\NoConfigurationException;
  13. use Symfony\Component\Routing\Exception\ResourceNotFoundException;
  14. use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface;
  15. /**
  16.  * @author Nicolas Grekas <p@tchwork.com>
  17.  *
  18.  * @internal
  19.  */
  20. trait PhpMatcherTrait
  21. {
  22.     private $matchHost false;
  23.     private $staticRoutes = [];
  24.     private $regexpList = [];
  25.     private $dynamicRoutes = [];
  26.     private $checkCondition;
  27.     public function match($pathinfo)
  28.     {
  29.         $allow $allowSchemes = [];
  30.         if ($ret $this->doMatch($pathinfo$allow$allowSchemes)) {
  31.             return $ret;
  32.         }
  33.         if ($allow) {
  34.             throw new MethodNotAllowedException(array_keys($allow));
  35.         }
  36.         if (!$this instanceof RedirectableUrlMatcherInterface) {
  37.             throw new ResourceNotFoundException();
  38.         }
  39.         if (!\in_array($this->context->getMethod(), ['HEAD''GET'], true)) {
  40.             // no-op
  41.         } elseif ($allowSchemes) {
  42.             redirect_scheme:
  43.             $scheme $this->context->getScheme();
  44.             $this->context->setScheme(key($allowSchemes));
  45.             try {
  46.                 if ($ret $this->doMatch($pathinfo)) {
  47.                     return $this->redirect($pathinfo$ret['_route'], $this->context->getScheme()) + $ret;
  48.                 }
  49.             } finally {
  50.                 $this->context->setScheme($scheme);
  51.             }
  52.         } elseif ('/' !== $trimmedPathinfo rtrim($pathinfo'/') ?: '/') {
  53.             $pathinfo $trimmedPathinfo === $pathinfo $pathinfo.'/' $trimmedPathinfo;
  54.             if ($ret $this->doMatch($pathinfo$allow$allowSchemes)) {
  55.                 return $this->redirect($pathinfo$ret['_route']) + $ret;
  56.             }
  57.             if ($allowSchemes) {
  58.                 goto redirect_scheme;
  59.             }
  60.         }
  61.         throw new ResourceNotFoundException();
  62.     }
  63.     private function doMatch(string $pathinfo, array &$allow = [], array &$allowSchemes = []): array
  64.     {
  65.         $allow $allowSchemes = [];
  66.         $pathinfo rawurldecode($pathinfo) ?: '/';
  67.         $trimmedPathinfo rtrim($pathinfo'/') ?: '/';
  68.         $context $this->context;
  69.         $requestMethod $canonicalMethod $context->getMethod();
  70.         if ($this->matchHost) {
  71.             $host strtolower($context->getHost());
  72.         }
  73.         if ('HEAD' === $requestMethod) {
  74.             $canonicalMethod 'GET';
  75.         }
  76.         $supportsRedirections 'GET' === $canonicalMethod && $this instanceof RedirectableUrlMatcherInterface;
  77.         foreach ($this->staticRoutes[$trimmedPathinfo] ?? [] as list($ret$requiredHost$requiredMethods$requiredSchemes$hasTrailingSlash, , $condition)) {
  78.             if ($condition && !($this->checkCondition)($condition$context$condition $request ?? $request $this->request ?: $this->createRequest($pathinfo) : null)) {
  79.                 continue;
  80.             }
  81.             if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
  82.                 if ($supportsRedirections && (!$requiredMethods || isset($requiredMethods['GET']))) {
  83.                     return $allow $allowSchemes = [];
  84.                 }
  85.                 continue;
  86.             }
  87.             if ($requiredHost) {
  88.                 if ('#' !== $requiredHost[0] ? $requiredHost !== $host : !preg_match($requiredHost$host$hostMatches)) {
  89.                     continue;
  90.                 }
  91.                 if ('#' === $requiredHost[0] && $hostMatches) {
  92.                     $hostMatches['_route'] = $ret['_route'];
  93.                     $ret $this->mergeDefaults($hostMatches$ret);
  94.                 }
  95.             }
  96.             $hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
  97.             if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
  98.                 if ($hasRequiredScheme) {
  99.                     $allow += $requiredMethods;
  100.                 }
  101.                 continue;
  102.             }
  103.             if (!$hasRequiredScheme) {
  104.                 $allowSchemes += $requiredSchemes;
  105.                 continue;
  106.             }
  107.             return $ret;
  108.         }
  109.         $matchedPathinfo $this->matchHost $host.'.'.$pathinfo $pathinfo;
  110.         foreach ($this->regexpList as $offset => $regex) {
  111.             while (preg_match($regex$matchedPathinfo$matches)) {
  112.                 foreach ($this->dynamicRoutes[$m = (int) $matches['MARK']] as list($ret$vars$requiredMethods$requiredSchemes$hasTrailingSlash$hasTrailingVar$condition)) {
  113.                     if ($condition && !($this->checkCondition)($condition$context$condition $request ?? $request $this->request ?: $this->createRequest($pathinfo) : null)) {
  114.                         continue;
  115.                     }
  116.                     $hasTrailingVar $trimmedPathinfo !== $pathinfo && $hasTrailingVar;
  117.                     if ($hasTrailingVar && ($hasTrailingSlash || '/' !== substr($matches[\count($vars)], -1)) && preg_match($regex$this->matchHost $host.'.'.$trimmedPathinfo $trimmedPathinfo$n) && $m === (int) $n['MARK']) {
  118.                         if ($hasTrailingSlash) {
  119.                             $matches $n;
  120.                         } else {
  121.                             $hasTrailingVar false;
  122.                         }
  123.                     }
  124.                     if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
  125.                         if ($supportsRedirections && (!$requiredMethods || isset($requiredMethods['GET']))) {
  126.                             return $allow $allowSchemes = [];
  127.                         }
  128.                         continue;
  129.                     }
  130.                     foreach ($vars as $i => $v) {
  131.                         if (isset($matches[$i])) {
  132.                             $ret[$v] = $matches[$i];
  133.                         }
  134.                     }
  135.                     $hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
  136.                     if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
  137.                         if ($hasRequiredScheme) {
  138.                             $allow += $requiredMethods;
  139.                         }
  140.                         continue;
  141.                     }
  142.                     if (!$hasRequiredScheme) {
  143.                         $allowSchemes += $requiredSchemes;
  144.                         continue;
  145.                     }
  146.                     return $ret;
  147.                 }
  148.                 $regex substr_replace($regex'F'$m $offset+ \strlen($m));
  149.                 $offset += \strlen($m);
  150.             }
  151.         }
  152.         if ('/' === $pathinfo && !$allow && !$allowSchemes) {
  153.             throw new NoConfigurationException();
  154.         }
  155.         return [];
  156.     }
  157. }