/** * Dispatch middleware * * Given a route (which contains the handler for given middleware), * the $err value passed to $next, $next, and the request and response * objects, dispatch a middleware handler. * * If $err is non-falsy, and the current handler has an arity of 4, * it will be dispatched. * * If $err is falsy, and the current handler has an arity of < 4, * it will be dispatched. * * In all other cases, the handler will be ignored, and $next will be * invoked with the current $err value. * * If an exception is raised when executing the handler, the exception * will be assigned as the value of $err, and $next will be invoked * with it. * * @param Route $route * @param mixed $err * @param ServerRequestInterface $request * @param ResponseInterface $response * @param callable $next */ public function __invoke(Route $route, $err, ServerRequestInterface $request, ResponseInterface $response, callable $next) { $handler = $route->handler; $hasError = null !== $err; switch (true) { case $handler instanceof ErrorMiddlewareInterface: $arity = 4; break; case $handler instanceof MiddlewareInterface: $arity = 3; break; default: $arity = Utils::getArity($handler); break; } // @todo Trigger event with Route, original URL from request? try { if ($hasError && $arity === 4) { return $handler($err, $request, $response, $next); } if (!$hasError && $arity < 4) { return $handler($request, $response, $next); } } catch (Throwable $throwable) { return $next($request, $response, $throwable); } catch (Exception $exception) { return $next($request, $response, $exception); } return $next($request, $response, $err); }
/** * @dataProvider nonCallables */ public function testReturnsZeroForNonCallableArguments($test) { $this->assertSame(0, Utils::getArity($test)); }
public function testPipeWillCreateErrorClosureForObjectImplementingHandle() { $this->markTestIncomplete(); $handler = new TestAsset\ErrorHandler(); $this->middleware->pipe($handler); $r = new ReflectionProperty($this->middleware, 'queue'); $r->setAccessible(true); $queue = $r->getValue($this->middleware); $route = $queue[$queue->count() - 1]; $this->assertInstanceOf('Zend\\Stratigility\\Route', $route); $handler = $route->handler; $this->assertInstanceOf('Closure', $handler); $this->assertEquals(4, Utils::getArity($handler)); }
/** * Dispatch non-interop middleware. * * @param callable $middleware * @param callable $next * @param ServerRequestInterface $request * @param ResponseInterface $response * @param mixed $err * @return ResponseInterface */ private function dispatchCallableMiddleware(callable $middleware, callable $next, ServerRequestInterface $request, ResponseInterface $response, $err = null) { $hasError = null !== $err; switch (true) { case $middleware instanceof ErrorMiddlewareInterface: $arity = 4; break; case $middleware instanceof MiddlewareInterface: $arity = 3; break; default: $arity = Utils::getArity($middleware); break; } if ($this->raiseThrowables) { if ($hasError && $arity === 4) { return $middleware($err, $request, $response, $next); } if (!$hasError && $arity < 4) { return $middleware($request, $response, $next); } return $next($request, $response, $err); } try { if ($hasError && $arity === 4) { return $middleware($err, $request, $response, $next); } if (!$hasError && $arity < 4) { return $middleware($request, $response, $next); } } catch (Throwable $throwable) { return $next($request, $response, $throwable); } catch (\Exception $exception) { return $next($request, $response, $exception); } return $next($request, $response, $err); }
/** * Is the middleware error middleware? * * @todo Remove for 2.0.0 * @param mixed $middleware * @return bool */ private function isErrorMiddleware($middleware) { return $middleware instanceof ErrorMiddlewareInterface || Utils::getArity($middleware) >= 4; }