@@ -29,7 +29,6 @@ class PhpMatcherDumper extends MatcherDumper
2929{
3030 private $ expressionLanguage ;
3131 private $ signalingException ;
32- private $ supportsRedirections ;
3332
3433 /**
3534 * @var ExpressionFunctionProviderInterface[]
@@ -57,7 +56,7 @@ public function dump(array $options = array())
5756
5857 // trailing slash support is only enabled if we know how to redirect the user
5958 $ interfaces = class_implements ($ options ['base_class ' ]);
60- $ this -> supportsRedirections = isset ($ interfaces [RedirectableUrlMatcherInterface::class]);
59+ $ supportsRedirections = isset ($ interfaces [RedirectableUrlMatcherInterface::class]);
6160
6261 return <<<EOF
6362<?php
@@ -77,7 +76,7 @@ public function __construct(RequestContext \$context)
7776 \$this->context = \$context;
7877 }
7978
80- {$ this ->generateMatchMethod ()}
79+ {$ this ->generateMatchMethod ($ supportsRedirections )}
8180}
8281
8382EOF ;
@@ -91,7 +90,7 @@ public function addExpressionLanguageProvider(ExpressionFunctionProviderInterfac
9190 /**
9291 * Generates the code for the match method implementing UrlMatcherInterface.
9392 */
94- private function generateMatchMethod (): string
93+ private function generateMatchMethod (bool $ supportsRedirections ): string
9594 {
9695 // Group hosts by same-suffix, re-order when possible
9796 $ matchHost = false ;
@@ -111,7 +110,7 @@ private function generateMatchMethod(): string
111110
112111 $ code = <<<EOF
113112 {
114- \$allow = array();
113+ \$allow = \$ allowSchemes = array();
115114 \$pathinfo = rawurldecode( \$rawPathinfo);
116115 \$context = \$this->context;
117116 \$requestMethod = \$canonicalMethod = \$context->getMethod();
@@ -124,25 +123,44 @@ private function generateMatchMethod(): string
124123
125124EOF ;
126125
127- if ($ this -> supportsRedirections ) {
126+ if ($ supportsRedirections ) {
128127 return <<<'EOF'
129128 public function match($pathinfo)
130129 {
131- $allow = array();
132- if ($ret = $this->doMatch($pathinfo, $allow)) {
130+ $allow = $allowSchemes = array();
131+ if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes )) {
133132 return $ret;
134133 }
135- if ('/' !== $pathinfo && in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
134+ if ($allow) {
135+ throw new MethodNotAllowedException(array_keys($allow));
136+ }
137+ if (!in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
138+ // no-op
139+ } elseif ($allowSchemes) {
140+ redirect_scheme:
141+ $scheme = $this->context->getScheme();
142+ $this->context->setScheme(key($allowSchemes));
143+ try {
144+ if ($ret = $this->doMatch($pathinfo)) {
145+ return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret;
146+ }
147+ } finally {
148+ $this->context->setScheme($scheme);
149+ }
150+ } elseif ('/' !== $pathinfo) {
136151 $pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
137- if ($ret = $this->doMatch($pathinfo)) {
152+ if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes )) {
138153 return $this->redirect($pathinfo, $ret['_route']) + $ret;
139154 }
155+ if ($allowSchemes) {
156+ goto redirect_scheme;
157+ }
140158 }
141159
142- throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
160+ throw new ResourceNotFoundException();
143161 }
144162
145- private function doMatch(string $rawPathinfo, array &$allow = array()): ?array
163+ private function doMatch(string $rawPathinfo, array &$allow = array(), array &$allowSchemes = array() ): ?array
146164
147165EOF
148166 .$ code ."\n return null; \n } " ;
@@ -238,9 +256,6 @@ private function compileStaticRoutes(array $staticRoutes, bool $matchHost): stri
238256 }
239257
240258 if (!$ route ->getCondition ()) {
241- if (!$ this ->supportsRedirections && $ route ->getSchemes ()) {
242- throw new \LogicException ('The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface. ' );
243- }
244259 $ default .= sprintf (
245260 "%s => array(%s, %s, %s, %s), \n" ,
246261 self ::export ($ url ),
@@ -535,8 +550,8 @@ private function compileSwitchDefault(bool $hasVars, bool $matchHost): string
535550 } else {
536551 $ code = '' ;
537552 }
538- if ( $ this -> supportsRedirections ) {
539- $ code .= <<<EOF
553+
554+ $ code .= <<<EOF
540555
541556 \$hasRequiredScheme = ! \$requiredSchemes || isset( \$requiredSchemes[ \$context->getScheme()]);
542557 if ( \$requiredMethods && !isset( \$requiredMethods[ \$canonicalMethod]) && !isset( \$requiredMethods[ \$requestMethod])) {
@@ -546,28 +561,13 @@ private function compileSwitchDefault(bool $hasVars, bool $matchHost): string
546561 break;
547562 }
548563 if (! \$hasRequiredScheme) {
549- if ('GET' !== \$canonicalMethod) {
550- break;
551- }
552-
553- return \$this->redirect( \$rawPathinfo, \$ret['_route'], key( \$requiredSchemes)) + \$ret;
554- }
555-
556- return \$ret;
557-
558- EOF ;
559- } else {
560- $ code .= <<<EOF
561-
562- if ( \$requiredMethods && !isset( \$requiredMethods[ \$canonicalMethod]) && !isset( \$requiredMethods[ \$requestMethod])) {
563- \$allow += \$requiredMethods;
564+ \$allowSchemes += \$requiredSchemes;
564565 break;
565566 }
566567
567568 return \$ret;
568569
569570EOF ;
570- }
571571
572572 return $ code ;
573573 }
@@ -647,9 +647,6 @@ private function compileRoute(Route $route, string $name, bool $checkHost): stri
647647 }
648648
649649 if ($ schemes = $ route ->getSchemes ()) {
650- if (!$ this ->supportsRedirections ) {
651- throw new \LogicException ('The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface. ' );
652- }
653650 $ schemes = self ::export (array_flip ($ schemes ));
654651 if ($ methods ) {
655652 $ code .= <<<EOF
@@ -662,11 +659,8 @@ private function compileRoute(Route $route, string $name, bool $checkHost): stri
662659 goto $ gotoname;
663660 }
664661 if (! \$hasRequiredScheme) {
665- if ('GET' !== \$canonicalMethod) {
666- goto $ gotoname;
667- }
668-
669- return \$this->redirect( \$rawPathinfo, ' $ name', key( \$requiredSchemes)) + \$ret;
662+ \$allowSchemes += \$requiredSchemes;
663+ goto $ gotoname;
670664 }
671665
672666
@@ -675,11 +669,8 @@ private function compileRoute(Route $route, string $name, bool $checkHost): stri
675669 $ code .= <<<EOF
676670 \$requiredSchemes = $ schemes;
677671 if (!isset( \$requiredSchemes[ \$context->getScheme()])) {
678- if ('GET' !== \$canonicalMethod) {
679- goto $ gotoname;
680- }
681-
682- return \$this->redirect( \$rawPathinfo, ' $ name', key( \$requiredSchemes)) + \$ret;
672+ \$allowSchemes += \$requiredSchemes;
673+ goto $ gotoname;
683674 }
684675
685676
0 commit comments