config = $config; $this->logger = $logger; } /** * @param Controller $controller * @param string $methodName * @param Exception $exception * * @return Response * @throws Exception */ #[\Override] public function afterException($controller, $methodName, Exception $exception) { $reflectionMethod = new ReflectionMethod($controller, $methodName); $attributes = $reflectionMethod->getAttributes(TrapError::class); if ($attributes === []) { return parent::afterException($controller, $methodName, $exception); } if ($exception instanceof ClientException) { return JsonResponse::failWith($exception); } if ($exception instanceof DoesNotExistException) { return JSONResponse::fail([], Http::STATUS_NOT_FOUND); } if ($exception instanceof NotImplemented) { return JSONResponse::fail([], Http::STATUS_NOT_IMPLEMENTED); } $temporary = $this->isTemporaryException($exception); if ($temporary) { $this->logger->warning($exception->getMessage(), [ 'exception' => $exception, ]); } else { $this->logger->error($exception->getMessage(), [ 'exception' => $exception, ]); } if ($this->config->getSystemValue('debug', false)) { return JsonResponse::errorFromThrowable( $exception, $temporary ? Http::STATUS_SERVICE_UNAVAILABLE : Http::STATUS_INTERNAL_SERVER_ERROR, [ 'debug' => true, ] ); } return JsonResponse::error( 'Server error', $temporary ? Http::STATUS_SERVICE_UNAVAILABLE : Http::STATUS_INTERNAL_SERVER_ERROR ); } private function isTemporaryException(Throwable $ex): bool { if ($ex instanceof ServiceException && $ex->getPrevious() !== null) { $ex = $ex->getPrevious(); } if ($ex instanceof Horde_Imap_Client_Exception) { return in_array( $ex->getCode(), [ Horde_Imap_Client_Exception::DISCONNECT, Horde_Imap_Client_Exception::SERVER_READERROR, Horde_Imap_Client_Exception::SERVER_WRITEERROR, ], true ); } return false; } }