Initial commit - TPU Survey System with Google Forms & Certificate Generator
This commit is contained in:
@@ -0,0 +1,254 @@
|
||||
<?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]);
|
||||
}
|
||||
Reference in New Issue
Block a user