-
-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathRouteResult.php
188 lines (167 loc) · 5.22 KB
/
RouteResult.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
<?php
declare(strict_types=1);
namespace Mezzio\Router;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use function assert;
/**
* Value object representing the results of routing.
*
* RouterInterface::match() is defined as returning a RouteResult instance,
* which will contain the following state:
*
* - isSuccess()/isFailure() indicate whether routing succeeded or not.
* - On success, it will contain:
* - the matched route name (typically the path)
* - the matched route middleware
* - any parameters matched by routing
* - On failure:
* - isMethodFailure() further qualifies a routing failure to indicate that it
* was due to using an HTTP method not allowed for the given path.
* - If the failure was due to HTTP method negotiation, it will contain the
* list of allowed HTTP methods.
*
* RouteResult instances are consumed by the Application in the routing
* middleware.
*/
final class RouteResult implements MiddlewareInterface
{
/**
* Only allow instantiation via factory methods.
*
* @param bool $success Success state of routing.
* @param Route|null $route Route matched during routing.
* @param null|string $matchedRouteName The name of the matched route. Null if routing failed.
* @param null|list<string> $allowedMethods Methods allowed by the route, or null if all methods are allowed.
* @param array<string, mixed> $matchedParams Matched routing parameters for successful routes.
*/
private function __construct(
private readonly bool $success,
private readonly ?Route $route,
private readonly ?string $matchedRouteName,
private readonly ?array $allowedMethods,
private readonly array $matchedParams = [],
) {
}
/**
* Create an instance representing a route success from the matching route.
*
* @param array<string, mixed> $params Parameters associated with the matched route, if any.
*/
public static function fromRoute(Route $route, array $params = []): self
{
return new self(
true,
$route,
$route->getName(),
$route->getAllowedMethods(),
$params,
);
}
/**
* Create an instance representing a route failure.
*
* @param null|list<string> $methods HTTP methods allowed for the current URI, if any.
* null is equivalent to allowing any HTTP method; empty array means none.
*/
public static function fromRouteFailure(?array $methods): self
{
return new self(
false,
null,
null,
$methods,
[],
);
}
/**
* Process the result as middleware.
*
* If the result represents a failure, it passes handling to the handler.
*
* Otherwise, it processes the composed middleware using the provided request
* and handler.
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
if ($this->isFailure()) {
return $handler->handle($request);
}
$route = $this->getMatchedRoute();
assert($route instanceof MiddlewareInterface);
return $route->process($request, $handler);
}
/**
* Does the result represent successful routing?
*/
public function isSuccess(): bool
{
return $this->success;
}
/**
* Retrieve the route that resulted in the route match.
*
* @return false|Route false if representing a routing failure; Route instance otherwise.
*/
public function getMatchedRoute(): Route|false
{
return $this->route ?? false;
}
/**
* Retrieve the matched route name, if possible.
*
* If this result represents a failure, return false; otherwise, return the
* matched route name.
*/
public function getMatchedRouteName(): false|string
{
if ($this->isFailure()) {
return false;
}
assert($this->matchedRouteName !== null);
return $this->matchedRouteName;
}
/**
* Returns the matched params.
*
* Guaranteed to return an array, even if it is simply empty.
*
* @return array<string, mixed>
*/
public function getMatchedParams(): array
{
return $this->matchedParams;
}
/**
* Is this a routing failure result?
*/
public function isFailure(): bool
{
return ! $this->success;
}
/**
* Does the result represent failure to route due to HTTP method?
*/
public function isMethodFailure(): bool
{
if ($this->isSuccess() || $this->allowedMethods === Route::HTTP_METHOD_ANY) {
return false;
}
return true;
}
/**
* Retrieve the allowed methods for the route failure.
*
* @return null|list<string> HTTP methods allowed
*/
public function getAllowedMethods(): ?array
{
if ($this->isSuccess()) {
assert($this->route !== null);
return $this->route->getAllowedMethods();
}
return $this->allowedMethods;
}
}