-
Notifications
You must be signed in to change notification settings - Fork 45
/
RequestHandler.php
107 lines (89 loc) · 3.26 KB
/
RequestHandler.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
<?php
namespace Laravel\Folio;
use Closure;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Routing\Pipeline;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\View;
use Laravel\Folio\Pipeline\MatchedView;
class RequestHandler
{
/**
* Create a new request handler instance.
*
* @param array<int, \Laravel\Folio\MountPath> $mountPaths
*/
public function __construct(
protected array $mountPaths,
protected ?Closure $renderUsing = null,
protected ?Closure $onViewMatch = null,
) {
}
/**
* Handle the incoming request using Folio.
*/
public function __invoke(Request $request): mixed
{
foreach ($this->mountPaths as $mountPath) {
$requestPath = '/'.ltrim($request->path(), '/');
$uri = '/'.ltrim(substr($requestPath, strlen($mountPath->baseUri)), '/');
if ($matchedView = (new Router($mountPath))->match($request, $uri)) {
break;
}
}
abort_unless($matchedView ?? null, 404);
if ($name = $matchedView->name()) {
$request->route()->action['as'] = $name;
}
app(Dispatcher::class)->dispatch(new Events\ViewMatched($matchedView, $mountPath));
$middleware = collect($this->middleware($mountPath, $matchedView));
return (new Pipeline(app()))
->send($request)
->through($middleware->all())
->then(function (Request $request) use ($matchedView, $middleware) {
if ($this->onViewMatch) {
($this->onViewMatch)($matchedView);
}
$response = $this->renderUsing
? ($this->renderUsing)($request, $matchedView)
: $this->toResponse($matchedView);
$app = app();
$app->make(FolioManager::class)->terminateUsing(function () use ($middleware, $app, $request, $response) {
$middleware->filter(fn ($m) => is_string($m) && class_exists($m) && method_exists($m, 'terminate'))
->map(fn (string $m) => $app->make($m))
->each(fn (object $m) => $app->call([$m, 'terminate'], ['request' => $request, 'response' => $response]));
$request->route()->action['as'] = 'laravel-folio';
});
return $response;
});
}
/**
* Get the middleware that should be applied to the matched view.
*/
protected function middleware(MountPath $mountPath, MatchedView $matchedView): array
{
return Route::resolveMiddleware(
$mountPath
->middleware
->match($matchedView)
->prepend('web')
->merge($matchedView->inlineMiddleware())
->unique()
->values()
->all()
);
}
/**
* Create a response instance for the given matched view.
*/
protected function toResponse(MatchedView $matchedView): Response
{
return new Response(
View::file($matchedView->path, $matchedView->data),
200,
['Content-Type' => 'text/html'],
);
}
}