submit.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <?php
  2. // submit.php - Handles saving an answer and displaying the result
  3. $answers_dir = __DIR__ . '/data/answers';
  4. if (!is_dir($answers_dir)) {
  5. mkdir($answers_dir, 0755, true);
  6. }
  7. $is_post = ($_SERVER['REQUEST_METHOD'] === 'POST');
  8. $form_id = $_REQUEST['form_id'] ?? $_GET['id'] ?? '';
  9. $answer_id = $_REQUEST['answer_id'] ?? $_POST['edit_id'] ?? '';
  10. $form_file = __DIR__ . '/data/forms/' . preg_replace('/[^a-zA-Z0-9_-]/', '', $form_id) . '.json';
  11. if (empty($form_id) || !file_exists($form_file)) {
  12. die('<div style="font-family:sans-serif; text-align:center; padding:50px;"><h2>Formular nicht gefunden</h2></div>');
  13. }
  14. $form_data = json_decode(file_get_contents($form_file), true);
  15. $questions_map = [];
  16. foreach ($form_data['questions'] as $q) {
  17. $questions_map[$q['id']] = $q['label'];
  18. }
  19. $injected_js = '';
  20. if ($is_post) {
  21. // Process form submission
  22. $respondent_name = trim($_POST['respondent_name'] ?? 'Anonym');
  23. $respondent_email = trim($_POST['respondent_email'] ?? '');
  24. $answers = $_POST['answers'] ?? [];
  25. $answers_freetext = $_POST['answers_freetext'] ?? [];
  26. // Resolve free text substitutions
  27. foreach ($answers as $q_id => $val) {
  28. if (is_array($val)) {
  29. $idx = array_search('__freetext__', $val);
  30. if ($idx !== false) {
  31. if (!empty($answers_freetext[$q_id])) {
  32. $val[$idx] = "Sonstiges: " . ltrim($answers_freetext[$q_id]);
  33. } else {
  34. unset($val[$idx]); // they selected 'Sonstiges' but left it blank
  35. }
  36. $answers[$q_id] = array_values($val);
  37. }
  38. } else {
  39. if ($val === '__freetext__') {
  40. if (!empty($answers_freetext[$q_id])) {
  41. $answers[$q_id] = "Sonstiges: " . ltrim($answers_freetext[$q_id]);
  42. } else {
  43. $answers[$q_id] = ''; // blank fallback
  44. }
  45. }
  46. }
  47. }
  48. $is_edit = !empty($answer_id);
  49. if (!$is_edit) {
  50. $answer_id = uniqid('ans_');
  51. }
  52. $safe_answer_id = preg_replace('/[^a-zA-Z0-9_-]/', '', $answer_id);
  53. $answer_data = [
  54. 'answer_id' => $safe_answer_id,
  55. 'form_id' => $form_id,
  56. 'respondent_name' => $respondent_name,
  57. 'respondent_email' => $respondent_email,
  58. 'submitted_at' => date('c'),
  59. 'answers' => $answers
  60. ];
  61. file_put_contents("$answers_dir/{$form_id}_{$safe_answer_id}.json", json_encode($answer_data, JSON_PRETTY_PRINT));
  62. // No longer injecting JS to prevent double-submit.
  63. $injected_js = "";
  64. // Email notification if provided
  65. if (!empty($respondent_email) && filter_var($respondent_email, FILTER_VALIDATE_EMAIL)) {
  66. $subject = "Deine Einsendung für: " . $form_data['title'];
  67. $body = "Hallo $respondent_name,\n\nVielen Dank für deine Einsendung.\nHier sind deine Antworten:\n\n";
  68. foreach ($answers as $q_id => $val) {
  69. $label = $questions_map[$q_id] ?? 'Frage';
  70. $val_str = is_array($val) ? implode(', ', $val) : $val;
  71. $body .= "$label:\n$val_str\n\n";
  72. }
  73. $host = $_SERVER['HTTP_HOST'];
  74. $headers = "From: no-reply@" . $host . "\r\n";
  75. @mail($respondent_email, $subject, $body, $headers);
  76. }
  77. // Redirect to self as GET to prevent duplicate POSTs on refresh
  78. header("Location: submit.php?id=" . urlencode($form_id) . "&answer_id=" . urlencode($safe_answer_id) . "&success=1");
  79. exit;
  80. }
  81. // Display Mode (GET)
  82. $success = isset($_GET['success']);
  83. $safe_answer_id = preg_replace('/[^a-zA-Z0-9_-]/', '', $answer_id);
  84. $answer_file = "$answers_dir/{$form_id}_{$safe_answer_id}.json";
  85. if (empty($safe_answer_id) || !file_exists($answer_file)) {
  86. die('<div style="font-family:sans-serif; text-align:center; padding:50px;"><h2>Einsendung nicht gefunden</h2></div>');
  87. }
  88. $answer_data = json_decode(file_get_contents($answer_file), true);
  89. ?>
  90. <!DOCTYPE html>
  91. <html lang="de">
  92. <head>
  93. <meta charset="UTF-8">
  94. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  95. <title>Einsendung erfolgreich</title>
  96. <link rel="stylesheet" href="assets/css/style.css">
  97. <script>
  98. <?= $injected_js ?> // Output any localstorage writes if we didn't redirect (e.g. if we chose to drop the header(Location))
  99. function clearAndAnswerNew() {
  100. // we don't need to clear submissions here anymore since we allow doubles
  101. window.location.href = 'answer.php?id=<?= htmlspecialchars($form_id) ?>';
  102. }
  103. </script>
  104. </head>
  105. <body>
  106. <header class="site-header">
  107. <div class="container header-inner">
  108. <div class="brand">
  109. <span class="brand-title"><?= htmlspecialchars($form_data['title']) ?></span>
  110. </div>
  111. </div>
  112. </header>
  113. <main class="container">
  114. <?php if ($success): ?>
  115. <div class="alert alert-success mt-3 mb-3">
  116. Deine Antwort wurde erfolgreich gespeichert.
  117. <?php if (!empty($answer_data['respondent_email'])): ?>
  118. <br><small>Eine Kopie deiner Antworten wurde gesendet an <?= htmlspecialchars($answer_data['respondent_email']) ?>.</small>
  119. <?php endif; ?>
  120. </div>
  121. <?php endif; ?>
  122. <div class="panel">
  123. <h2 class="card-title">Eingereichte Antworten</h2>
  124. <br>
  125. <table class="table-compact responsive-table">
  126. <tbody>
  127. <tr>
  128. <td data-label="Antwortender"><strong><?= htmlspecialchars($answer_data['respondent_name']) ?></strong></td>
  129. </tr>
  130. <?php foreach ($answer_data['answers'] as $q_id => $val): ?>
  131. <tr>
  132. <td data-label="<?= htmlspecialchars($questions_map[$q_id] ?? 'Frage') ?>">
  133. <div><strong style="color:var(--brand-muted); font-size:0.85rem;"><?= htmlspecialchars($questions_map[$q_id] ?? 'Frage') ?></strong></div>
  134. <div><?= nl2br(htmlspecialchars(is_array($val) ? implode(', ', $val) : $val)) ?></div>
  135. </td>
  136. </tr>
  137. <?php endforeach; ?>
  138. </tbody>
  139. </table>
  140. </div>
  141. <div class="panel text-center" style="background:transparent; border:none; box-shadow:none;">
  142. <a href="answer.php?id=<?= htmlspecialchars($form_id) ?>&edit=<?= htmlspecialchars($answer_data['answer_id']) ?>" class="btn mt-2">Antwort bearbeiten</a>
  143. <button onclick="clearAndAnswerNew()" class="btn btn-secondary mt-2">Weitere Antwort hinzufügen</button>
  144. </div>
  145. </main>
  146. </body>
  147. </html>