1
|
|
|
<?php declare(strict_types=1); |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* It's free open-source software released under the MIT License. |
5
|
|
|
* |
6
|
|
|
* @author Anatoly Fenric <[email protected]> |
7
|
|
|
* @copyright Copyright (c) 2018, Anatoly Fenric |
8
|
|
|
* @license https://github.com/sunrise-php/http-router/blob/master/LICENSE |
9
|
|
|
* @link https://github.com/sunrise-php/http-router |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Sunrise\Http\Router; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Import classes |
16
|
|
|
*/ |
17
|
|
|
use Psr\Http\Message\ResponseInterface; |
18
|
|
|
use Psr\Http\Message\ServerRequestInterface; |
19
|
|
|
use Psr\Http\Server\MiddlewareInterface; |
20
|
|
|
use Psr\Http\Server\RequestHandlerInterface; |
21
|
|
|
use Sunrise\Http\Router\RequestHandler\QueueableRequestHandler; |
22
|
|
|
use ReflectionClass; |
23
|
|
|
use ReflectionMethod; |
24
|
|
|
use Reflector; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* Import functions |
28
|
|
|
*/ |
29
|
|
|
use function rtrim; |
30
|
|
|
use function strtoupper; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Route |
34
|
|
|
* |
35
|
|
|
* Use the {@see RouteFactory} factory to create this class. |
36
|
|
|
*/ |
37
|
|
|
class Route implements RouteInterface |
38
|
|
|
{ |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* Server Request attribute name for the route |
42
|
|
|
* |
43
|
|
|
* @var string |
44
|
|
|
*/ |
45
|
|
|
public const ATTR_NAME_FOR_ROUTE = '@route'; |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* Server Request attribute name for the route name |
49
|
|
|
* |
50
|
|
|
* @var string |
51
|
|
|
* |
52
|
|
|
* @deprecated 2.9.0 |
53
|
|
|
*/ |
54
|
|
|
public const ATTR_NAME_FOR_ROUTE_NAME = '@route-name'; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* The route name |
58
|
|
|
* |
59
|
|
|
* @var string |
60
|
|
|
*/ |
61
|
|
|
private $name; |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* The route host |
65
|
|
|
* |
66
|
|
|
* @var string|null |
67
|
|
|
*/ |
68
|
|
|
private $host = null; |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* The route path |
72
|
|
|
* |
73
|
|
|
* @var string |
74
|
|
|
*/ |
75
|
|
|
private $path; |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* The route methods |
79
|
|
|
* |
80
|
|
|
* @var string[] |
81
|
|
|
*/ |
82
|
|
|
private $methods; |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* The route request handler |
86
|
|
|
* |
87
|
|
|
* @var RequestHandlerInterface |
88
|
|
|
*/ |
89
|
|
|
private $requestHandler; |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* The route middlewares |
93
|
|
|
* |
94
|
|
|
* @var MiddlewareInterface[] |
95
|
|
|
*/ |
96
|
|
|
private $middlewares = []; |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* The route attributes |
100
|
|
|
* |
101
|
|
|
* @var array |
102
|
|
|
*/ |
103
|
|
|
private $attributes = []; |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* The route summary |
107
|
|
|
* |
108
|
|
|
* @var string |
109
|
|
|
*/ |
110
|
|
|
private $summary = ''; |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* The route description |
114
|
|
|
* |
115
|
|
|
* @var string |
116
|
|
|
*/ |
117
|
|
|
private $description = ''; |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* The route tags |
121
|
|
|
* |
122
|
|
|
* @var string[] |
123
|
|
|
*/ |
124
|
|
|
private $tags = []; |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* The route holder |
128
|
|
|
* |
129
|
|
|
* @var ReflectionClass|ReflectionMethod|null |
130
|
|
|
*/ |
131
|
|
|
private $holder = null; |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* Constructor of the class |
135
|
|
|
* |
136
|
|
|
* @param string $name |
137
|
|
|
* @param string $path |
138
|
|
|
* @param string[] $methods |
139
|
|
|
* @param RequestHandlerInterface $requestHandler |
140
|
|
|
* @param MiddlewareInterface[] $middlewares |
141
|
|
|
* @param array $attributes |
142
|
|
|
*/ |
143
|
84 |
|
public function __construct( |
144
|
|
|
string $name, |
145
|
|
|
string $path, |
146
|
|
|
array $methods, |
147
|
|
|
RequestHandlerInterface $requestHandler, |
148
|
|
|
array $middlewares = [], |
149
|
|
|
array $attributes = [] |
150
|
|
|
) { |
151
|
84 |
|
$this->setName($name); |
152
|
84 |
|
$this->setPath($path); |
153
|
84 |
|
$this->setMethods(...$methods); |
154
|
84 |
|
$this->setRequestHandler($requestHandler); |
155
|
84 |
|
$this->setMiddlewares(...$middlewares); |
156
|
84 |
|
$this->setAttributes($attributes); |
157
|
84 |
|
} |
158
|
|
|
|
159
|
|
|
/** |
160
|
|
|
* {@inheritdoc} |
161
|
|
|
*/ |
162
|
55 |
|
public function getName() : string |
163
|
|
|
{ |
164
|
55 |
|
return $this->name; |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* {@inheritdoc} |
169
|
|
|
*/ |
170
|
20 |
|
public function getHost() : ?string |
171
|
|
|
{ |
172
|
20 |
|
return $this->host; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* {@inheritdoc} |
177
|
|
|
*/ |
178
|
38 |
|
public function getPath() : string |
179
|
|
|
{ |
180
|
38 |
|
return $this->path; |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* {@inheritdoc} |
185
|
|
|
*/ |
186
|
37 |
|
public function getMethods() : array |
187
|
|
|
{ |
188
|
37 |
|
return $this->methods; |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
/** |
192
|
|
|
* {@inheritdoc} |
193
|
|
|
*/ |
194
|
20 |
|
public function getRequestHandler() : RequestHandlerInterface |
195
|
|
|
{ |
196
|
20 |
|
return $this->requestHandler; |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
/** |
200
|
|
|
* {@inheritdoc} |
201
|
|
|
*/ |
202
|
21 |
|
public function getMiddlewares() : array |
203
|
|
|
{ |
204
|
21 |
|
return $this->middlewares; |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
/** |
208
|
|
|
* {@inheritdoc} |
209
|
|
|
*/ |
210
|
16 |
|
public function getAttributes() : array |
211
|
|
|
{ |
212
|
16 |
|
return $this->attributes; |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
/** |
216
|
|
|
* {@inheritdoc} |
217
|
|
|
*/ |
218
|
3 |
|
public function getSummary() : string |
219
|
|
|
{ |
220
|
3 |
|
return $this->summary; |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* {@inheritdoc} |
225
|
|
|
*/ |
226
|
3 |
|
public function getDescription() : string |
227
|
|
|
{ |
228
|
3 |
|
return $this->description; |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
/** |
232
|
|
|
* {@inheritdoc} |
233
|
|
|
*/ |
234
|
3 |
|
public function getTags() : array |
235
|
|
|
{ |
236
|
3 |
|
return $this->tags; |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
/** |
240
|
|
|
* {@inheritdoc} |
241
|
|
|
*/ |
242
|
3 |
|
public function getHolder() : ?Reflector |
243
|
|
|
{ |
244
|
3 |
|
return $this->holder; |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* {@inheritdoc} |
249
|
|
|
*/ |
250
|
84 |
|
public function setName(string $name) : RouteInterface |
251
|
|
|
{ |
252
|
84 |
|
$this->name = $name; |
253
|
|
|
|
254
|
84 |
|
return $this; |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
/** |
258
|
|
|
* {@inheritdoc} |
259
|
|
|
*/ |
260
|
13 |
|
public function setHost(?string $host) : RouteInterface |
261
|
|
|
{ |
262
|
13 |
|
$this->host = $host; |
263
|
|
|
|
264
|
13 |
|
return $this; |
265
|
|
|
} |
266
|
|
|
|
267
|
|
|
/** |
268
|
|
|
* {@inheritdoc} |
269
|
|
|
*/ |
270
|
84 |
|
public function setPath(string $path) : RouteInterface |
271
|
|
|
{ |
272
|
84 |
|
$this->path = $path; |
273
|
|
|
|
274
|
84 |
|
return $this; |
275
|
|
|
} |
276
|
|
|
|
277
|
|
|
/** |
278
|
|
|
* {@inheritdoc} |
279
|
|
|
*/ |
280
|
84 |
|
public function setMethods(string ...$methods) : RouteInterface |
281
|
|
|
{ |
282
|
84 |
|
foreach ($methods as &$method) { |
283
|
83 |
|
$method = strtoupper($method); |
284
|
|
|
} |
285
|
|
|
|
286
|
84 |
|
$this->methods = $methods; |
287
|
|
|
|
288
|
84 |
|
return $this; |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
/** |
292
|
|
|
* {@inheritdoc} |
293
|
|
|
*/ |
294
|
84 |
|
public function setRequestHandler(RequestHandlerInterface $requestHandler) : RouteInterface |
295
|
|
|
{ |
296
|
84 |
|
$this->requestHandler = $requestHandler; |
297
|
|
|
|
298
|
84 |
|
return $this; |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
/** |
302
|
|
|
* {@inheritdoc} |
303
|
|
|
*/ |
304
|
84 |
|
public function setMiddlewares(MiddlewareInterface ...$middlewares) : RouteInterface |
305
|
|
|
{ |
306
|
84 |
|
$this->middlewares = $middlewares; |
307
|
|
|
|
308
|
84 |
|
return $this; |
309
|
|
|
} |
310
|
|
|
|
311
|
|
|
/** |
312
|
|
|
* {@inheritdoc} |
313
|
|
|
*/ |
314
|
84 |
|
public function setAttributes(array $attributes) : RouteInterface |
315
|
|
|
{ |
316
|
84 |
|
$this->attributes = $attributes; |
317
|
|
|
|
318
|
84 |
|
return $this; |
319
|
|
|
} |
320
|
|
|
|
321
|
|
|
/** |
322
|
|
|
* {@inheritdoc} |
323
|
|
|
*/ |
324
|
11 |
|
public function setSummary(string $summary) : RouteInterface |
325
|
|
|
{ |
326
|
11 |
|
$this->summary = $summary; |
327
|
|
|
|
328
|
11 |
|
return $this; |
329
|
|
|
} |
330
|
|
|
|
331
|
|
|
/** |
332
|
|
|
* {@inheritdoc} |
333
|
|
|
*/ |
334
|
11 |
|
public function setDescription(string $description) : RouteInterface |
335
|
|
|
{ |
336
|
11 |
|
$this->description = $description; |
337
|
|
|
|
338
|
11 |
|
return $this; |
339
|
|
|
} |
340
|
|
|
|
341
|
|
|
/** |
342
|
|
|
* {@inheritdoc} |
343
|
|
|
*/ |
344
|
11 |
|
public function setTags(string ...$tags) : RouteInterface |
345
|
|
|
{ |
346
|
11 |
|
$this->tags = $tags; |
347
|
|
|
|
348
|
11 |
|
return $this; |
349
|
|
|
} |
350
|
|
|
|
351
|
|
|
/** |
352
|
|
|
* {@inheritdoc} |
353
|
|
|
*/ |
354
|
11 |
|
public function setHolder(?Reflector $holder) : RouteInterface |
355
|
|
|
{ |
356
|
11 |
|
$this->holder = $holder; |
357
|
|
|
|
358
|
11 |
|
return $this; |
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
/** |
362
|
|
|
* {@inheritdoc} |
363
|
|
|
*/ |
364
|
3 |
|
public function addPrefix(string $prefix) : RouteInterface |
365
|
|
|
{ |
366
|
|
|
// https://github.com/sunrise-php/http-router/issues/26 |
367
|
3 |
|
$prefix = rtrim($prefix, '/'); |
368
|
|
|
|
369
|
3 |
|
$this->path = $prefix . $this->path; |
370
|
|
|
|
371
|
3 |
|
return $this; |
372
|
|
|
} |
373
|
|
|
|
374
|
|
|
/** |
375
|
|
|
* {@inheritdoc} |
376
|
|
|
*/ |
377
|
2 |
|
public function addSuffix(string $suffix) : RouteInterface |
378
|
|
|
{ |
379
|
2 |
|
$this->path .= $suffix; |
380
|
|
|
|
381
|
2 |
|
return $this; |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
/** |
385
|
|
|
* {@inheritdoc} |
386
|
|
|
*/ |
387
|
3 |
|
public function addMethod(string ...$methods) : RouteInterface |
388
|
|
|
{ |
389
|
3 |
|
foreach ($methods as $method) { |
390
|
3 |
|
$this->methods[] = strtoupper($method); |
391
|
|
|
} |
392
|
|
|
|
393
|
3 |
|
return $this; |
394
|
|
|
} |
395
|
|
|
|
396
|
|
|
/** |
397
|
|
|
* {@inheritdoc} |
398
|
|
|
*/ |
399
|
5 |
|
public function addMiddleware(MiddlewareInterface ...$middlewares) : RouteInterface |
400
|
|
|
{ |
401
|
5 |
|
foreach ($middlewares as $middleware) { |
402
|
5 |
|
$this->middlewares[] = $middleware; |
403
|
|
|
} |
404
|
|
|
|
405
|
5 |
|
return $this; |
406
|
|
|
} |
407
|
|
|
|
408
|
|
|
/** |
409
|
|
|
* {@inheritdoc} |
410
|
|
|
*/ |
411
|
8 |
|
public function withAddedAttributes(array $attributes) : RouteInterface |
412
|
|
|
{ |
413
|
8 |
|
$clone = clone $this; |
414
|
|
|
|
415
|
8 |
|
foreach ($attributes as $key => $value) { |
416
|
1 |
|
$clone->attributes[$key] = $value; |
417
|
|
|
} |
418
|
|
|
|
419
|
8 |
|
return $clone; |
420
|
|
|
} |
421
|
|
|
|
422
|
|
|
/** |
423
|
|
|
* {@inheritdoc} |
424
|
|
|
*/ |
425
|
8 |
|
public function handle(ServerRequestInterface $request) : ResponseInterface |
426
|
|
|
{ |
427
|
8 |
|
$request = $request->withAttribute(self::ATTR_NAME_FOR_ROUTE, $this); |
428
|
|
|
|
429
|
|
|
/** @todo Must be removed from the 3.0.0 version */ |
430
|
8 |
|
$request = $request->withAttribute(self::ATTR_NAME_FOR_ROUTE_NAME, $this->name); |
|
|
|
|
431
|
|
|
|
432
|
8 |
|
foreach ($this->attributes as $key => $value) { |
433
|
1 |
|
$request = $request->withAttribute($key, $value); |
434
|
|
|
} |
435
|
|
|
|
436
|
8 |
|
if (empty($this->middlewares)) { |
437
|
6 |
|
return $this->requestHandler->handle($request); |
438
|
|
|
} |
439
|
|
|
|
440
|
2 |
|
$handler = new QueueableRequestHandler($this->requestHandler); |
441
|
2 |
|
$handler->add(...$this->middlewares); |
442
|
|
|
|
443
|
2 |
|
return $handler->handle($request); |
444
|
|
|
} |
445
|
|
|
} |
446
|
|
|
|
This class constant has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.