Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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