選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

voting.php 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. include('../inc/inc.php');
  3. if (!$user->loggedin()) {
  4. header('Location: /login.php');
  5. die();
  6. }
  7. if ($user->getRole() !== "admin") {
  8. header('Location: /index.php');
  9. die();
  10. }
  11. function loadPositions() {
  12. global $db;
  13. $_pos = $db->fetchAssoc("select position as code, description as label, active from positions");
  14. $positions = [];
  15. foreach ($_pos as $position)
  16. $positions[$position['code']] = [ "label" => $position['label'], "active" => $position['active']];
  17. return $positions;
  18. }
  19. function loadVoters() {
  20. global $db;
  21. $voters = $db->fetchAssoc('
  22. select
  23. MIN(skymanager_id) as `skymanager_id`,
  24. MIN(members.voting_id) as `voting_id`,
  25. MIN(name) as `name`,
  26. MIN(username) as `username`,
  27. group_concat(proxy.voting_id) as `proxies`,
  28. MIN(upstream_proxy.delegate_id) as `delegate`,
  29. coalesce(MIN(email), "") as `gravatar_email`
  30. from members
  31. left join proxy on (members.voting_id=proxy.delegate_id)
  32. left join proxy as upstream_proxy on (upstream_proxy.voting_id=members.voting_id)
  33. where members.voting_id is not null
  34. group by members.voting_id
  35. UNION
  36. select skymanager_id, voting_id, name, username, NULL as `proxies`, NULL as `delegate`, coalesce(email, "") as `gravatar_email`
  37. from members where members.voting_id is null');
  38. get_gravatar_assoc($voters);
  39. return $voters;
  40. }
  41. $result = null;
  42. // Create Position
  43. if (!empty($_POST['create'])) {
  44. $code = $_POST['add-position'];
  45. $desc = $_POST['add-description'];
  46. if (empty($code) || empty($desc)) $error = "Both code and description are required";
  47. if (empty($error)) {
  48. $result = $db->query('INSERT INTO positions (position, description) VALUES ("' . $db->sanitize($code) . '", "' . $db->sanitize($desc) . '")');
  49. if ($result === false)
  50. $error = "That position already exists.";
  51. else
  52. $error = "Created position " . htmlspecialchars($desc);
  53. }
  54. } else if (!empty($_POST['setActive']) || !empty($_POST['deactivate'])) {
  55. if (!array_key_exists('ballot', $_POST)) {
  56. $error = "No position selected";
  57. } else {
  58. $positions = loadPositions();
  59. $position = $_POST['ballot'];
  60. if (!array_key_exists($position, $positions)) $error = "That position does not exist";
  61. if (!empty($_POST['deactivate']))
  62. $position='';
  63. if (empty($error)) {
  64. $result = $db->query('UPDATE positions set active=(position="' . $db->sanitize($position) . '")');
  65. if ($result === false)
  66. $error = "Failed to set active position";
  67. else if (empty($position))
  68. $error = "Deactivated voting form";
  69. else
  70. $error = "Set " . htmlspecialchars($positions[$_POST['ballot']]['label']) . " as active.";
  71. }
  72. }
  73. } else if (!empty($_POST['remove'])) {
  74. if (!array_key_exists('ballot', $_POST)) {
  75. $error = "No position selected";
  76. } else {
  77. $positions = loadPositions();
  78. if (!array_key_exists($_POST['ballot'], $positions)) $error = "That position does not exist";
  79. if (empty($error)) {
  80. $result = $db->query('DELETE FROM positions WHERE position="' . $db->sanitize($_POST['ballot']) . '"');
  81. if ($result === false)
  82. $error = "Failed to remove position";
  83. else
  84. $error = "Removed " . htmlspecialchars($positions[$_POST['ballot']]['label']) . " and discarded cast ballots.";
  85. }
  86. }
  87. } else if (!empty($_POST['force'])) {
  88. $voters = loadVoters();
  89. $values = [];
  90. $vid = [];
  91. foreach ($voters as $voter) {
  92. $vid[$voter['skymanager_id']] = $voter;
  93. if ($voter['voting_id'])
  94. array_push($values, $voter['voting_id']);
  95. }
  96. if (!array_key_exists($_POST['voter-smid'], $vid))
  97. $error = "Voter does not exist";
  98. sort($values);
  99. $count = count($values);
  100. $rand = rand(100, 999-$count);
  101. for ($i = 0; $i < $count && $values[$i] <= $rand; $i++) {
  102. $rand++;
  103. }
  104. if (empty($error)) {
  105. $result = $db->query('UPDATE members set voting_id=' . ((int) $rand) . ' where skymanager_id=' . ((int) $_POST['voter-smid']));
  106. if ($result === false)
  107. $error = "Failed to force check-in. Please try again.";
  108. else
  109. $error = "Assigned voting id $rand to {$vid[$_POST['voter-smid']]['name']}";
  110. }
  111. }
  112. $positions = loadPositions();
  113. $voters = loadVoters();
  114. $header = new Header("Michigan Flyers Election : Admin");
  115. $header->addStyle("/styles/style.css");
  116. $header->addStyle("/styles/admin.css");
  117. $header->addStyle("/styles/vote.css");
  118. $header->addScript("/js/jquery-1.11.3.min.js");
  119. $header->addScript("/js/search.js");
  120. $header->addScript("/js/admin-search.js");
  121. $header->setAttribute('title', 'Michigan Flyers');
  122. $header->setAttribute('tagline', 'Election Administration Tools');
  123. $header->output();
  124. ?>
  125. <script type="text/javascript">
  126. var voters = <?= json_encode($voters); ?>;
  127. </script>
  128. <form action="voting.php" method="POST">
  129. <?php if (!empty($error) || !empty($result)): ?>
  130. <div id="vote-result">
  131. <div id="status" class="<?= $result ? "success" : "failure"; ?>"></div>
  132. <div id="message" class="<?= $result ? "success" : "failure"; ?>">
  133. <?= !empty($error) ? $error : ($result ? "This Ballot has been successfully Submitted" :
  134. "This ballot has already been submitted.") ?>
  135. </div>
  136. </div>
  137. <?php endif; ?>
  138. <?php if (!empty($positions)): ?>
  139. <div class="form-section">
  140. <h3>Manage Positions</h3>
  141. <div class="form-row">
  142. <div class="selector">
  143. <?php foreach ($positions as $code => $position): ?>
  144. <label class="radio">
  145. <input type="radio" id="vote-<?= $code ?>" name="ballot" value="<?= $code ?>" <?= ($position['active']) ? 'checked' : '' ?> />
  146. <span class="radio-button-label"><?= $position['label'] ?></span>
  147. </label>
  148. <?php endforeach; ?>
  149. </div>
  150. </div>
  151. <div class="form-row split-button">
  152. <input class="submit danger" type="submit" name="remove" value="Remove Position & Ballots" />
  153. <input class="submit" type="submit" name="deactivate" value="Deactivate" />
  154. <input class="submit" type="submit" name="setActive" value="Set Active" />
  155. </div>
  156. </div>
  157. <?php endif; ?>
  158. <div class="form-section">
  159. <h3>Add Position</h3>
  160. <div class="form-row">
  161. <label for="add-position">Add Position Code</label>
  162. <input type="text" placeholder="PRES" id="add-position" name="add-position" value="" />
  163. </div>
  164. <div class="form-row">
  165. <label for="add-description">Add Position Description</label>
  166. <input type="text" placeholder="President" id="add-description" name="add-description" value="" />
  167. </div>
  168. <div class="form-row">
  169. <input class="submit" type="submit" name="create" value="Create Position" />
  170. </div>
  171. </div>
  172. <div class="form-section">
  173. <h3>Force Check-In</h3>
  174. <div class="form-row">
  175. <input type="text" placeholder="Voter Search" id="voter-searchbox" name="voter-searchbox" value="" />
  176. <div id="voter-results"></div>
  177. <input type="hidden" name="voter" id="voter-input" value="0" />
  178. <input type="hidden" name="voter-smid" id="voter-smid" value="0" />
  179. <div id="selectedVoter" class="selected candidate voter">
  180. <span class="placeholder">No Selected Voter</span>
  181. </div>
  182. </div>
  183. <div class="form-row">
  184. <input class="submit" type="submit" name="force" value="Force Check In" />
  185. </div>
  186. </div>
  187. </form>
  188. <?php
  189. $footer = new Footer();
  190. $footer->output();