submit.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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>Form Not Found</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'] ?? 'Anonymous');
  23. $respondent_email = trim($_POST['respondent_email'] ?? '');
  24. $answers = $_POST['answers'] ?? [];
  25. $is_edit = !empty($answer_id);
  26. if (!$is_edit) {
  27. $answer_id = uniqid('ans_');
  28. }
  29. $safe_answer_id = preg_replace('/[^a-zA-Z0-9_-]/', '', $answer_id);
  30. $answer_data = [
  31. 'answer_id' => $safe_answer_id,
  32. 'form_id' => $form_id,
  33. 'respondent_name' => $respondent_name,
  34. 'respondent_email' => $respondent_email,
  35. 'submitted_at' => date('c'),
  36. 'answers' => $answers
  37. ];
  38. file_put_contents("$answers_dir/{$form_id}_{$safe_answer_id}.json", json_encode($answer_data, JSON_PRETTY_PRINT));
  39. // No longer injecting JS to prevent double-submit.
  40. $injected_js = "";
  41. // Email notification if provided
  42. if (!empty($respondent_email) && filter_var($respondent_email, FILTER_VALIDATE_EMAIL)) {
  43. $subject = "Your submission for: " . $form_data['title'];
  44. $body = "Hi $respondent_name,\n\nThank you for your submission.\nHere is what you submitted:\n\n";
  45. foreach ($answers as $q_id => $val) {
  46. $label = $questions_map[$q_id] ?? 'Question';
  47. $val_str = is_array($val) ? implode(', ', $val) : $val;
  48. $body .= "$label:\n$val_str\n\n";
  49. }
  50. $host = $_SERVER['HTTP_HOST'];
  51. $headers = "From: no-reply@" . $host . "\r\n";
  52. @mail($respondent_email, $subject, $body, $headers);
  53. }
  54. // Redirect to self as GET to prevent duplicate POSTs on refresh
  55. header("Location: submit.php?id=" . urlencode($form_id) . "&answer_id=" . urlencode($safe_answer_id) . "&success=1");
  56. exit;
  57. }
  58. // Display Mode (GET)
  59. $success = isset($_GET['success']);
  60. $safe_answer_id = preg_replace('/[^a-zA-Z0-9_-]/', '', $answer_id);
  61. $answer_file = "$answers_dir/{$form_id}_{$safe_answer_id}.json";
  62. if (empty($safe_answer_id) || !file_exists($answer_file)) {
  63. die('<div style="font-family:sans-serif; text-align:center; padding:50px;"><h2>Submission Not Found</h2></div>');
  64. }
  65. $answer_data = json_decode(file_get_contents($answer_file), true);
  66. ?>
  67. <!DOCTYPE html>
  68. <html lang="en">
  69. <head>
  70. <meta charset="UTF-8">
  71. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  72. <title>Submission Complete</title>
  73. <link rel="stylesheet" href="assets/css/style.css">
  74. <script>
  75. <?= $injected_js ?> // Output any localstorage writes if we didn't redirect (e.g. if we chose to drop the header(Location))
  76. function clearAndAnswerNew() {
  77. // we don't need to clear submissions here anymore since we allow doubles
  78. window.location.href = 'answer.php?id=<?= htmlspecialchars($form_id) ?>';
  79. }
  80. </script>
  81. </head>
  82. <body>
  83. <header class="site-header">
  84. <div class="container header-inner">
  85. <div class="brand">
  86. <span class="brand-title"><?= htmlspecialchars($form_data['title']) ?></span>
  87. </div>
  88. </div>
  89. </header>
  90. <main class="container">
  91. <?php if ($success): ?>
  92. <div class="alert alert-success mt-3 mb-3">
  93. Your response has been successfully saved.
  94. <?php if (!empty($answer_data['respondent_email'])): ?>
  95. <br><small>A copy of your responses was sent to <?= htmlspecialchars($answer_data['respondent_email']) ?>.</small>
  96. <?php endif; ?>
  97. </div>
  98. <?php endif; ?>
  99. <div class="panel">
  100. <h2 class="card-title">Submitted Answers</h2>
  101. <br>
  102. <table class="table-compact responsive-table">
  103. <tbody>
  104. <tr>
  105. <td data-label="Respondent"><strong><?= htmlspecialchars($answer_data['respondent_name']) ?></strong></td>
  106. </tr>
  107. <?php foreach ($answer_data['answers'] as $q_id => $val): ?>
  108. <tr>
  109. <td data-label="<?= htmlspecialchars($questions_map[$q_id] ?? 'Question') ?>">
  110. <div><strong style="color:var(--brand-muted); font-size:0.85rem;"><?= htmlspecialchars($questions_map[$q_id] ?? 'Question') ?></strong></div>
  111. <div><?= nl2br(htmlspecialchars(is_array($val) ? implode(', ', $val) : $val)) ?></div>
  112. </td>
  113. </tr>
  114. <?php endforeach; ?>
  115. </tbody>
  116. </table>
  117. </div>
  118. <div class="panel text-center" style="background:transparent; border:none; box-shadow:none;">
  119. <a href="answer.php?id=<?= htmlspecialchars($form_id) ?>&edit=<?= htmlspecialchars($answer_data['answer_id']) ?>" class="btn mt-2">Edit Response</a>
  120. <button onclick="clearAndAnswerNew()" class="btn btn-secondary mt-2">Add another answer</button>
  121. </div>
  122. </main>
  123. </body>
  124. </html>