middlewareLock) { throw new RuntimeException('Middleware can’t be added once the stack is dequeuing'); } if (is_null($this->stack)) { $this->seedMiddlewareStack(); } $next = $this->stack->top(); $this->stack[] = function (ServerRequestInterface $req, ResponseInterface $res) use ($callable, $next) { $result = call_user_func($callable, $req, $res, $next); if ($result instanceof ResponseInterface === false) { throw new UnexpectedValueException( 'Middleware must return instance of \Psr\Http\Message\ResponseInterface' ); } return $result; }; return $this; } /** * Seed middleware stack with first callable * * @param callable $kernel The last item to run as middleware * * @throws RuntimeException if the stack is seeded more than once */ protected function seedMiddlewareStack(callable $kernel = null) { if (!is_null($this->stack)) { throw new RuntimeException('MiddlewareStack can only be seeded once.'); } if ($kernel === null) { $kernel = $this; } $this->stack = new SplStack; $this->stack->setIteratorMode(SplDoublyLinkedList::IT_MODE_LIFO | SplDoublyLinkedList::IT_MODE_KEEP); $this->stack[] = $kernel; } /** * Call middleware stack * * @param ServerRequestInterface $req A request object * @param ResponseInterface $res A response object * * @return ResponseInterface */ public function callMiddlewareStack(ServerRequestInterface $req, ResponseInterface $res) { if (is_null($this->stack)) { $this->seedMiddlewareStack(); } /** @var callable $start */ $start = $this->stack->top(); $this->middlewareLock = true; $resp = $start($req, $res); $this->middlewareLock = false; return $resp; } }