Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
124 / 124
90.73% covered (success)
90.73%
137 / 151
15.35% covered (danger)
15.35%
37 / 241
59.09% covered (warning)
59.09%
13 / 22
CRAP
0.00% covered (danger)
0.00%
0 / 1
RoutePattern
100.00% covered (success)
100.00%
124 / 124
90.73% covered (success)
90.73%
137 / 151
15.35% covered (danger)
15.35%
37 / 241
100.00% covered (success)
100.00%
22 / 22
2548.27
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 pattern
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 tokens
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 match
100.00% covered (success)
100.00%
4 / 4
83.33% covered (warning)
83.33%
5 / 6
50.00% covered (danger)
50.00%
2 / 4
100.00% covered (success)
100.00%
1 / 1
4.12
 namedMatches
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
6 / 6
25.00% covered (danger)
25.00%
1 / 4
100.00% covered (success)
100.00%
1 / 1
6.80
 generate
100.00% covered (success)
100.00%
9 / 9
83.33% covered (warning)
83.33%
10 / 12
16.67% covered (danger)
16.67%
1 / 6
100.00% covered (success)
100.00%
1 / 1
19.47
 generateParameter
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 generateRemainder
100.00% covered (success)
100.00%
4 / 4
75.00% covered (warning)
75.00%
3 / 4
50.00% covered (danger)
50.00%
1 / 2
100.00% covered (success)
100.00%
1 / 1
1.12
 stringParam
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
7 / 7
80.00% covered (warning)
80.00%
4 / 5
100.00% covered (success)
100.00%
1 / 1
4.13
 matchesConstraint
100.00% covered (success)
100.00%
1 / 1
75.00% covered (warning)
75.00%
3 / 4
50.00% covered (danger)
50.00%
1 / 2
100.00% covered (success)
100.00%
1 / 1
1.12
 assertSafeRemainder
100.00% covered (success)
100.00%
6 / 6
85.71% covered (warning)
85.71%
18 / 21
3.33% covered (danger)
3.33%
3 / 90
100.00% covered (success)
100.00%
1 / 1
38.52
 assertKnownParams
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
8 / 8
50.00% covered (danger)
50.00%
3 / 6
100.00% covered (success)
100.00%
1 / 1
6.00
 parameterNames
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
6 / 6
25.00% covered (danger)
25.00%
1 / 4
100.00% covered (success)
100.00%
1 / 1
6.80
 normalize
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 parse
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
11 / 11
20.00% covered (danger)
20.00%
1 / 5
100.00% covered (success)
100.00%
1 / 1
17.80
 flushLiteral
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 assertUniqueName
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 hideInnerBraces
100.00% covered (success)
100.00%
17 / 17
92.31% covered (success)
92.31%
24 / 26
3.33% covered (danger)
3.33%
3 / 90
100.00% covered (success)
100.00%
1 / 1
82.17
 restoreInnerBraces
100.00% covered (success)
100.00%
1 / 1
75.00% covered (warning)
75.00%
3 / 4
50.00% covered (danger)
50.00%
1 / 2
100.00% covered (success)
100.00%
1 / 1
1.12
 compile
100.00% covered (success)
100.00%
8 / 8
83.33% covered (warning)
83.33%
10 / 12
16.67% covered (danger)
16.67%
1 / 6
100.00% covered (success)
100.00%
1 / 1
19.47
 compileParameter
