$resp) { $row = [ $ri + 1, $resp['created_at'], $resp['status'], $resp['device_type'] ?? '', $resp['time_taken_seconds'] ?? '', ]; foreach ($questions as $q) { if (in_array($q['type'], ['statement','section_break'])) continue; $row[] = $answers[$resp['id']][$q['id']] ?? ''; } $rows[] = $row; } $safeName = preg_replace('/[^a-z0-9_-]/i', '_', $survey['title']); $filename = 'survam_' . $safeName . '_' . date('Ymd_His'); switch ($fmt) { // ── CSV ─────────────────────────────────────────────────── case 'csv': header('Content-Type: text/csv; charset=UTF-8'); header("Content-Disposition: attachment; filename=\"$filename.csv\""); $out = fopen('php://output', 'w'); // BOM for Excel UTF-8 compatibility fputs($out, "\xEF\xBB\xBF"); fputcsv($out, $headers); foreach ($rows as $row) fputcsv($out, $row); fclose($out); exit; // ── JSON ────────────────────────────────────────────────── case 'json': header('Content-Type: application/json; charset=UTF-8'); header("Content-Disposition: attachment; filename=\"$filename.json\""); $out = []; foreach ($responses as $ri => $resp) { $record = [ 'response_num' => $ri + 1, 'submitted_at' => $resp['created_at'], 'status' => $resp['status'], 'device' => $resp['device_type'] ?? '', 'time_seconds' => $resp['time_taken_seconds'], 'answers' => [], ]; foreach ($questions as $q) { if (in_array($q['type'], ['statement','section_break'])) continue; $record['answers'][$q['id']] = [ 'question' => $q['title'], 'type' => $q['type'], 'answer' => $answers[$resp['id']][$q['id']] ?? null, ]; } $out[] = $record; } echo json_encode(['survey' => $survey['title'], 'exported_at' => date('c'), 'responses' => $out], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); exit; // ── XLSX ────────────────────────────────────────────────── case 'xlsx': if (!file_exists(__DIR__ . '/../vendor/autoload.php')) { // Fallback to CSV if PhpSpreadsheet not available header('Content-Type: text/csv; charset=UTF-8'); header("Content-Disposition: attachment; filename=\"$filename.csv\""); $out = fopen('php://output', 'w'); fputs($out, "\xEF\xBB\xBF"); fputcsv($out, $headers); foreach ($rows as $row) fputcsv($out, $row); fclose($out); exit; } require __DIR__ . '/../vendor/autoload.php'; $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); $sheet->setTitle('Responses'); // Header row foreach ($headers as $ci => $h) { $col = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($ci + 1); $sheet->setCellValue($col . '1', $h); $sheet->getStyle($col . '1')->getFont()->setBold(true); $sheet->getStyle($col . '1')->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setARGB('FF1A1A2E'); $sheet->getStyle($col . '1')->getFont()->getColor()->setARGB('FFFFFFFF'); } // Data rows foreach ($rows as $ri => $row) { foreach ($row as $ci => $val) { $col = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($ci + 1); $sheet->setCellValue($col . ($ri + 2), $val); } } foreach (range(1, count($headers)) as $ci) { $sheet->getColumnDimensionByColumn($ci)->setAutoSize(true); } $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet); header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); header("Content-Disposition: attachment; filename=\"$filename.xlsx\""); $writer->save('php://output'); exit; // ── PDF ─────────────────────────────────────────────────── case 'pdf': // Render to HTML then print - works without library $html = generatePDFHTML($survey, $headers, $rows, $filename); header('Content-Type: text/html; charset=UTF-8'); echo $html; exit; // ── SPSS ───────────────────────────────────────────────── case 'spss': // Generate SAV-compatible syntax file (.sps) header('Content-Type: text/plain; charset=UTF-8'); header("Content-Disposition: attachment; filename=\"$filename.sps\""); echo generateSPSSsyntax($survey, $questions, $responses, $answers); exit; default: http_response_code(400); die('Unknown format.'); } function generatePDFHTML(array $survey, array $headers, array $rows, string $filename): string { $title = htmlspecialchars($survey['title']); $safeH = implode('', array_map('htmlspecialchars', $headers)); $rowsHTML = ''; foreach ($rows as $row) { $cells = implode('', array_map('htmlspecialchars', $row)); $rowsHTML .= "$cells"; } return "$title

$title — Survey Responses

Exported " . date('d M Y H:i') . " · " . count($rows) . " responses · SURVAM by Relevant Reflex Consulting

$rowsHTML
$safeH
"; } function generateSPSSsyntax(array $survey, array $questions, array $responses, array $answers): string { $out = "* SURVAM SPSS Export\n"; $out .= "* Survey: " . $survey['title'] . "\n"; $out .= "* Exported: " . date('Y-m-d H:i:s') . "\n\n"; $out .= "DATA LIST FREE\n /resp_num status device time_sec"; foreach ($questions as $i => $q) { if (in_array($q['type'], ['statement','section_break'])) continue; $out .= " q{$i}"; } $out .= " .\n\nBEGIN DATA.\n"; foreach ($responses as $ri => $resp) { $out .= ($ri + 1) . " " . $resp['status'] . " " . ($resp['device_type'] ?? '') . " " . ($resp['time_taken_seconds'] ?? 0); foreach ($questions as $i => $q) { if (in_array($q['type'], ['statement','section_break'])) continue; $val = $answers[$resp['id']][$q['id']] ?? ''; $val = str_replace(['"', "\n"], ['', ' '], $val); $out .= " \"$val\""; } $out .= "\n"; } $out .= "END DATA.\n\nVARIABLE LABELS\n resp_num 'Response Number'\n status 'Response Status'\n device 'Device Type'\n time_sec 'Time Taken (seconds)'"; foreach ($questions as $i => $q) { if (in_array($q['type'], ['statement','section_break'])) continue; $lbl = addslashes(substr($q['title'], 0, 120)); $out .= "\n q{$i} '$lbl'"; } $out .= " .\n\nEXECUTE.\n"; return $out; }