@@ -29,7 +29,6 @@ class PhpMatcherDumper extends MatcherDumper
29
29
{
30
30
private $ expressionLanguage ;
31
31
private $ signalingException ;
32
- private $ supportsRedirections ;
33
32
34
33
/**
35
34
* @var ExpressionFunctionProviderInterface[]
@@ -57,7 +56,7 @@ public function dump(array $options = array())
57
56
58
57
// trailing slash support is only enabled if we know how to redirect the user
59
58
$ interfaces = class_implements ($ options ['base_class ' ]);
60
- $ this -> supportsRedirections = isset ($ interfaces [RedirectableUrlMatcherInterface::class]);
59
+ $ supportsRedirections = isset ($ interfaces [RedirectableUrlMatcherInterface::class]);
61
60
62
61
return <<<EOF
63
62
<?php
@@ -77,7 +76,7 @@ public function __construct(RequestContext \$context)
77
76
\$this->context = \$context;
78
77
}
79
78
80
- {$ this ->generateMatchMethod ()}
79
+ {$ this ->generateMatchMethod ($ supportsRedirections )}
81
80
}
82
81
83
82
EOF ;
@@ -91,7 +90,7 @@ public function addExpressionLanguageProvider(ExpressionFunctionProviderInterfac
91
90
/**
92
91
* Generates the code for the match method implementing UrlMatcherInterface.
93
92
*/
94
- private function generateMatchMethod (): string
93
+ private function generateMatchMethod (bool $ supportsRedirections ): string
95
94
{
96
95
// Group hosts by same-suffix, re-order when possible
97
96
$ matchHost = false ;
@@ -111,7 +110,7 @@ private function generateMatchMethod(): string
111
110
112
111
$ code = <<<EOF
113
112
{
114
- \$allow = array();
113
+ \$allow = \$ allowSchemes = array();
115
114
\$pathinfo = rawurldecode( \$rawPathinfo);
116
115
\$context = \$this->context;
117
116
\$requestMethod = \$canonicalMethod = \$context->getMethod();
@@ -124,25 +123,42 @@ private function generateMatchMethod(): string
124
123
125
124
EOF ;
126
125
127
- if ($ this -> supportsRedirections ) {
126
+ if ($ supportsRedirections ) {
128
127
return <<<'EOF'
129
128
public function match($pathinfo)
130
129
{
131
- $allow = array();
132
- if ($ret = $this->doMatch($pathinfo, $allow)) {
130
+ $allow = $allowSchemes = array();
131
+ if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes )) {
133
132
return $ret;
134
133
}
135
- if ('/' !== $pathinfo && in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
134
+ if ($allow || !in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
135
+ // no-op
136
+ } elseif ($allowSchemes) {
137
+ redirect_scheme:
138
+ $scheme = $this->context->getScheme();
139
+ $this->context->setScheme(key($allowSchemes));
140
+ try {
141
+ if ($ret = $this->doMatch($pathinfo)) {
142
+ return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret;
143
+ }
144
+ } finally {
145
+ $this->context->setScheme($scheme);
146
+ }
147
+ } elseif ('/' !== $pathinfo) {
148
+ $allow2 = array();
136
149
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
137
- if ($ret = $this->doMatch($pathinfo)) {
150
+ if ($ret = $this->doMatch($pathinfo, $allow2, $allowSchemes )) {
138
151
return $this->redirect($pathinfo, $ret['_route']) + $ret;
139
152
}
153
+ if ($allowSchemes) {
154
+ goto redirect_scheme;
155
+ }
140
156
}
141
157
142
158
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
143
159
}
144
160
145
- private function doMatch(string $rawPathinfo, array &$allow = array()): ?array
161
+ private function doMatch(string $rawPathinfo, array &$allow = array(), array &$allowSchemes = array() ): ?array
146
162
147
163
EOF
148
164
.$ code ."\n return null; \n } " ;
@@ -238,9 +254,6 @@ private function compileStaticRoutes(array $staticRoutes, bool $matchHost): stri
238
254
}
239
255
240
256
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
- }
244
257
$ default .= sprintf (
245
258
"%s => array(%s, %s, %s, %s), \n" ,
246
259
self ::export ($ url ),
@@ -535,8 +548,8 @@ private function compileSwitchDefault(bool $hasVars, bool $matchHost): string
535
548
} else {
536
549
$ code = '' ;
537
550
}
538
- if ( $ this -> supportsRedirections ) {
539
- $ code .= <<<EOF
551
+
552
+ $ code .= <<<EOF
540
553
541
554
\$hasRequiredScheme = ! \$requiredSchemes || isset( \$requiredSchemes[ \$context->getScheme()]);
542
555
if ( \$requiredMethods && !isset( \$requiredMethods[ \$canonicalMethod]) && !isset( \$requiredMethods[ \$requestMethod])) {
@@ -546,28 +559,13 @@ private function compileSwitchDefault(bool $hasVars, bool $matchHost): string
546
559
break;
547
560
}
548
561
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;
562
+ \$allowSchemes += \$requiredSchemes;
564
563
break;
565
564
}
566
565
567
566
return \$ret;
568
567
569
568
EOF ;
570
- }
571
569
572
570
return $ code ;
573
571
}
@@ -647,9 +645,6 @@ private function compileRoute(Route $route, string $name, bool $checkHost): stri
647
645
}
648
646
649
647
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
- }
653
648
$ schemes = self ::export (array_flip ($ schemes ));
654
649
if ($ methods ) {
655
650
$ code .= <<<EOF
@@ -662,11 +657,8 @@ private function compileRoute(Route $route, string $name, bool $checkHost): stri
662
657
goto $ gotoname;
663
658
}
664
659
if (! \$hasRequiredScheme) {
665
- if ('GET' !== \$canonicalMethod) {
666
- goto $ gotoname;
667
- }
668
-
669
- return \$this->redirect( \$rawPathinfo, ' $ name', key( \$requiredSchemes)) + \$ret;
660
+ \$allowSchemes += \$requiredSchemes;
661
+ goto $ gotoname;
670
662
}
671
663
672
664
@@ -675,11 +667,8 @@ private function compileRoute(Route $route, string $name, bool $checkHost): stri
675
667
$ code .= <<<EOF
676
668
\$requiredSchemes = $ schemes;
677
669
if (!isset( \$requiredSchemes[ \$context->getScheme()])) {
678
- if ('GET' !== \$canonicalMethod) {
679
- goto $ gotoname;
680
- }
681
-
682
- return \$this->redirect( \$rawPathinfo, ' $ name', key( \$requiredSchemes)) + \$ret;
670
+ \$allowSchemes += \$requiredSchemes;
671
+ goto $ gotoname;
683
672
}
684
673
685
674
0 commit comments