100.00% covered (success)
100.00%
5 / 5
85.71% covered (warning)
85.71%
6 / 7
66.67% covered (warning)
66.67%
2 / 3
100.00% covered (success)
100.00%
1 / 1
2.15
 compileRemainder
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Celemas\Router;
6
7use Celemas\Router\Exception\InvalidArgumentException;
8use Celemas\Router\Exception\ValueError;
9use Stringable;
10
11/** @internal */
12final readonly class RoutePattern
13{
14    private const string LEFT_BRACE = '§§§€§§§';
15    private const string RIGHT_BRACE = '§§§£§§§';
16
17    private string $pattern;
18
19    /** @var list<RouteToken> */
20    private array $tokens;
21
22    private string $regex;
23
24    public function __construct(string $pattern)
25    {
26        $this->pattern = self::normalize($pattern);
27        $this->tokens = $this->parse($this->pattern);
28        $this->regex = '~^' . $this->compile($this->tokens) . '$~';
29    }
30
31    public function pattern(): string
32    {
33        return $this->pattern;
34    }
35
36    /**
37     * @psalm-suppress PossiblyUnusedMethod -- exposed for parser tests.
38     * @return list<RouteToken>
39     */
40    public function tokens(): array
41    {
42        return $this->tokens;
43    }
44
45    /** @return null|array<string, string> */
46    public function match(string $path): ?array
47    {
48        $path = $path === '' ? '/' : $path;
49
50        /** @psalm-suppress ArgumentTypeCoercion -- route regexes are compiled as non-empty strings */
51        if (preg_match($this->regex, $path, $matches) !== 1) {
52            return null;
53        }
54
55        return self::namedMatches($matches);
56    }
57
58    /**
59     * @param array<array-key, string> $matches
60     * @return array<string, string>
61     */
62    private static function namedMatches(array $matches): array
63    {
64        $params = [];
65
66        foreach ($matches as $key => $value) {
67            if (!is_string($key)) {
68                continue;
69            }
70
71            $params[$key] = $value;
72        }
73
74        return $params;
75    }
76
77    /** @param array<array-key, mixed> $params */
78    public function generate(array $params = []): string
79    {
80        $this->assertKnownParams($params);
81        $path = '';
82
83        foreach ($this->tokens as $token) {
84            $path .= match ($token->type()) {
85                RouteToken::LITERAL => $token->value(),
86                RouteToken::PARAMETER => $this->generateParameter($token, $params),
87                RouteToken::REMAINDER => $this->generateRemainder($token, $params),
88            };
89        }
90
91        return $path;
92    }
93
94    /** @param array<array-key, mixed> $params */
95    private function generateParameter(RouteToken $part, array $params): string
96    {
97        $name = (string) $part->name();
98        $value = $this->stringParam($params, $name);
99        $constraint = $part->constraint() ?? '[.\w-]+';
100
101        if (!$this->matchesConstraint($constraint, $value)) {
102            throw new InvalidArgumentException('Route parameter does not match constraint: ' . $name);
103        }
104
105        return rawurlencode($value);
106    }
107
108    /** @param array<array-key, mixed> $params */
109    private function generateRemainder(RouteToken $part, array $params): string
110    {
111        $name = (string) $part->name();
112        $value = $this->stringParam($params, $name);
113        $this->assertSafeRemainder($name, $value);
114
115        return implode('/', array_map(rawurlencode(...), explode('/', $value)));
116    }
117
118    /** @param array<array-key, mixed> $params */
119    private function stringParam(array $params, string $name): string
120    {
121        if (!array_key_exists($name, $params)) {
122            throw new InvalidArgumentException('Missing route parameter: ' . $name);
123        }
124
125        /** @psalm-suppress MixedAssignment -- route params are intentionally mixed and validated below */
126        $value = $params[$name];
127
128        if (is_scalar($value) || $value instanceof Stringable) {
129            return (string) $value;
130        }
131
132        throw new InvalidArgumentException('Route parameter must be scalar or Stringable: ' . $name);
133    }
134
135    private function matchesConstraint(string $constraint, string $value): bool
136    {
137        return preg_match('~^(?:' . str_replace('~', '\\~', $constraint) . ')$~', $value) === 1;
138    }
139
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
145        }
146
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
153
154    /** @param array<array-key, mixed> $params */
155    private function assertKnownParams(array $params): void
156    {
157        $names = array_flip($this->parameterNames());
158
159        foreach ($params as $name => $_) {
160            if (!is_string($name) || !array_key_exists($name, $names)) {
161                throw new InvalidArgumentException('Unknown route parameter: ' . (string) $name);
162            }
163        }
164    }
165
166    /** @return list<string> */
167    private function parameterNames(): array
168    {
169        $names = [];
170
171        foreach ($this->tokens as $token) {
172            $name = $token->name();
173
174            if ($name !== null) {
175                $names[] = $name;
176            }
177        }
178
179        return $names;
180    }
181
182    private static function normalize(string $pattern): string
183    {
184        $pattern = '/' . ltrim($pattern, '/');
185
186        return strlen($pattern) > 1 ? rtrim($pattern, '/') : $pattern;
187    }
188
189    /** @return list<RouteToken> */
190    private function parse(string $pattern): array
191    {
192        $pattern = $this->hideInnerBraces($pattern);
193        $tokens = [];
194        $names = [];
195        $literal = '';
196        $offset = 0;
197        $length = strlen($pattern);
198
199        while ($offset < $length) {
200            if (preg_match('/\G\{(\w+)(?::([^}]+))?\}/', $pattern, $matches, 0, $offset) === 1) {
201                $this->flushLiteral($tokens, $literal);
202                $name = $matches[1];
203                $this->assertUniqueName($names, $name);
204                $constraint = isset($matches[2]) ? $this->restoreInnerBraces($matches[2]) : null;
205                $tokens[] = RouteToken::parameter($name, $constraint);
206                $offset += strlen($matches[0]);
207
208                continue;
209            }
210
211            if (preg_match('/\G\.\.\.(\w+)\z/', $pattern, $matches, 0, $offset) === 1) {
212                $this->flushLiteral($tokens, $literal);
213                $name = $matches[1];
214                $this->assertUniqueName($names, $name);
215                $tokens[] = RouteToken::remainder($name);
216                $offset += strlen($matches[0]);
217
218                continue;
219            }
220
221            $literal .= $pattern[$offset];
222            $offset++;
223        }
224
225        $this->flushLiteral($tokens, $literal);
226
227        return $tokens;
228    }
229
230    /**
231     * @param list<RouteToken> $tokens
232     * @param-out list<RouteToken> $tokens
233     */
234    private function flushLiteral(array &$tokens, string &$literal): void
235    {
236        if ($literal === '') {
237            return;
238        }
239
240        $tokens[] = RouteToken::literal($literal);
241        $literal = '';
242    }
243
244    /** @param array<string, true> $names */
245    private function assertUniqueName(array &$names, string $name): void
246    {
247        if (array_key_exists($name, $names)) {
248            throw new ValueError('Duplicate route parameter: ' . $name);
249        }
250
251        $names[$name] = true;
252    }
253
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
257            throw new ValueError('Escaped braces are not allowed: ' . $this->pattern);
258        }
259
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
283        }
284
285        return $new;
286    }
287
288    private function restoreInnerBraces(string $str): string
289    {
290        return str_replace(self::LEFT_BRACE, '{', str_replace(self::RIGHT_BRACE, '}', $str));
291    }
292
293    /** @param list<RouteToken> $tokens */
294    private function compile(array $tokens): string
295    {
296        $regex = '';
297
298        foreach ($tokens as $token) {
299            $regex .= match ($token->type()) {
300                RouteToken::LITERAL => preg_quote($token->value(), '~'),
301                RouteToken::PARAMETER => $this->compileParameter($token),
302                RouteToken::REMAINDER => $this->compileRemainder($token),
303            };
304        }
305
306        return $regex;
307    }
308
309    private function compileParameter(RouteToken $part): string
310    {
311        $name = (string) $part->name();
312        $constraint = $part->constraint();
313
314        return $constraint === null
315            ? "(?P<{$name}>[.\w-]+)"
316            : "(?P<{$name}>" . str_replace('~', '\\~', $constraint) . ')';
317    }
318
319    private function compileRemainder(RouteToken $part): string
320    {
321        return '(?P<' . (string) $part->name() . '>.*)';
322    }
323}

Paths

