Initial commit - TPU Survey System with Google Forms & Certificate Generator
This commit is contained in:
@@ -0,0 +1,291 @@
|
||||
<?php
|
||||
/**
|
||||
* Import Google Form API
|
||||
* POST ?action=importFromUrl - Import survey structure from Google Form URL
|
||||
* POST ?action=importFromJson - Import survey structure from JSON
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../config/database.php';
|
||||
require_once __DIR__ . '/../config/auth.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
requireLogin();
|
||||
|
||||
$action = $_GET['action'] ?? '';
|
||||
|
||||
switch ($action) {
|
||||
case 'importFromUrl':
|
||||
importFromUrl();
|
||||
break;
|
||||
case 'importFromJson':
|
||||
importFromJson();
|
||||
break;
|
||||
default:
|
||||
jsonResponse(['error' => 'Invalid action'], 400);
|
||||
}
|
||||
|
||||
function importFromUrl() {
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$url = trim($input['url'] ?? '');
|
||||
$projectId = !empty($input['project_id']) ? (int)$input['project_id'] : null;
|
||||
|
||||
if (empty($url)) {
|
||||
jsonResponse(['error' => 'กรุณาระบุ URL หรือ Link ของ Google Form'], 400);
|
||||
}
|
||||
|
||||
// Extract Form ID or viewform URL
|
||||
if (!preg_match('/docs\.google\.com\/forms\/d\/e?\/([^\/]+)/i', $url, $matches) && !preg_match('/docs\.google\.com\/forms\/d\/([^\/]+)/i', $url, $matches)) {
|
||||
jsonResponse(['error' => 'รูปแบบ URL ของ Google Form ไม่ถูกต้อง'], 400);
|
||||
}
|
||||
|
||||
// Attempt to fetch the public viewform HTML
|
||||
$fetchUrl = $url;
|
||||
if (strpos($fetchUrl, '/viewform') === false && strpos($fetchUrl, '/edit') === false) {
|
||||
$fetchUrl = rtrim($fetchUrl, '/') . '/viewform';
|
||||
}
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $fetchUrl);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
$html = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($httpCode !== 200 || empty($html)) {
|
||||
jsonResponse(['error' => 'ไม่สามารถดึงข้อมูลจาก Google Form URL นี้ได้ โปรดตรวจสอบว่าเปิดเป็นสาธารณะ (Public) หรือไม่'], 400);
|
||||
}
|
||||
|
||||
// Parse FB_PUBLIC_LOAD_DATA_
|
||||
if (!preg_match('/FB_PUBLIC_LOAD_DATA_\s*=\s*(.+?);<\/script>/s', $html, $dataMatches)) {
|
||||
jsonResponse(['error' => 'ไม่พบโครงสร้างแบบสอบถามใน Google Form นี้'], 400);
|
||||
}
|
||||
|
||||
$formData = json_decode($dataMatches[1], true);
|
||||
if (!$formData || !isset($formData[1])) {
|
||||
jsonResponse(['error' => 'โครงสร้างข้อมูล Google Form ไม่ถูกต้อง'], 400);
|
||||
}
|
||||
|
||||
$parsedSurvey = parseGoogleFormData($formData);
|
||||
$surveyId = saveParsedSurveyToDB($parsedSurvey, $projectId);
|
||||
|
||||
jsonResponse([
|
||||
'success' => true,
|
||||
'message' => 'นำเข้าโครงสร้างแบบสอบถามจาก Google Form เรียบร้อยแล้ว',
|
||||
'survey_id' => $surveyId,
|
||||
'title' => $parsedSurvey['title']
|
||||
]);
|
||||
}
|
||||
|
||||
function importFromJson() {
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$projectId = !empty($input['project_id']) ? (int)$input['project_id'] : null;
|
||||
$surveyData = $input['survey_data'] ?? null;
|
||||
|
||||
if (!$surveyData || empty($surveyData['title'])) {
|
||||
jsonResponse(['error' => 'ข้อมูล JSON ไม่ถูกต้อง หรือขาดชื่อแบบสอบถาม'], 400);
|
||||
}
|
||||
|
||||
$surveyId = saveParsedSurveyToDB($surveyData, $projectId);
|
||||
|
||||
jsonResponse([
|
||||
'success' => true,
|
||||
'message' => 'นำเข้าแบบสอบถามเรียบร้อยแล้ว',
|
||||
'survey_id' => $surveyId,
|
||||
'title' => $surveyData['title']
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper: Parse Google Forms FB_PUBLIC_LOAD_DATA_ structure
|
||||
*/
|
||||
function parseGoogleFormData($data) {
|
||||
$title = $data[1][8] ?? $data[1][1] ?? $data[3] ?? 'แบบสอบถามจาก Google Forms';
|
||||
$description = $data[1][0] ?? '';
|
||||
|
||||
$rawItems = $data[1][1] ?? [];
|
||||
|
||||
$sections = [];
|
||||
$currentSection = [
|
||||
'section_number' => 1,
|
||||
'title' => 'ส่วนที่ 1 ข้อมูลทั่วไป',
|
||||
'description' => '',
|
||||
'category' => 'general',
|
||||
'questions' => []
|
||||
];
|
||||
|
||||
$sectionCount = 1;
|
||||
|
||||
foreach ($rawItems as $item) {
|
||||
if (!is_array($item)) continue;
|
||||
|
||||
$qTitle = $item[1] ?? '';
|
||||
$qDesc = $item[2] ?? '';
|
||||
$qTypeNum = $item[3] ?? 0;
|
||||
$qDetails = $item[4][0] ?? [];
|
||||
|
||||
if (empty($qTitle) && $qTypeNum != 8) continue; // Skip empty items except section breaks
|
||||
|
||||
// Type 8 = Section Break in Google Forms
|
||||
if ($qTypeNum == 8) {
|
||||
if (!empty($currentSection['questions'])) {
|
||||
$sections[] = $currentSection;
|
||||
}
|
||||
$sectionCount++;
|
||||
$currentSection = [
|
||||
'section_number' => $sectionCount,
|
||||
'title' => $qTitle ?: ('ส่วนที่ ' . $sectionCount),
|
||||
'description' => $qDesc,
|
||||
'category' => 'rating',
|
||||
'questions' => []
|
||||
];
|
||||
continue;
|
||||
}
|
||||
|
||||
$qType = 'radio';
|
||||
$options = [];
|
||||
$scaleMin = 1;
|
||||
$scaleMax = 5;
|
||||
|
||||
// Map Google Forms Item Type numbers:
|
||||
// 0: Short Text, 1: Paragraph
|
||||
// 2: Radio (Multiple Choice), 3: Dropdown, 4: Checkbox
|
||||
// 5: Linear Scale (1-5)
|
||||
// 7: Grid / Matrix
|
||||
switch ($qTypeNum) {
|
||||
case 0:
|
||||
case 1:
|
||||
$qType = 'text';
|
||||
break;
|
||||
case 2:
|
||||
$qType = 'radio';
|
||||
if (isset($qDetails[1]) && is_array($qDetails[1])) {
|
||||
foreach ($qDetails[1] as $opt) {
|
||||
if (isset($opt[0])) $options[] = $opt[0];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
$qType = 'dropdown';
|
||||
if (isset($qDetails[1]) && is_array($qDetails[1])) {
|
||||
foreach ($qDetails[1] as $opt) {
|
||||
if (isset($opt[0])) $options[] = $opt[0];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
$qType = 'checkbox';
|
||||
if (isset($qDetails[1]) && is_array($qDetails[1])) {
|
||||
foreach ($qDetails[1] as $opt) {
|
||||
if (isset($opt[0])) $options[] = $opt[0];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
$qType = 'radio'; // Rating Scale
|
||||
$scaleMin = 1;
|
||||
$scaleMax = 5;
|
||||
break;
|
||||
default:
|
||||
$qType = 'text';
|
||||
break;
|
||||
}
|
||||
|
||||
$isRequired = isset($qDetails[2]) && $qDetails[2] == 1 ? 1 : 0;
|
||||
|
||||
$questionObj = [
|
||||
'question_text' => $qTitle,
|
||||
'question_type' => $qType,
|
||||
'is_required' => $isRequired,
|
||||
'description' => $qDesc,
|
||||
'options' => count($options) > 0 ? $options : null,
|
||||
'scale_min' => $scaleMin,
|
||||
'scale_max' => $scaleMax
|
||||
];
|
||||
|
||||
$currentSection['questions'][] = $questionObj;
|
||||
}
|
||||
|
||||
if (!empty($currentSection['questions'])) {
|
||||
$sections[] = $currentSection;
|
||||
}
|
||||
|
||||
if (empty($sections)) {
|
||||
$sections[] = [
|
||||
'section_number' => 1,
|
||||
'title' => 'ส่วนที่ 1 ข้อมูลและข้อคำถาม',
|
||||
'description' => 'นำเข้าจาก Google Forms',
|
||||
'category' => 'general',
|
||||
'questions' => []
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'title' => $title,
|
||||
'description' => $description ?: 'แบบสอบถามที่นำเข้าจาก Google Forms',
|
||||
'sections' => $sections
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Save parsed survey structure into database
|
||||
*/
|
||||
function saveParsedSurveyToDB($parsedSurvey, $projectId = null) {
|
||||
$db = getDB();
|
||||
$uniqueLink = bin2hex(random_bytes(16));
|
||||
|
||||
$db->beginTransaction();
|
||||
try {
|
||||
$stmt = $db->prepare("INSERT INTO surveys (user_id, project_id, title, description, unique_link, status) VALUES (?, ?, ?, ?, ?, 'active')");
|
||||
$stmt->execute([
|
||||
$_SESSION['user_id'],
|
||||
$projectId,
|
||||
$parsedSurvey['title'],
|
||||
$parsedSurvey['description'] ?? '',
|
||||
$uniqueLink
|
||||
]);
|
||||
$surveyId = $db->lastInsertId();
|
||||
|
||||
$sections = $parsedSurvey['sections'] ?? [];
|
||||
$secNum = 1;
|
||||
|
||||
foreach ($sections as $sec) {
|
||||
$stmt = $db->prepare("INSERT INTO survey_sections (survey_id, section_number, title, description, category) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->execute([
|
||||
$surveyId,
|
||||
$sec['section_number'] ?? $secNum,
|
||||
$sec['title'] ?? ('ส่วนที่ ' . $secNum),
|
||||
$sec['description'] ?? '',
|
||||
$sec['category'] ?? 'rating'
|
||||
]);
|
||||
$sectionId = $db->lastInsertId();
|
||||
|
||||
$orderNum = 1;
|
||||
foreach ($sec['questions'] as $q) {
|
||||
$optionsJson = !empty($q['options']) ? json_encode($q['options'], JSON_UNESCAPED_UNICODE) : null;
|
||||
$stmtQ = $db->prepare("INSERT INTO survey_questions (section_id, question_text, question_type, is_required, order_num, options, scale_min, scale_max, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmtQ->execute([
|
||||
$sectionId,
|
||||
$q['question_text'],
|
||||
$q['question_type'] ?? 'radio',
|
||||
$q['is_required'] ?? 1,
|
||||
$orderNum++,
|
||||
$optionsJson,
|
||||
$q['scale_min'] ?? 1,
|
||||
$q['scale_max'] ?? 5,
|
||||
$q['description'] ?? null
|
||||
]);
|
||||
}
|
||||
$secNum++;
|
||||
}
|
||||
|
||||
$db->commit();
|
||||
return $surveyId;
|
||||
} catch (Exception $e) {
|
||||
$db->rollBack();
|
||||
jsonResponse(['error' => 'เกิดข้อผิดพลาดในการบันทึกแบบสอบถาม: ' . $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user