372 lines
14 KiB
PHP
372 lines
14 KiB
PHP
<?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');
|
|
if (php_sapi_name() !== 'cli') {
|
|
requireLogin();
|
|
}
|
|
|
|
if (isset($_GET['action'])) {
|
|
$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',
|
|
'headings' => [],
|
|
'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 && $qTypeNum != 7) continue;
|
|
|
|
// Type 8 = Section Break in Google Forms
|
|
if ($qTypeNum == 8) {
|
|
if (!empty($currentSection['questions']) || !empty($currentSection['headings'])) {
|
|
$sections[] = $currentSection;
|
|
}
|
|
$sectionCount++;
|
|
$currentSection = [
|
|
'section_number' => $sectionCount,
|
|
'title' => $qTitle ?: ('ตอนที่ ' . $sectionCount),
|
|
'description' => $qDesc ?: '',
|
|
'category' => 'rating',
|
|
'headings' => [],
|
|
'questions' => []
|
|
];
|
|
continue;
|
|
}
|
|
|
|
// Type 7 = Grid / Matrix (ตารางประเมินระดับความพึงพอใจ 5 ระดับ)
|
|
if ($qTypeNum == 7) {
|
|
$gridTitle = $qTitle ?: 'ด้านที่ประเมิน';
|
|
$gridDesc = $qDesc ?: '';
|
|
$gridQuestions = [];
|
|
|
|
if (isset($item[4]) && is_array($item[4])) {
|
|
foreach ($item[4] as $sub) {
|
|
if (!is_array($sub)) continue;
|
|
$rowTitle = '';
|
|
if (isset($sub[3]) && is_array($sub[3]) && !empty($sub[3])) {
|
|
$rowTitle = $sub[3][0];
|
|
} elseif (isset($sub[3]) && is_string($sub[3])) {
|
|
$rowTitle = $sub[3];
|
|
}
|
|
if (empty($rowTitle)) continue;
|
|
|
|
$gridQuestions[] = [
|
|
'question_text' => $rowTitle,
|
|
'question_type' => 'radio',
|
|
'is_required' => 1,
|
|
'description' => '',
|
|
'options' => null, // 5-point Rating scale
|
|
'scale_min' => 1,
|
|
'scale_max' => 5
|
|
];
|
|
}
|
|
}
|
|
|
|
if (!empty($gridQuestions)) {
|
|
$currentSection['headings'][] = [
|
|
'title' => $gridTitle,
|
|
'description' => $gridDesc,
|
|
'questions' => $gridQuestions
|
|
];
|
|
}
|
|
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)
|
|
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']) || !empty($currentSection['headings'])) {
|
|
$sections[] = $currentSection;
|
|
}
|
|
|
|
if (empty($sections)) {
|
|
$sections[] = [
|
|
'section_number' => 1,
|
|
'title' => 'ส่วนที่ 1 ข้อมูลและข้อคำถาม',
|
|
'description' => 'นำเข้าจาก Google Forms',
|
|
'category' => 'general',
|
|
'headings' => [],
|
|
'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;
|
|
|
|
// 1. Insert Headings & their questions (e.g. Grids)
|
|
if (!empty($sec['headings'])) {
|
|
foreach ($sec['headings'] as $hIdx => $h) {
|
|
$stmtH = $db->prepare("INSERT INTO survey_headings (section_id, title, description, order_num) VALUES (?, ?, ?, ?)");
|
|
$stmtH->execute([
|
|
$sectionId,
|
|
$h['title'] ?? '',
|
|
$h['description'] ?? '',
|
|
$hIdx + 1
|
|
]);
|
|
$headingId = $db->lastInsertId();
|
|
|
|
foreach ($h['questions'] as $q) {
|
|
$optionsJson = !empty($q['options']) ? json_encode($q['options'], JSON_UNESCAPED_UNICODE) : null;
|
|
$stmtQ = $db->prepare("INSERT INTO survey_questions (section_id, heading_id, question_text, question_type, is_required, order_num, options, scale_min, scale_max, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
$stmtQ->execute([
|
|
$sectionId,
|
|
$headingId,
|
|
$q['question_text'],
|
|
$q['question_type'] ?? 'radio',
|
|
$q['is_required'] ?? 1,
|
|
$orderNum++,
|
|
$optionsJson,
|
|
$q['scale_min'] ?? 1,
|
|
$q['scale_max'] ?? 5,
|
|
$q['description'] ?? null
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 2. Insert Loose questions
|
|
if (!empty($sec['questions'])) {
|
|
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, heading_id, question_text, question_type, is_required, order_num, options, scale_min, scale_max, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
$stmtQ->execute([
|
|
$sectionId,
|
|
null,
|
|
$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);
|
|
}
|
|
}
|