Files
survey/api/responses.php
T

255 lines
12 KiB
PHP

<?php
/**
* Survey Responses API
* POST ?action=submit — Submit response (public)
* GET ?action=list&survey_id=X — List responses for a survey
* GET ?action=get&id=X — Get single response detail
*/
require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../config/auth.php';
require_once __DIR__ . '/../config/mail.php';
require_once __DIR__ . '/certificate_helper.php';
require_once __DIR__ . '/mail_helper.php';
header('Content-Type: application/json; charset=utf-8');
$action = $_GET['action'] ?? '';
// Public endpoint
if ($action === 'submit') {
submitResponse();
exit;
}
requireLogin();
switch ($action) {
case 'list':
listResponses();
break;
case 'get':
getResponse();
break;
default:
jsonResponse(['error' => 'Invalid action'], 400);
}
function submitResponse() {
$input = getInput();
$surveyLink = $input['survey_link'] ?? '';
$answers = $input['answers'] ?? [];
$respondentInfo = $input['respondent_info'] ?? [];
if (empty($surveyLink)) {
jsonResponse(['error' => 'Missing survey link'], 400);
}
$db = getDB();
// Find survey
$stmt = $db->prepare("SELECT id, status, title, has_certificate, certificate_template, cert_name_y, cert_code_y FROM surveys WHERE unique_link = ?");
$stmt->execute([$surveyLink]);
$survey = $stmt->fetch();
if (!$survey) jsonResponse(['error' => 'ไม่พบแบบสอบถาม'], 404);
if ($survey['status'] !== 'active') jsonResponse(['error' => 'แบบสอบถามนี้ปิดรับคำตอบแล้ว'], 400);
// ตรวจสอบข้อมูลเพื่อรับเกียรติบัตรล่วงหน้า (และทำ Fallback ตรวจจับจากคำตอบ)
if (!empty($survey['has_certificate'])) {
$email = trim($respondentInfo['email'] ?? '');
$name = trim($respondentInfo['name'] ?? '');
// Fallback: หากส่งค่าจาก JS เป็นค่าว่าง (เช่น กรณีเบราว์เซอร์แคชไฟล์เก่า) ค้นหาอีเมลจากคำตอบ
if (empty($email) || empty($name)) {
foreach ($answers as $ans) {
$val = trim($ans['value'] ?? '');
if (filter_var($val, FILTER_VALIDATE_EMAIL) &&
(str_ends_with($val, '@tapee.ac.th') || str_ends_with($val, '@student.tapee.ac.th') || str_ends_with($val, '@gmail.com') || str_ends_with($val, '@gmil.com'))) {
$email = $val;
}
}
if (!empty($email) && empty($name)) {
// ค้นหาช่องคำตอบชื่อจริง
$stmtQ = $db->prepare("
SELECT q.id
FROM survey_questions q
JOIN survey_sections s ON q.section_id = s.id
WHERE s.survey_id = ? AND (q.question_text LIKE '%ชื่อ%' OR q.question_text LIKE '%นามสกุล%')
LIMIT 1
");
$stmtQ->execute([$survey['id']]);
$qRow = $stmtQ->fetch();
if ($qRow) {
$nameQuestionId = $qRow['id'];
foreach ($answers as $ans) {
if (($ans['question_id'] ?? 0) == $nameQuestionId) {
$name = trim($ans['value'] ?? '');
break;
}
}
}
}
// อัปเดตกลับเข้าตัวแปร respondentInfo เพื่อเตรียมบันทึกลง JSON
$respondentInfo['email'] = $email;
$respondentInfo['name'] = $name;
}
// ตรวจสอบการกรอกอีเมลซ้ำสำหรับแบบสอบถามที่แจกเกียรติบัตร (1 อีเมล ต่อ 1 สิทธิ์)
if (!empty($email)) {
$stmtCheck = $db->prepare("
SELECT COUNT(*) FROM survey_responses
WHERE survey_id = ? AND LOWER(JSON_UNQUOTE(JSON_EXTRACT(respondent_info, '$.email'))) = ?
");
$stmtCheck->execute([$survey['id'], strtolower($email)]);
if ($stmtCheck->fetchColumn() > 0) {
jsonResponse(['error' => 'อีเมลนี้เคยทำแบบประเมินและขอรับเกียรติบัตรไปแล้ว (สามารถลงทะเบียนได้เพียง 1 ครั้งต่อ 1 อีเมลเท่านั้น)'], 400);
}
}
}
$db->beginTransaction();
try {
$stmt = $db->prepare("INSERT INTO survey_responses (survey_id, respondent_info, ip_address) VALUES (?, ?, ?)");
$stmt->execute([
$survey['id'],
json_encode($respondentInfo, JSON_UNESCAPED_UNICODE),
$_SERVER['REMOTE_ADDR'] ?? ''
]);
$responseId = $db->lastInsertId();
foreach ($answers as $answer) {
$questionId = (int)($answer['question_id'] ?? 0);
$value = $answer['value'] ?? '';
if ($questionId) {
$stmt2 = $db->prepare("INSERT INTO response_answers (response_id, question_id, answer_value) VALUES (?, ?, ?)");
$stmt2->execute([$responseId, $questionId, is_array($value) ? json_encode($value, JSON_UNESCAPED_UNICODE) : $value]);
}
}
$db->commit();
// ดำเนินการสร้างและจัดส่งเกียรติบัตรอัตโนมัติหากเปิดใช้งานเกียรติบัตรสำหรับแบบสอบถามนี้
if (!empty($survey['has_certificate'])) {
$email = $respondentInfo['email'] ?? '';
$name = $respondentInfo['name'] ?? '';
if (!empty($email) && !empty($name)) {
// ดึงข้อมูลหัวข้อแบบสอบถามเพื่อใช้เป็นชื่อหัวข้ออีเมล
$surveyTitle = $survey['title'] ?? 'โครงการอบรม';
// สร้างรหัสตรวจสอบเกียรติบัตรที่ไม่ซ้ำกัน (เช่น TPU-2569-0016)
$thaiYear = date('Y') + 543;
$certCode = 'TPU-' . $thaiYear . '-' . str_pad($responseId, 4, '0', STR_PAD_LEFT);
// อัปเดตรหัสตรวจสอบลงในฐานข้อมูลตาราง survey_responses
$stmtUpdateCode = $db->prepare("UPDATE survey_responses SET cert_code = ? WHERE id = ?");
$stmtUpdateCode->execute([$certCode, $responseId]);
// สร้างโฟลเดอร์ชั่วคราวสำหรับเกียรติบัตร (ถ้ายังไม่มี)
$tempDir = __DIR__ . '/../temp_certificates';
if (!is_dir($tempDir)) {
mkdir($tempDir, 0777, true);
}
chmod($tempDir, 0777);
$pdfFileName = 'cert_' . $responseId . '_' . time() . '.pdf';
$pdfPath = $tempDir . '/' . $pdfFileName;
try {
// 1. สร้างเกียรติบัตร PDF โดยใช้พิกัดและเทมเพลตที่ตั้งค่าเฉพาะของแบบสอบถามนี้
$yPos = isset($survey['cert_name_y']) ? (double)$survey['cert_name_y'] : 82.5;
$codeY = isset($survey['cert_code_y']) ? (double)$survey['cert_code_y'] : 190.5;
$bgImage = $survey['certificate_template'] ?? '';
generateCertificate($name, $pdfPath, $yPos, $certCode, $bgImage, $codeY);
// 2. ส่งอีเมลพร้อมแนบเกียรติบัตร
sendCertificateEmail($email, $name, $pdfPath, $surveyTitle);
// 3. ลบไฟล์ PDF ชั่วคราวหลังจากส่งสำเร็จ
if (file_exists($pdfPath)) {
unlink($pdfPath);
}
} catch (Exception $mailEx) {
// บันทึกข้อผิดพลาดกรณีส่งเมลไม่สำเร็จ แต่ไม่ทำให้การส่งแบบสอบถามทั้งหมดล้มเหลว
// เพื่อให้ผู้ใช้ตอบแบบสอบถามเสร็จสมบูรณ์
error_log("Certificate dispatch failed for response ID " . $responseId . ": " . $mailEx->getMessage());
}
}
}
jsonResponse(['success' => true, 'message' => 'ส่งแบบสอบถามสำเร็จ ขอบคุณค่ะ/ครับ'], 201);
} catch (Exception $e) {
$db->rollBack();
jsonResponse(['error' => 'เกิดข้อผิดพลาด: ' . $e->getMessage()], 500);
}
}
function listResponses() {
$surveyId = (int)($_GET['survey_id'] ?? 0);
if (!$surveyId) jsonResponse(['error' => 'Missing survey_id'], 400);
$db = getDB();
// Check access
if (!isAdmin()) {
$stmt = $db->prepare("SELECT user_id FROM surveys WHERE id = ?");
$stmt->execute([$surveyId]);
$survey = $stmt->fetch();
if (!$survey || $survey['user_id'] != $_SESSION['user_id']) {
jsonResponse(['error' => 'ไม่มีสิทธิ์'], 403);
}
}
$stmt = $db->prepare("
SELECT id, respondent_info, ip_address, submitted_at
FROM survey_responses
WHERE survey_id = ?
ORDER BY submitted_at DESC
");
$stmt->execute([$surveyId]);
$responses = $stmt->fetchAll();
foreach ($responses as &$r) {
$r['respondent_info'] = json_decode($r['respondent_info'], true);
}
jsonResponse(['responses' => $responses, 'total' => count($responses)]);
}
function getResponse() {
$id = (int)($_GET['id'] ?? 0);
if (!$id) jsonResponse(['error' => 'Missing ID'], 400);
$db = getDB();
$stmt = $db->prepare("
SELECT sr.*, s.title as survey_title, s.user_id
FROM survey_responses sr
JOIN surveys s ON sr.survey_id = s.id
WHERE sr.id = ?
");
$stmt->execute([$id]);
$response = $stmt->fetch();
if (!$response) jsonResponse(['error' => 'ไม่พบคำตอบ'], 404);
if (!isAdmin() && $response['user_id'] != $_SESSION['user_id']) {
jsonResponse(['error' => 'ไม่มีสิทธิ์'], 403);
}
$response['respondent_info'] = json_decode($response['respondent_info'], true);
// Get answers
$stmt = $db->prepare("
SELECT ra.*, sq.question_text, sq.question_type
FROM response_answers ra
JOIN survey_questions sq ON ra.question_id = sq.id
WHERE ra.response_id = ?
ORDER BY sq.order_num
");
$stmt->execute([$id]);
$response['answers'] = $stmt->fetchAll();
jsonResponse(['response' => $response]);
}