getBody()->write(json_encode($data)); return $response->withStatus($statusCode)->withHeader('Content-Type', 'application/json'); } public function parseError(Throwable $exception): array { return [ 'code' => $exception->getCode(), 'message' => $exception->getMessage(), 'file' => $this->parseFilename($exception->getFile()), 'line' => $exception->getLine(), 'trace' => $this->parseStack($exception->getTraceAsString()), 'previous' => ($exception->getPrevious() instanceof Throwable) ? $this->parseError($exception->getPrevious()) : '' ]; } public function withError(ResponseInterface $response, Throwable $exception): ResponseInterface { $output = $this->parseError($exception); $response->getBody()->write(json_encode(['error' => $output])); return $response->withHeader('Content-Type', 'application/json'); } public function withErrors(ResponseInterface $response, array $errors): ResponseInterface { foreach ($errors as $error) { $response = $this->withError($response, $error); } return $response; } protected function parseFilename(string $filename): string { return str_replace('/code/', '', $filename); } protected function parseStack(string|array $stack): array { if (is_string($stack)) { $stack = explode(PHP_EOL, $stack); } $output = []; foreach ($stack as $line) { $index = substr($line, 1, strpos($line, ' ') - 1); $content = substr($line, strpos($line, ' ') + 1); if (str_contains($line, '{main}')) { $output [] = [ 'stack' => $index, 'message' => $content ]; continue; } if (str_starts_with($content, '[internal function]')) { $content = substr($content, strlen('[internal function]: ')); $output [] = [ 'stack' => $index, 'type' => 'internal function', 'message' => $content ]; continue; } $fileData = substr($content, 0, strpos($content, ' ')); $file = substr($fileData, 0, strrpos($fileData, '(')); $fileLine = (int) substr($fileData, strrpos($fileData, '(') + 1, -2); $error = substr($content, strlen($fileData) + 1); $output []= [ 'stack' => $index, 'file' => $this->parseFilename($file), 'line' => $fileLine, 'error' => $error ]; } return $output; } }