| 1 | <?php |
||
| 2 | |||
| 3 | declare(strict_types=1); |
||
| 4 | |||
| 5 | namespace Yiisoft\Middleware\Dispatcher; |
||
| 6 | |||
| 7 | use Closure; |
||
| 8 | use Psr\EventDispatcher\EventDispatcherInterface; |
||
| 9 | use Psr\Http\Message\ResponseInterface; |
||
| 10 | use Psr\Http\Message\ServerRequestInterface; |
||
| 11 | use Psr\Http\Server\MiddlewareInterface; |
||
| 12 | use Psr\Http\Server\RequestHandlerInterface; |
||
| 13 | use RuntimeException; |
||
| 14 | use Yiisoft\Middleware\Dispatcher\Event\AfterMiddleware; |
||
| 15 | use Yiisoft\Middleware\Dispatcher\Event\BeforeMiddleware; |
||
| 16 | |||
| 17 | final class MiddlewareStack implements RequestHandlerInterface |
||
| 18 | { |
||
| 19 | /** |
||
| 20 | * Contains a stack of middleware wrapped in handlers. |
||
| 21 | * Each handler points to the handler of middleware that will be processed next. |
||
| 22 | * |
||
| 23 | * @var RequestHandlerInterface|null stack of middleware |
||
| 24 | */ |
||
| 25 | private ?RequestHandlerInterface $stack = null; |
||
| 26 | |||
| 27 | /** |
||
| 28 | * @param Closure[] $middlewares Middlewares. |
||
| 29 | * @param RequestHandlerInterface $fallbackHandler Fallback handler |
||
| 30 | * @param EventDispatcherInterface|null $eventDispatcher Event dispatcher to use for triggering before/after |
||
| 31 | * middleware events. |
||
| 32 | */ |
||
| 33 | 8 | public function __construct( |
|
| 34 | private array $middlewares, |
||
| 35 | private RequestHandlerInterface $fallbackHandler, |
||
| 36 | private ?EventDispatcherInterface $eventDispatcher = null |
||
| 37 | ) { |
||
| 38 | 8 | if ($middlewares === []) { |
|
| 39 | 1 | throw new RuntimeException('Stack is empty.'); |
|
| 40 | } |
||
| 41 | } |
||
| 42 | |||
| 43 | 7 | public function handle(ServerRequestInterface $request): ResponseInterface |
|
| 44 | { |
||
| 45 | 7 | if ($this->stack === null) { |
|
| 46 | 7 | $this->build(); |
|
| 47 | } |
||
| 48 | |||
| 49 | 7 | return $this->stack->handle($request); |
|
|
0 ignored issues
–
show
|
|||
| 50 | } |
||
| 51 | |||
| 52 | /** |
||
| 53 | * @psalm-assert RequestHandlerInterface $this->stack |
||
| 54 | */ |
||
| 55 | 7 | private function build(): void |
|
| 56 | { |
||
| 57 | 7 | $handler = $this->fallbackHandler; |
|
| 58 | |||
| 59 | 7 | foreach ($this->middlewares as $middleware) { |
|
| 60 | 7 | $handler = $this->wrap($middleware, $handler); |
|
| 61 | } |
||
| 62 | |||
| 63 | 7 | $this->stack = $handler; |
|
| 64 | } |
||
| 65 | |||
| 66 | /** |
||
| 67 | * Wrap handler by middlewares. |
||
| 68 | */ |
||
| 69 | 7 | private function wrap(Closure $middlewareFactory, RequestHandlerInterface $handler): RequestHandlerInterface |
|
| 70 | { |
||
| 71 | 7 | return new class ($middlewareFactory, $handler, $this->eventDispatcher) implements RequestHandlerInterface { |
|
| 72 | private Closure $middlewareFactory; |
||
| 73 | private ?MiddlewareInterface $middleware = null; |
||
| 74 | |||
| 75 | public function __construct( |
||
| 76 | Closure $middlewareFactory, |
||
| 77 | private RequestHandlerInterface $handler, |
||
| 78 | private ?EventDispatcherInterface $eventDispatcher |
||
| 79 | ) { |
||
| 80 | 7 | $this->middlewareFactory = $middlewareFactory; |
|
| 81 | } |
||
| 82 | |||
| 83 | public function handle(ServerRequestInterface $request): ResponseInterface |
||
| 84 | { |
||
| 85 | 7 | if ($this->middleware === null) { |
|
| 86 | /** @var MiddlewareInterface */ |
||
| 87 | 7 | $this->middleware = ($this->middlewareFactory)(); |
|
|
0 ignored issues
–
show
|
|||
| 88 | } |
||
| 89 | |||
| 90 | 7 | $this->eventDispatcher?->dispatch(new BeforeMiddleware($this->middleware, $request)); |
|
| 91 | |||
| 92 | try { |
||
| 93 | 7 | return $response = $this->middleware->process($request, $this->handler); |
|
| 94 | } finally { |
||
| 95 | 7 | $this->eventDispatcher?->dispatch(new AfterMiddleware($this->middleware, $response ?? null)); |
|
| 96 | } |
||
| 97 | } |
||
| 98 | 7 | }; |
|
| 99 | } |
||
| 100 | } |
||
| 101 |
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.