documentModel = new DocumentModel(); } public function __invoke(ServerRequestInterface $request) { $userId = (int)($request->getAttribute('api_user_id') ?? 0); $companyId = (int)($request->getAttribute('api_company_id') ?? 0); if ($userId <= 0 || $companyId <= 0) { return ResponseLib::sendFail('Unauthorized', [], 'E_VALIDATE')->withStatus(401); } $body = json_decode((string)$request->getBody(), true) ?? []; try { val::key('document_type', val::stringType()->notEmpty()->length(1, 255)) ->assert($body); } catch (ValidationException $e) { return ResponseLib::sendFail('Validation failed: ' . $e->getFullMessage(), [], 'E_VALIDATE')->withStatus(400); } $documentType = (string)$body['document_type']; try { $doc = $this->documentModel->findLatestByUserIdAndType($userId, $documentType); } catch (\Throwable $e) { return ResponseLib::sendFail('Database error: ' . $e->getMessage(), [], 'E_DATABASE')->withStatus(500); } if (!$doc) { return ResponseLib::sendFail('Document not found', [], 'E_NOT_FOUND')->withStatus(404); } $path = (string)($doc['document_path'] ?? ''); if ($path === '' || !is_file($path)) { return ResponseLib::sendFail('Document file not found', [], 'E_NOT_FOUND')->withStatus(404); } $filename = basename($path); $content = @file_get_contents($path); if ($content === false) { return ResponseLib::sendFail('Failed to read document file', [], 'E_INTERNAL')->withStatus(500); } $contentType = 'application/octet-stream'; $ext = strtolower((string)pathinfo($filename, PATHINFO_EXTENSION)); if ($ext === 'pdf') { $contentType = 'application/pdf'; } return new Response( 200, [ 'Content-Type' => $contentType, 'Content-Disposition' => 'attachment; filename="' . $filename . '"', ], $content ); } }