Below are the source code lines that represent each code path as identified by Xdebug. Please note a path is not necessarily coterminous with a line, a line may contain multiple paths and therefore show up more than once. Please also be aware that some paths may include implicit rather than explicit branches, e.g. an if statement always has an else as part of its logical flow even if you didn't write one.

RoutePattern->__construct
24    public function __construct(string $pattern)
25    {
26        $this->pattern = self::normalize($pattern);
27        $this->tokens = $this->parse($this->pattern);
28        $this->regex = '~^' . $this->compile($this->tokens) . '$~';
29    }
RoutePattern->assertKnownParams
155    private function assertKnownParams(array $params): void
156    {
157        $names = array_flip($this->parameterNames());
158
159        foreach ($params as $name => $_) {
 
159        foreach ($params as $name => $_) {
 
159        foreach ($params as $name => $_) {
160            if (!is_string($name) || !array_key_exists($name, $names)) {
 
160            if (!is_string($name) || !array_key_exists($name, $names)) {
 
160            if (!is_string($name) || !array_key_exists($name, $names)) {
 
161                throw new InvalidArgumentException('Unknown route parameter: ' . (string) $name);
155    private function assertKnownParams(array $params): void
156    {
157        $names = array_flip($this->parameterNames());
158
159        foreach ($params as $name => $_) {
 
159        foreach ($params as $name => $_) {
 
159        foreach ($params as $name => $_) {
160            if (!is_string($name) || !array_key_exists($name, $names)) {
 
160            if (!is_string($name) || !array_key_exists($name, $names)) {
 
160            if (!is_string($name) || !array_key_exists($name, $names)) {
 
159        foreach ($params as $name => $_) {
 
159        foreach ($params as $name => $_) {
 
159        foreach ($params as $name => $_) {
160            if (!is_string($name) || !array_key_exists($name, $names)) {
161                throw new InvalidArgumentException('Unknown route parameter: ' . (string) $name);
162            }
163        }
164    }
155    private function assertKnownParams(array $params): void
156    {
157        $names = array_flip($this->parameterNames());
158
159        foreach ($params as $name => $_) {
 
159        foreach ($params as $name => $_) {
 
159        foreach ($params as $name => $_) {
160            if (!is_string($name) || !array_key_exists($name, $names)) {
 
160            if (!is_string($name) || !array_key_exists($name, $names)) {
 
161                throw new InvalidArgumentException('Unknown route parameter: ' . (string) $name);
155    private function assertKnownParams(array $params): void
156    {
157        $names = array_flip($this->parameterNames());
158
159        foreach ($params as $name => $_) {
 
159        foreach ($params as $name => $_) {
 
159        foreach ($params as $name => $_) {
160            if (!is_string($name) || !array_key_exists($name, $names)) {
 
160            if (!is_string($name) || !array_key_exists($name, $names)) {
 
159        foreach ($params as $name => $_) {
 
159        foreach ($params as $name => $_) {
 
159        foreach ($params as $name => $_) {
160            if (!is_string($name) || !array_key_exists($name, $names)) {
161                throw new InvalidArgumentException('Unknown route parameter: ' . (string) $name);
162            }
163        }
164    }
155    private function assertKnownParams(array $params): void
156    {
157        $names = array_flip($this->parameterNames());
158
159        foreach ($params as $name => $_) {
 
159        foreach ($params as $name => $_) {
 
159        foreach ($params as $name => $_) {
160            if (!is_string($name) || !array_key_exists($name, $names)) {
161                throw new InvalidArgumentException('Unknown route parameter: ' . (string) $name);
162            }
163        }
164    }
155    private function assertKnownParams(array $params): void
156    {
157        $names = array_flip($this->parameterNames());
158
159        foreach ($params as $name => $_) {
 
159        foreach ($params as $name => $_) {
160            if (!is_string($name) || !array_key_exists($name, $names)) {
161                throw new InvalidArgumentException('Unknown route parameter: ' . (string) $name);
162            }
163        }
164    }
RoutePattern->assertSafeRemainder
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
143            throw new InvalidArgumentException('Remainder route parameter must be a relative path: '
144            . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
148            if ($segment === '..') {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
140    private function assertSafeRemainder(string $name, string $value): void
141    {
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
142        if (str_contains($value, "\0") || str_contains($value, '\\') || str_starts_with($value, '/')) {
 
147        foreach (explode('/', $value) as $segment) {
 
147        foreach (explode('/', $value) as $segment) {
148            if ($segment === '..') {
149                throw new InvalidArgumentException('Remainder route parameter must stay relative: ' . $name);
150            }
151        }
152    }
RoutePattern->assertUniqueName
245    private function assertUniqueName(array &$names, string $name): void
246    {
247        if (array_key_exists($name, $names)) {
 
248            throw new ValueError('Duplicate route parameter: ' . $name);
245    private function assertUniqueName(array &$names, string $name): void
246    {
247        if (array_key_exists($name, $names)) {
 
251        $names[$name] = true;
252    }
RoutePattern->compile
294    private function compile(array $tokens): string
295    {
296        $regex = '';
297
298        foreach ($tokens as $token) {
 
298        foreach ($tokens as $token) {
 
299            $regex .= match ($token->type()) {
300                RouteToken::LITERAL => preg_quote($token->value(), '~'),
 
301                RouteToken::PARAMETER => $this->compileParameter($token),
 
302                RouteToken::REMAINDER => $this->compileRemainder($token),
 
302                RouteToken::REMAINDER => $this->compileRemainder($token),
 
302                RouteToken::REMAINDER => $this->compileRemainder($token),
294    private function compile(array $tokens): string
295    {
296        $regex = '';
297
298        foreach ($tokens as $token) {
 
298        foreach ($tokens as $token) {
 
299            $regex .= match ($token->type()) {
300                RouteToken::LITERAL => preg_quote($token->value(), '~'),
 
301                RouteToken::PARAMETER => $this->compileParameter($token),
 
302                RouteToken::REMAINDER => $this->compileRemainder($token),
 
302                RouteToken::REMAINDER => $this->compileRemainder($token),
 
298        foreach ($tokens as $token) {
299            $regex .= match ($token->type()) {
300                RouteToken::LITERAL => preg_quote($token->value(), '~'),
301                RouteToken::PARAMETER => $this->compileParameter($token),
302                RouteToken::REMAINDER => $this->compileRemainder($token),
 
298        foreach ($tokens as $token) {
 
298        foreach ($tokens as $token) {
299            $regex .= match ($token->type()) {
300                RouteToken::LITERAL => preg_quote($token->value(), '~'),
301                RouteToken::PARAMETER => $this->compileParameter($token),
302                RouteToken::REMAINDER => $this->compileRemainder($token),
303            };
304        }
305
306        return $regex;
307    }
294    private function compile(array $tokens): string
295    {
296        $regex = '';
297
298        foreach ($tokens as $token) {
 
298        foreach ($tokens as $token) {
 
299            $regex .= match ($token->type()) {
300                RouteToken::LITERAL => preg_quote($token->value(), '~'),
 
301                RouteToken::PARAMETER => $this->compileParameter($token),
 
301                RouteToken::PARAMETER => $this->compileParameter($token),
 
298        foreach ($tokens as $token) {
299            $regex .= match ($token->type()) {
300                RouteToken::LITERAL => preg_quote($token->value(), '~'),
301                RouteToken::PARAMETER => $this->compileParameter($token),
302                RouteToken::REMAINDER => $this->compileRemainder($token),
 
298        foreach ($tokens as $token) {
 
298        foreach ($tokens as $token) {
299            $regex .= match ($token->type()) {
300                RouteToken::LITERAL => preg_quote($token->value(), '~'),
301                RouteToken::PARAMETER => $this->compileParameter($token),
302                RouteToken::REMAINDER => $this->compileRemainder($token),
303            };
304        }
305
306        return $regex;
307    }
294    private function compile(array $tokens): string
295    {
296        $regex = '';
297
298        foreach ($tokens as $token) {
 
298        foreach ($tokens as $token) {
 
299            $regex .= match ($token->type()) {
300                RouteToken::LITERAL => preg_quote($token->value(), '~'),
 
300                RouteToken::LITERAL => preg_quote($token->value(), '~'),
 
298        foreach ($tokens as $token) {
299            $regex .= match ($token->type()) {
300                RouteToken::LITERAL => preg_quote($token->value(), '~'),
301                RouteToken::PARAMETER => $this->compileParameter($token),
302                RouteToken::REMAINDER => $this->compileRemainder($token),
 
298        foreach ($tokens as $token) {
 
298        foreach ($tokens as $token) {
299            $regex .= match ($token->type()) {
300                RouteToken::LITERAL => preg_quote($token->value(), '~'),
301                RouteToken::PARAMETER => $this->compileParameter($token),
302                RouteToken::REMAINDER => $this->compileRemainder($token),
303            };
304        }
305
306        return $regex;
307    }
294    private function compile(array $tokens): string
295    {
296        $regex = '';
297
298        foreach ($tokens as $token) {
 
298        foreach ($tokens as $token) {
 
298        foreach ($tokens as $token) {
299            $regex .= match ($token->type()) {
300                RouteToken::LITERAL => preg_quote($token->value(), '~'),
301                RouteToken::PARAMETER => $this->compileParameter($token),
302                RouteToken::REMAINDER => $this->compileRemainder($token),
303            };
304        }
305
306        return $regex;
307    }
294    private function compile(array $tokens): string
295    {
296        $regex = '';
297
298        foreach ($tokens as $token) {
 
298        foreach ($tokens as $token) {
299            $regex .= match ($token->type()) {
300                RouteToken::LITERAL => preg_quote($token->value(), '~'),
301                RouteToken::PARAMETER => $this->compileParameter($token),
302                RouteToken::REMAINDER => $this->compileRemainder($token),
303            };
304        }
305
306        return $regex;
307    }
RoutePattern->compileParameter
309    private function compileParameter(RouteToken $part): string
310    {
311        $name = (string) $part->name();
312        $constraint = $part->constraint();
313
314        return $constraint === null
 
315            ? "(?P<{$name}>[.\w-]+)"
 
316            : "(?P<{$name}>" . str_replace('~', '\\~', $constraint) . ')';
317    }
309    private function compileParameter(RouteToken $part): string
310    {
311        $name = (string) $part->name();
312        $constraint = $part->constraint();
313
314        return $constraint === null
 
316            : "(?P<{$name}>" . str_replace('~', '\\~', $constraint) . ')';
 
316            : "(?P<{$name}>" . str_replace('~', '\\~', $constraint) . ')';
 
316            : "(?P<{$name}>" . str_replace('~', '\\~', $constraint) . ')';
 
316            : "(?P<{$name}>" . str_replace('~', '\\~', $constraint) . ')';
317    }
309    private function compileParameter(RouteToken $part): string
310    {
311        $name = (string) $part->name();
312        $constraint = $part->constraint();
313
314        return $constraint === null
 
316            : "(?P<{$name}>" . str_replace('~', '\\~', $constraint) . ')';
 
316            : "(?P<{$name}>" . str_replace('~', '\\~', $constraint) . ')';
 
316            : "(?P<{$name}>" . str_replace('~', '\\~', $constraint) . ')';
 
316            : "(?P<{$name}>" . str_replace('~', '\\~', $constraint) . ')';
317    }
RoutePattern->compileRemainder
319    private function compileRemainder(RouteToken $part): string
320    {
321        return '(?P<' . (string) $part->name() . '>.*)';
322    }
RoutePattern->flushLiteral
234    private function flushLiteral(array &$tokens, string &$literal): void
235    {
236        if ($literal === '') {
 
237            return;
234    private function flushLiteral(array &$tokens, string &$literal): void
235    {
236        if ($literal === '') {
 
240        $tokens[] = RouteToken::literal($literal);
241        $literal = '';
242    }
RoutePattern->generate
78    public function generate(array $params = []): string
79    {
80        $this->assertKnownParams($params);
81        $path = '';
82
83        foreach ($this->tokens as $token) {
 
83        foreach ($this->tokens as $token) {
 
84            $path .= match ($token->type()) {
85                RouteToken::LITERAL => $token->value(),
 
86                RouteToken::PARAMETER => $this->generateParameter($token, $params),
 
87                RouteToken::REMAINDER => $this->generateRemainder($token, $params),
 
87                RouteToken::REMAINDER => $this->generateRemainder($token, $params),
 
87                RouteToken::REMAINDER => $this->generateRemainder($token, $params),
78    public function generate(array $params = []): string
79    {
80        $this->assertKnownParams($params);
81        $path = '';
82
83        foreach ($this->tokens as $token) {
 
83        foreach ($this->tokens as $token) {
 
84            $path .= match ($token->type()) {
85                RouteToken::LITERAL => $token->value(),
 
86                RouteToken::PARAMETER => $this->generateParameter($token, $params),
 
87                RouteToken::REMAINDER => $this->generateRemainder($token, $params),
 
87                RouteToken::REMAINDER => $this->generateRemainder($token, $params),
 
83        foreach ($this->tokens as $token) {
84            $path .= match ($token->type()) {
85                RouteToken::LITERAL => $token->value(),
86                RouteToken::PARAMETER => $this->generateParameter($token, $params),
87                RouteToken::REMAINDER => $this->generateRemainder($token, $params),
 
83        foreach ($this->tokens as $token) {
 
83        foreach ($this->tokens as $token) {
84            $path .= match ($token->type()) {
85                RouteToken::LITERAL => $token->value(),
86                RouteToken::PARAMETER => $this->generateParameter($token, $params),
87                RouteToken::REMAINDER => $this->generateRemainder($token, $params),
88            };
89        }
90
91        return $path;
92    }
78    public function generate(array $params = []): string
79    {
80        $this->assertKnownParams($params);
81        $path = '';
82
83        foreach ($this->tokens as $token) {
 
83        foreach ($this->tokens as $token) {
 
84            $path .= match ($token->type()) {
85                RouteToken::LITERAL => $token->value(),
 
86                RouteToken::PARAMETER => $this->generateParameter($token, $params),
 
86                RouteToken::PARAMETER => $this->generateParameter($token, $params),
 
83        foreach ($this->tokens as $token) {
84            $path .= match ($token->type()) {
85                RouteToken::LITERAL => $token->value(),
86                RouteToken::PARAMETER => $this->generateParameter($token, $params),
87                RouteToken::REMAINDER => $this->generateRemainder($token, $params),
 
83        foreach ($this->tokens as $token) {
 
83        foreach ($this->tokens as $token) {
84            $path .= match ($token->type()) {
85                RouteToken::LITERAL => $token->value(),
86                RouteToken::PARAMETER => $this->generateParameter($token, $params),
87                RouteToken::REMAINDER => $this->generateRemainder($token, $params),
88            };
89        }
90
91        return $path;
92    }
78    public function generate(array $params = []): string
79    {
80        $this->assertKnownParams($params);
81        $path = '';
82
83        foreach ($this->tokens as $token) {
 
83        foreach ($this->tokens as $token) {
 
84            $path .= match ($token->type()) {
85                RouteToken::LITERAL => $token->value(),
 
85                RouteToken::LITERAL => $token->value(),
 
83        foreach ($this->tokens as $token) {
84            $path .= match ($token->type()) {
85                RouteToken::LITERAL => $token->value(),
86                RouteToken::PARAMETER => $this->generateParameter($token, $params),
87                RouteToken::REMAINDER => $this->generateRemainder($token, $params),
 
83        foreach ($this->tokens as $token) {
 
83        foreach ($this->tokens as $token) {
84            $path .= match ($token->type()) {
85                RouteToken::LITERAL => $token->value(),
86                RouteToken::PARAMETER => $this->generateParameter($token, $params),
87                RouteToken::REMAINDER => $this->generateRemainder($token, $params),
88            };
89        }
90
91        return $path;
92    }
78    public function generate(array $params = []): string
79    {
80        $this->assertKnownParams($params);
81        $path = '';
82
83        foreach ($this->tokens as $token) {
 
83        foreach ($this->tokens as $token) {
 
83        foreach ($this->tokens as $token) {
84            $path .= match ($token->type()) {
85                RouteToken::LITERAL => $token->value(),
86                RouteToken::PARAMETER => $this->generateParameter($token, $params),
87                RouteToken::REMAINDER => $this->generateRemainder($token, $params),
88            };
89        }
90
91        return $path;
92    }
78    public function generate(array $params = []): string
79    {
80        $this->assertKnownParams($params);
81        $path = '';
82
83        foreach ($this->tokens as $token) {
 
83        foreach ($this->tokens as $token) {
84            $path .= match ($token->type()) {
85                RouteToken::LITERAL => $token->value(),
86                RouteToken::PARAMETER => $this->generateParameter($token, $params),
87                RouteToken::REMAINDER => $this->generateRemainder($token, $params),
88            };
89        }
90
91        return $path;
92    }
RoutePattern->generateParameter
95    private function generateParameter(RouteToken $part, array $params): string
96    {
97        $name = (string) $part->name();
98        $value = $this->stringParam($params, $name);
99        $constraint = $part->constraint() ?? '[.\w-]+';
100
101        if (!$this->matchesConstraint($constraint, $value)) {
 
102            throw new InvalidArgumentException('Route parameter does not match constraint: ' . $name);
95    private function generateParameter(RouteToken $part, array $params): string
96    {
97        $name = (string) $part->name();
98        $value = $this->stringParam($params, $name);
99        $constraint = $part->constraint() ?? '[.\w-]+';
100
101        if (!$this->matchesConstraint($constraint, $value)) {
 
105        return rawurlencode($value);
106    }
RoutePattern->generateRemainder
109    private function generateRemainder(RouteToken $part, array $params): string
110    {
111        $name = (string) $part->name();
112        $value = $this->stringParam($params, $name);
113        $this->assertSafeRemainder($name, $value);
114
115        return implode('/', array_map(rawurlencode(...), explode('/', $value)));
 
115        return implode('/', array_map(rawurlencode(...), explode('/', $value)));
 
115        return implode('/', array_map(rawurlencode(...), explode('/', $value)));
116    }
109    private function generateRemainder(RouteToken $part, array $params): string
110    {
111        $name = (string) $part->name();
112        $value = $this->stringParam($params, $name);
113        $this->assertSafeRemainder($name, $value);
114
115        return implode('/', array_map(rawurlencode(...), explode('/', $value)));
 
115        return implode('/', array_map(rawurlencode(...), explode('/', $value)));
 
115        return implode('/', array_map(rawurlencode(...), explode('/', $value)));
116    }
RoutePattern->hideInnerBraces
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
257            throw new ValueError('Escaped braces are not allowed: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
257            throw new ValueError('Escaped braces are not allowed: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
257            throw new ValueError('Escaped braces are not allowed: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
257            throw new ValueError('Escaped braces are not allowed: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
257            throw new ValueError('Escaped braces are not allowed: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
257            throw new ValueError('Escaped braces are not allowed: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
 
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
 
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
264            if ($c === '{') {
 
271            if ($c === '}') {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
282            throw new ValueError('Unbalanced braces in route pattern: ' . $this->pattern);
254    private function hideInnerBraces(string $str): string
255    {
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
256        if (str_contains($str, '\\{') || str_contains($str, '\\}')) {
 
260        $new = '';
261        $level = 0;
262
263        foreach (str_split($str) as $c) {
 
263        foreach (str_split($str) as $c) {
264            if ($c === '{') {
265                $level++;
266                $new .= $level > 1 ? self::LEFT_BRACE : '{';
267
268                continue;
269            }
270
271            if ($c === '}') {
272                $new .= $level > 1 ? self::RIGHT_BRACE : '}';
273                $level--;
274
275                continue;
276            }
277
278            $new .= $c;
279        }
280
281        if ($level !== 0) {
 
285        return $new;
286    }
RoutePattern->match
46    public function match(string $path): ?array
47    {
48        $path = $path === '' ? '/' : $path;
 
48        $path = $path === '' ? '/' : $path;
 
48        $path = $path === '' ? '/' : $path;
49
50        /** @psalm-suppress ArgumentTypeCoercion -- route regexes are compiled as non-empty strings */
51        if (preg_match($this->regex, $path, $matches) !== 1) {
 
52            return null;
46    public function match(string $path): ?array
47    {
48        $path = $path === '' ? '/' : $path;
 
48        $path = $path === '' ? '/' : $path;
 
48        $path = $path === '' ? '/' : $path;
49
50        /** @psalm-suppress ArgumentTypeCoercion -- route regexes are compiled as non-empty strings */
51        if (preg_match($this->regex, $path, $matches) !== 1) {
 
55        return self::namedMatches($matches);
56    }
46    public function match(string $path): ?array
47    {
48        $path = $path === '' ? '/' : $path;
 
48        $path = $path === '' ? '/' : $path;
 
48        $path = $path === '' ? '/' : $path;
49
50        /** @psalm-suppress ArgumentTypeCoercion -- route regexes are compiled as non-empty strings */
51        if (preg_match($this->regex, $path, $matches) !== 1) {
 
52            return null;
46    public function match(string $path): ?array
47    {
48        $path = $path === '' ? '/' : $path;
 
48        $path = $path === '' ? '/' : $path;
 
48        $path = $path === '' ? '/' : $path;
49
50        /** @psalm-suppress ArgumentTypeCoercion -- route regexes are compiled as non-empty strings */
51        if (preg_match($this->regex, $path, $matches) !== 1) {
 
55        return self::namedMatches($matches);
56    }
RoutePattern->matchesConstraint
135    private function matchesConstraint(string $constraint, string $value): bool
136    {
137        return preg_match('~^(?:' . str_replace('~', '\\~', $constraint) . ')$~', $value) === 1;
 
137        return preg_match('~^(?:' . str_replace('~', '\\~', $constraint) . ')$~', $value) === 1;
 
137        return preg_match('~^(?:' . str_replace('~', '\\~', $constraint) . ')$~', $value) === 1;
138    }
135    private function matchesConstraint(string $constraint, string $value): bool
136    {
137        return preg_match('~^(?:' . str_replace('~', '\\~', $constraint) . ')$~', $value) === 1;
 
137        return preg_match('~^(?:' . str_replace('~', '\\~', $constraint) . ')$~', $value) === 1;
 
137        return preg_match('~^(?:' . str_replace('~', '\\~', $constraint) . ')$~', $value) === 1;
138    }
RoutePattern->namedMatches
62    private static function namedMatches(array $matches): array
63    {
64        $params = [];
65
66        foreach ($matches as $key => $value) {
 
66        foreach ($matches as $key => $value) {
 
66        foreach ($matches as $key => $value) {
67            if (!is_string($key)) {
 
68                continue;
 
66        foreach ($matches as $key => $value) {
 
66        foreach ($matches as $key => $value) {
67            if (!is_string($key)) {
68                continue;
69            }
70
71            $params[$key] = $value;
72        }
73
74        return $params;
75    }
62    private static function namedMatches(array $matches): array
63    {
64        $params = [];
65
66        foreach ($matches as $key => $value) {
 
66        foreach ($matches as $key => $value) {
 
66        foreach ($matches as $key => $value) {
67            if (!is_string($key)) {
 
66        foreach ($matches as $key => $value) {
67            if (!is_string($key)) {
68                continue;
69            }
70
71            $params[$key] = $value;
 
66        foreach ($matches as $key => $value) {
 
66        foreach ($matches as $key => $value) {
67            if (!is_string($key)) {
68                continue;
69            }
70
71            $params[$key] = $value;
72        }
73
74        return $params;
75    }
62    private static function namedMatches(array $matches): array
63    {
64        $params = [];
65
66        foreach ($matches as $key => $value) {
 
66        foreach ($matches as $key => $value) {
 
66        foreach ($matches as $key => $value) {
67            if (!is_string($key)) {
68                continue;
69            }
70
71            $params[$key] = $value;
72        }
73
74        return $params;
75    }
62    private static function namedMatches(array $matches): array
63    {
64        $params = [];
65
66        foreach ($matches as $key => $value) {
 
66        foreach ($matches as $key => $value) {
67            if (!is_string($key)) {
68                continue;
69            }
70
71            $params[$key] = $value;
72        }
73
74        return $params;
75    }
RoutePattern->normalize
182    private static function normalize(string $pattern): string
183    {
184        $pattern = '/' . ltrim($pattern, '/');
185
186        return strlen($pattern) > 1 ? rtrim($pattern, '/') : $pattern;
 
186        return strlen($pattern) > 1 ? rtrim($pattern, '/') : $pattern;
 
186        return strlen($pattern) > 1 ? rtrim($pattern, '/') : $pattern;
187    }
182    private static function normalize(string $pattern): string
183    {
184        $pattern = '/' . ltrim($pattern, '/');
185
186        return strlen($pattern) > 1 ? rtrim($pattern, '/') : $pattern;
 
186        return strlen($pattern) > 1 ? rtrim($pattern, '/') : $pattern;
 
186        return strlen($pattern) > 1 ? rtrim($pattern, '/') : $pattern;
187    }
RoutePattern->parameterNames
169        $names = [];
170
171        foreach ($this->tokens as $token) {
 
171        foreach ($this->tokens as $token) {
 
172            $name = $token->name();
173
174            if ($name !== null) {
 
171        foreach ($this->tokens as $token) {
172            $name = $token->name();
173
174            if ($name !== null) {
175                $names[] = $name;
 
171        foreach ($this->tokens as $token) {
 
171        foreach ($this->tokens as $token) {
 
171        foreach ($this->tokens as $token) {
172            $name = $token->name();
173
174            if ($name !== null) {
175                $names[] = $name;
176            }
177        }
178
179        return $names;
180    }
169        $names = [];
170
171        foreach ($this->tokens as $token) {
 
171        foreach ($this->tokens as $token) {
 
172            $name = $token->name();
173
174            if ($name !== null) {
 
171        foreach ($this->tokens as $token) {
 
171        foreach ($this->tokens as $token) {
 
171        foreach ($this->tokens as $token) {
172            $name = $token->name();
173
174            if ($name !== null) {
175                $names[] = $name;
176            }
177        }
178
179        return $names;
180    }
169        $names = [];
170
171        foreach ($this->tokens as $token) {
 
171        foreach ($this->tokens as $token) {
 
171        foreach ($this->tokens as $token) {
172            $name = $token->name();
173
174            if ($name !== null) {
175                $names[] = $name;
176            }
177        }
178
179        return $names;
180    }
169        $names = [];
170
171        foreach ($this->tokens as $token) {
 
171        foreach ($this->tokens as $token) {
172            $name = $token->name();
173
174            if ($name !== null) {
175                $names[] = $name;
176            }
177        }
178
179        return $names;
180    }
RoutePattern->parse
190    private function parse(string $pattern): array
191    {
192        $pattern = $this->hideInnerBraces($pattern);
193        $tokens = [];
194        $names = [];
195        $literal = '';
196        $offset = 0;
197        $length = strlen($pattern);
198
199        while ($offset < $length) {
 
199        while ($offset < $length) {
 
225        $this->flushLiteral($tokens, $literal);
226
227        return $tokens;
228    }
190    private function parse(string $pattern): array
191    {
192        $pattern = $this->hideInnerBraces($pattern);
193        $tokens = [];
194        $names = [];
195        $literal = '';
196        $offset = 0;
197        $length = strlen($pattern);
198
199        while ($offset < $length) {
 
199        while ($offset < $length) {
 
200            if (preg_match('/\G\{(\w+)(?::([^}]+))?\}/', $pattern, $matches, 0, $offset) === 1) {
 
201                $this->flushLiteral($tokens, $literal);
202                $name = $matches[1];
203                $this->assertUniqueName($names, $name);
204                $constraint = isset($matches[2]) ? $this->restoreInnerBraces($matches[2]) : null;
 
204                $constraint = isset($matches[2]) ? $this->restoreInnerBraces($matches[2]) : null;
 
204                $constraint = isset($matches[2]) ? $this->restoreInnerBraces($matches[2]) : null;
205                $tokens[] = RouteToken::parameter($name, $constraint);
206                $offset += strlen($matches[0]);
207
208                continue;
 
199        while ($offset < $length) {
 
225        $this->flushLiteral($tokens, $literal);
226
227        return $tokens;
228    }
190    private function parse(string $pattern): array
191    {
192        $pattern = $this->hideInnerBraces($pattern);
193        $tokens = [];
194        $names = [];
195        $literal = '';
196        $offset = 0;
197        $length = strlen($pattern);
198
199        while ($offset < $length) {
 
199        while ($offset < $length) {
 
200            if (preg_match('/\G\{(\w+)(?::([^}]+))?\}/', $pattern, $matches, 0, $offset) === 1) {
 
201                $this->flushLiteral($tokens, $literal);
202                $name = $matches[1];
203                $this->assertUniqueName($names, $name);
204                $constraint = isset($matches[2]) ? $this->restoreInnerBraces($matches[2]) : null;
 
204                $constraint = isset($matches[2]) ? $this->restoreInnerBraces($matches[2]) : null;
 
204                $constraint = isset($matches[2]) ? $this->restoreInnerBraces($matches[2]) : null;
205                $tokens[] = RouteToken::parameter($name, $constraint);
206                $offset += strlen($matches[0]);
207
208                continue;
 
199        while ($offset < $length) {
 
225        $this->flushLiteral($tokens, $literal);
226
227        return $tokens;
228    }
190    private function parse(string $pattern): array
191    {
192        $pattern = $this->hideInnerBraces($pattern);
193        $tokens = [];
194        $names = [];
195        $literal = '';
196        $offset = 0;
197        $length = strlen($pattern);
198
199        while ($offset < $length) {
 
199        while ($offset < $length) {
 
200            if (preg_match('/\G\{(\w+)(?::([^}]+))?\}/', $pattern, $matches, 0, $offset) === 1) {
 
211            if (preg_match('/\G\.\.\.(\w+)\z/', $pattern, $matches, 0, $offset) === 1) {
 
212                $this->flushLiteral($tokens, $literal);
213                $name = $matches[1];
214                $this->assertUniqueName($names, $name);
215                $tokens[] = RouteToken::remainder($name);
216                $offset += strlen($matches[0]);
217
218                continue;
 
199        while ($offset < $length) {
 
225        $this->flushLiteral($tokens, $literal);
226
227        return $tokens;
228    }
190    private function parse(string $pattern): array
191    {
192        $pattern = $this->hideInnerBraces($pattern);
193        $tokens = [];
194        $names = [];
195        $literal = '';
196        $offset = 0;
197        $length = strlen($pattern);
198
199        while ($offset < $length) {
 
199        while ($offset < $length) {
 
200            if (preg_match('/\G\{(\w+)(?::([^}]+))?\}/', $pattern, $matches, 0, $offset) === 1) {
 
211            if (preg_match('/\G\.\.\.(\w+)\z/', $pattern, $matches, 0, $offset) === 1) {
 
199        while ($offset < $length) {
200            if (preg_match('/\G\{(\w+)(?::([^}]+))?\}/', $pattern, $matches, 0, $offset) === 1) {
201                $this->flushLiteral($tokens, $literal);
202                $name = $matches[1];
203                $this->assertUniqueName($names, $name);
204                $constraint = isset($matches[2]) ? $this->restoreInnerBraces($matches[2]) : null;
205                $tokens[] = RouteToken::parameter($name, $constraint);
206                $offset += strlen($matches[0]);
207
208                continue;
209            }
210
211            if (preg_match('/\G\.\.\.(\w+)\z/', $pattern, $matches, 0, $offset) === 1) {
212                $this->flushLiteral($tokens, $literal);
213                $name = $matches[1];
214                $this->assertUniqueName($names, $name);
215                $tokens[] = RouteToken::remainder($name);
216                $offset += strlen($matches[0]);
217
218                continue;
219            }
220
221            $literal .= $pattern[$offset];
 
199        while ($offset < $length) {
 
225        $this->flushLiteral($tokens, $literal);
226
227        return $tokens;
228    }
RoutePattern->pattern
33        return $this->pattern;
34    }
RoutePattern->restoreInnerBraces
288    private function restoreInnerBraces(string $str): string
289    {
290        return str_replace(self::LEFT_BRACE, '{', str_replace(self::RIGHT_BRACE, '}', $str));
 
290        return str_replace(self::LEFT_BRACE, '{', str_replace(self::RIGHT_BRACE, '}', $str));
 
290        return str_replace(self::LEFT_BRACE, '{', str_replace(self::RIGHT_BRACE, '}', $str));
291    }
288    private function restoreInnerBraces(string $str): string
289    {
290        return str_replace(self::LEFT_BRACE, '{', str_replace(self::RIGHT_BRACE, '}', $str));
 
290        return str_replace(self::LEFT_BRACE, '{', str_replace(self::RIGHT_BRACE, '}', $str));
 
290        return str_replace(self::LEFT_BRACE, '{', str_replace(self::RIGHT_BRACE, '}', $str));
291    }
RoutePattern->stringParam
119    private function stringParam(array $params, string $name): string
120    {
121        if (!array_key_exists($name, $params)) {
 
122            throw new InvalidArgumentException('Missing route parameter: ' . $name);
119    private function stringParam(array $params, string $name): string
120    {
121        if (!array_key_exists($name, $params)) {
 
126        $value = $params[$name];
127
128        if (is_scalar($value) || $value instanceof Stringable) {
 
128        if (is_scalar($value) || $value instanceof Stringable) {
 
128        if (is_scalar($value) || $value instanceof Stringable) {
 
129            return (string) $value;
119    private function stringParam(array $params, string $name): string
120    {
121        if (!array_key_exists($name, $params)) {
 
126        $value = $params[$name];
127
128        if (is_scalar($value) || $value instanceof Stringable) {
 
128        if (is_scalar($value) || $value instanceof Stringable) {
 
128        if (is_scalar($value) || $value instanceof Stringable) {
 
132        throw new InvalidArgumentException('Route parameter must be scalar or Stringable: ' . $name);
133    }
119    private function stringParam(array $params, string $name): string
120    {
121        if (!array_key_exists($name, $params)) {
 
126        $value = $params[$name];
127
128        if (is_scalar($value) || $value instanceof Stringable) {
 
128        if (is_scalar($value) || $value instanceof Stringable) {
 
129            return (string) $value;
119    private function stringParam(array $params, string $name): string
120    {
121        if (!array_key_exists($name, $params)) {
 
126        $value = $params[$name];
127
128        if (is_scalar($value) || $value instanceof Stringable) {
 
128        if (is_scalar($value) || $value instanceof Stringable) {
 
132        throw new InvalidArgumentException('Route parameter must be scalar or Stringable: ' . $name);
133    }
RoutePattern->tokens
42        return $this->tokens;
43    }