| die(); | die(); | ||||
| } | } | ||||
| if (!empty($_POST['voter']) && ((int) $_POST['voter']) == $_POST['voter']) { | |||||
| if (isset($_POST['voter'])) { | |||||
| $voter = (int) $_POST['voter']; | $voter = (int) $_POST['voter']; | ||||
| $result = $db->query("update members set checkedin=true where voting_id=$voter"); | |||||
| if (!empty($_POST['voter']) && ((int) $_POST['voter']) == $_POST['voter']) { | |||||
| $result = $db->query("update members set checkedin=true where voting_id=$voter"); | |||||
| } else { | |||||
| $result = false; | |||||
| $error = "The selected voter is not eligible"; | |||||
| } | |||||
| } | } | ||||
| $header = new Header("2022 Michigan Flyers Election : Poll Worker"); | |||||
| $header = new Header("Michigan Flyers Election : Poll Worker"); | |||||
| $header->addStyle("/styles/style.css"); | $header->addStyle("/styles/style.css"); | ||||
| $header->addStyle("/styles/admin.css"); | $header->addStyle("/styles/admin.css"); | ||||
| $header->addStyle("/styles/vote.css"); | $header->addStyle("/styles/vote.css"); | ||||
| $header->addScript("/js/jquery-1.11.3.min.js"); | $header->addScript("/js/jquery-1.11.3.min.js"); | ||||
| $header->addScript("/js/admin-search.js"); | $header->addScript("/js/admin-search.js"); | ||||
| $header->setAttribute('title', 'Michigan Flyers'); | $header->setAttribute('title', 'Michigan Flyers'); | ||||
| $header->setAttribute('tagline', '2022 Election Administration'); | |||||
| $header->setAttribute('tagline', 'Election Poll Worker Tools'); | |||||
| $header->output(); | $header->output(); | ||||
| $voters = $db->fetchAssoc('select ANY_VALUE(skymanager_id) as `skymanager_id`, ANY_VALUE(members.voting_id) as `voting_id`, ANY_VALUE(name) as `name`, ANY_VALUE(username) as `username`, group_concat(proxy.voting_id) as `proxies`, ANY_VALUE(upstream_proxy.delegate_id) as `delegate`, md5(coalesce(ANY_VALUE(email), "")) as `gravatar_hash` from members left join proxy on (members.voting_id=proxy.delegate_id) left join proxy as upstream_proxy on (upstream_proxy.voting_id=members.voting_id) where members.voting_id is not null group by members.voting_id UNION select skymanager_id, voting_id, name, username, NULL as `proxies`, NULL as `delegate`, md5(coalesce(email, "")) as `gravatar_hash` from members where members.voting_id is null'); | |||||
| $voters = $db->fetchAssoc(' | |||||
| select | |||||
| MIN(skymanager_id) as `skymanager_id`, | |||||
| MIN(members.voting_id) as `voting_id`, | |||||
| MIN(name) as `name`, | |||||
| MIN(username) as `username`, | |||||
| group_concat(proxy.voting_id) as `proxies`, | |||||
| MIN(upstream_proxy.delegate_id) as `delegate`, | |||||
| md5(coalesce(MIN(email), "")) as `gravatar_hash` | |||||
| from members | |||||
| left join proxy on (members.voting_id=proxy.delegate_id) | |||||
| left join proxy as upstream_proxy on (upstream_proxy.voting_id=members.voting_id) | |||||
| where members.voting_id is not null | |||||
| group by members.voting_id | |||||
| UNION | |||||
| select skymanager_id, voting_id, name, username, NULL as `proxies`, NULL as `delegate`, md5(coalesce(email, "")) as `gravatar_hash` | |||||
| from members where members.voting_id is null'); | |||||
| ?> | ?> | ||||
| <script type="text/javascript"> | <script type="text/javascript"> | ||||
| var voters = <?= json_encode($voters); ?>; | var voters = <?= json_encode($voters); ?>; | ||||
| <input type="radio" name="button" value="pe" /> | <input type="radio" name="button" value="pe" /> | ||||
| <a class="radio-button-label" href="/admin/paper.php">Paper Entry</a> | <a class="radio-button-label" href="/admin/paper.php">Paper Entry</a> | ||||
| </label> | </label> | ||||
| <!-- | |||||
| <label class="radio"> | |||||
| <input type="radio" name="button" value="vo" /> | |||||
| <a class="radio-button-label" href="/admin/voting.php">Voting</a> | |||||
| </label> | |||||
| --> | |||||
| <label class="radio"> | <label class="radio"> | ||||
| <input type="radio" name="button" value="re" /> | <input type="radio" name="button" value="re" /> | ||||
| <a class="radio-button-label" href="/admin/results.php">Results</a> | <a class="radio-button-label" href="/admin/results.php">Results</a> | ||||
| <input class="submit" type="submit" name="submit" value="Check In" /> | <input class="submit" type="submit" name="submit" value="Check In" /> | ||||
| </div> | </div> | ||||
| </form> | </form> | ||||
| <?php if (!empty($voter)): ?> | |||||
| <?php if (isset($voter)): ?> | |||||
| <div id="vote-result"> | <div id="vote-result"> | ||||
| <div id="status" class="<?= $result ? "success" : "failure"; ?>"></div> | <div id="status" class="<?= $result ? "success" : "failure"; ?>"></div> | ||||
| <div id="message" class="<?= $result ? "success" : "failure"; ?>"> | <div id="message" class="<?= $result ? "success" : "failure"; ?>"> |
| die(); | die(); | ||||
| } | } | ||||
| $_pos = $db->fetchAssoc("select position as code, description as label from positions"); | |||||
| $positions = []; | |||||
| foreach ($_pos as $position) | |||||
| $positions[$position['code']] = $position['label']; | |||||
| $result = null; | |||||
| if (!empty($_POST['ballot']) && !empty($_POST['candidate'])) { | if (!empty($_POST['ballot']) && !empty($_POST['candidate'])) { | ||||
| $candidate_selected = (int) $_POST['candidate']; | $candidate_selected = (int) $_POST['candidate']; | ||||
| $voter_selected = (int) $_POST['voter']; | $voter_selected = (int) $_POST['voter']; | ||||
| if ($candidate_selected != $_POST['candidate']) $error = "An eccor occurred while processing your ballot. Please retry."; | if ($candidate_selected != $_POST['candidate']) $error = "An eccor occurred while processing your ballot. Please retry."; | ||||
| if ($voter_selected != $_POST['voter']) $error = "An eccor occurred while processing your ballot. Please retry."; | if ($voter_selected != $_POST['voter']) $error = "An eccor occurred while processing your ballot. Please retry."; | ||||
| if ($ballot !== "VICEPRESIDENT" && $ballot !== "SECRETARY" && $ballot !== "DIRECTOR") $error = "An eccor occurred while processing your ballot. Please retry."; | |||||
| if (!array_key_exists($ballot, $positions)) $error = "An eccor occurred while processing your ballot. Please retry."; | |||||
| if (empty($error)) { | if (empty($error)) { | ||||
| $result = $db->query("INSERT INTO votes (candidate_id, position, member_id, vote_type, submitter_id) SELECT $candidate_selected, \"$ballot\", $voter_selected, 'IN PERSON', $voter_selected UNION SELECT $candidate_selected, \"$ballot\", voting_id, 'PROXY IN PERSON', delegate_id from proxy where delegate_id=$voter_selected"); | $result = $db->query("INSERT INTO votes (candidate_id, position, member_id, vote_type, submitter_id) SELECT $candidate_selected, \"$ballot\", $voter_selected, 'IN PERSON', $voter_selected UNION SELECT $candidate_selected, \"$ballot\", voting_id, 'PROXY IN PERSON', delegate_id from proxy where delegate_id=$voter_selected"); | ||||
| } | } | ||||
| } | } | ||||
| $positions = [ | |||||
| 'VICEPRESIDENT' => 'Vice President', | |||||
| 'SECRETARY' => 'Secretary', | |||||
| 'DIRECTOR' => 'Director' | |||||
| ]; | |||||
| $header = new Header("2022 Michigan Flyers Election : Poll Worker"); | |||||
| $header = new Header("Michigan Flyers Election : Poll Worker"); | |||||
| $header->addStyle("/styles/style.css"); | $header->addStyle("/styles/style.css"); | ||||
| $header->addStyle("/styles/admin.css"); | $header->addStyle("/styles/admin.css"); | ||||
| $header->addStyle("/styles/vote.css"); | $header->addStyle("/styles/vote.css"); | ||||
| $header->addScript("/js/search.js"); | $header->addScript("/js/search.js"); | ||||
| $header->addScript("/js/admin-search.js"); | $header->addScript("/js/admin-search.js"); | ||||
| $header->setAttribute('title', 'Michigan Flyers'); | $header->setAttribute('title', 'Michigan Flyers'); | ||||
| $header->setAttribute('tagline', '2022 Election Administration'); | |||||
| $header->setAttribute('tagline', 'Election Poll Worker Tools'); | |||||
| $header->output(); | $header->output(); | ||||
| $candidates = $db->fetchAssoc('select skymanager_id, name, username, md5(coalesce(email, "")) as `gravatar_hash` from members where voting_id is not null'); | $candidates = $db->fetchAssoc('select skymanager_id, name, username, md5(coalesce(email, "")) as `gravatar_hash` from members where voting_id is not null'); | ||||
| $voters = $db->fetchAssoc('select ANY_VALUE(skymanager_id) as `skymanager_id`, ANY_VALUE(members.voting_id) as `voting_id`, ANY_VALUE(name) as `name`, ANY_VALUE(username) as `username`, group_concat(proxy.voting_id) as `proxies`, ANY_VALUE(upstream_proxy.delegate_id) as `delegate`, md5(coalesce(ANY_VALUE(email), "")) as `gravatar_hash` from members left join proxy on (members.voting_id=proxy.delegate_id) left join proxy as upstream_proxy on (upstream_proxy.voting_id=members.voting_id) where members.voting_id is not null group by members.voting_id UNION select skymanager_id, voting_id, name, username, NULL as `proxies`, NULL as `delegate`, md5(coalesce(email, "")) as `gravatar_hash` from members where members.voting_id is null'); | |||||
| $voters = $db->fetchAssoc('select MIN(skymanager_id) as `skymanager_id`, MIN(members.voting_id) as `voting_id`, MIN(name) as `name`, MIN(username) as `username`, group_concat(proxy.voting_id) as `proxies`, MIN(upstream_proxy.delegate_id) as `delegate`, md5(coalesce(MIN(email), "")) as `gravatar_hash` from members left join proxy on (members.voting_id=proxy.delegate_id) left join proxy as upstream_proxy on (upstream_proxy.voting_id=members.voting_id) where members.voting_id is not null group by members.voting_id UNION select skymanager_id, voting_id, name, username, NULL as `proxies`, NULL as `delegate`, md5(coalesce(email, "")) as `gravatar_hash` from members where members.voting_id is null'); | |||||
| ?> | ?> | ||||
| <script type="text/javascript"> | <script type="text/javascript"> | ||||
| var voters = <?= json_encode($voters); ?>; | var voters = <?= json_encode($voters); ?>; | ||||
| <input type="radio" name="button" value="pe" checked /> | <input type="radio" name="button" value="pe" checked /> | ||||
| <a class="radio-button-label" href="#">Paper Entry</a> | <a class="radio-button-label" href="#">Paper Entry</a> | ||||
| </label> | </label> | ||||
| <!-- | |||||
| <label class="radio"> | |||||
| <input type="radio" name="button" value="vo" /> | |||||
| <a class="radio-button-label" href="/admin/voting.php">Voting</a> | |||||
| </label> | |||||
| --> | |||||
| <label class="radio"> | <label class="radio"> | ||||
| <input type="radio" name="button" value="re" /> | <input type="radio" name="button" value="re" /> | ||||
| <a class="radio-button-label" href="/admin/results.php">Results</a> | <a class="radio-button-label" href="/admin/results.php">Results</a> | ||||
| </label> | </label> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <?php if (empty($positions)): ?> | |||||
| <h3>No positions are open for voting.</h3> | |||||
| <a href="/admin/positions.php?create">Create a position</a> | |||||
| <?php else: ?> | |||||
| <div class="form-row"> | <div class="form-row"> | ||||
| <div class="selector"> | <div class="selector"> | ||||
| <?php foreach ($positions as $code => $label): ?> | |||||
| <label class="radio"> | <label class="radio"> | ||||
| <input type="radio" id="vote-vicepresident" name="ballot" value="VICEPRESIDENT" checked /> | |||||
| <span class="radio-button-label">Vice President</span> | |||||
| </label> | |||||
| <label class="radio"> | |||||
| <input type="radio" id="vote-secretary" name="ballot" value="SECRETARY" checked /> | |||||
| <span class="radio-button-label">Secretary</span> | |||||
| </label> | |||||
| <label class="radio"> | |||||
| <input type="radio" id="vote-director" name="ballot" value="DIRECTOR" /> | |||||
| <span class="radio-button-label">Director-At-Large</span> | |||||
| <input type="radio" id="vote-<?= $code ?>" name="ballot" value="<?= $code ?>" checked /> | |||||
| <span class="radio-button-label"><?= $label ?></span> | |||||
| </label> | </label> | ||||
| <?php endforeach; ?> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="form-row"> | <div class="form-row"> | ||||
| <?php endif; ?> | <?php endif; ?> | ||||
| </div> | </div> | ||||
| <?php endif; ?> | <?php endif; ?> | ||||
| <?php endif; ?> | |||||
| <?php | <?php | ||||
| $footer = new Footer(); | $footer = new Footer(); | ||||
| $footer->output(); | $footer->output(); |
| $result = $db->query("update members set checkedin=true where voting_id=$voter"); | $result = $db->query("update members set checkedin=true where voting_id=$voter"); | ||||
| } | } | ||||
| $header = new Header("2022 Michigan Flyers Election : Poll Worker"); | |||||
| $header = new Header("Michigan Flyers Election : Poll Worker"); | |||||
| $header->addStyle("/styles/style.css"); | $header->addStyle("/styles/style.css"); | ||||
| $header->addStyle("/styles/admin.css"); | $header->addStyle("/styles/admin.css"); | ||||
| $header->addStyle("/styles/vote.css"); | $header->addStyle("/styles/vote.css"); | ||||
| $header->addScript("/js/jquery-1.11.3.min.js"); | $header->addScript("/js/jquery-1.11.3.min.js"); | ||||
| $header->addScript("/js/admin-search.js"); | $header->addScript("/js/admin-search.js"); | ||||
| $header->setAttribute('title', 'Michigan Flyers'); | $header->setAttribute('title', 'Michigan Flyers'); | ||||
| $header->setAttribute('tagline', '2022 Election Administration'); | |||||
| $header->setAttribute('tagline', 'Election Poll Worker Tools'); | |||||
| $header->output(); | $header->output(); | ||||
| $checkedin = $db->fetchAssoc('select name, username, voting_id, NULL as `proxy` from members where checkedin=true UNION select voter.name, voter.username, voter.voting_id, members.voting_id as `proxy` from members inner join proxy on (proxy.delegate_id=members.voting_id) left join members as `voter` on (voter.voting_id=proxy.voting_id) where members.checkedin = true'); | $checkedin = $db->fetchAssoc('select name, username, voting_id, NULL as `proxy` from members where checkedin=true UNION select voter.name, voter.username, voter.voting_id, members.voting_id as `proxy` from members inner join proxy on (proxy.delegate_id=members.voting_id) left join members as `voter` on (voter.voting_id=proxy.voting_id) where members.checkedin = true'); | ||||
| <input type="radio" name="button" value="pe" /> | <input type="radio" name="button" value="pe" /> | ||||
| <a class="radio-button-label" href="/admin/paper.php">Paper Entry</a> | <a class="radio-button-label" href="/admin/paper.php">Paper Entry</a> | ||||
| </label> | </label> | ||||
| <!-- | |||||
| <label class="radio"> | |||||
| <input type="radio" name="button" value="vo" /> | |||||
| <a class="radio-button-label" href="/admin/voting.php">Voting</a> | |||||
| </label> | |||||
| --> | |||||
| <label class="radio"> | <label class="radio"> | ||||
| <input type="radio" name="button" value="re" checked /> | <input type="radio" name="button" value="re" checked /> | ||||
| <a class="radio-button-label" href="#">Results</a> | <a class="radio-button-label" href="#">Results</a> |
| <?php | |||||
| include('../inc/inc.php'); | |||||
| if (!$user->loggedin()) { | |||||
| header('Location: /login.php'); | |||||
| die(); | |||||
| } | |||||
| if ($user->getRole() !== "admin") { | |||||
| header('Location: /index.php'); | |||||
| die(); | |||||
| } | |||||
| function loadPositions() { | |||||
| global $db; | |||||
| $_pos = $db->fetchAssoc("select position as code, description as label, active from positions"); | |||||
| $positions = []; | |||||
| foreach ($_pos as $position) | |||||
| $positions[$position['code']] = [ "label" => $position['label'], "active" => $position['active']]; | |||||
| return $positions; | |||||
| } | |||||
| function loadVoters() { | |||||
| global $db; | |||||
| return $db->fetchAssoc(' | |||||
| select | |||||
| MIN(skymanager_id) as `skymanager_id`, | |||||
| MIN(members.voting_id) as `voting_id`, | |||||
| MIN(name) as `name`, | |||||
| MIN(username) as `username`, | |||||
| group_concat(proxy.voting_id) as `proxies`, | |||||
| MIN(upstream_proxy.delegate_id) as `delegate`, | |||||
| md5(coalesce(MIN(email), "")) as `gravatar_hash` | |||||
| from members | |||||
| left join proxy on (members.voting_id=proxy.delegate_id) | |||||
| left join proxy as upstream_proxy on (upstream_proxy.voting_id=members.voting_id) | |||||
| where members.voting_id is not null | |||||
| group by members.voting_id | |||||
| UNION | |||||
| select skymanager_id, voting_id, name, username, NULL as `proxies`, NULL as `delegate`, md5(coalesce(email, "")) as `gravatar_hash` | |||||
| from members where members.voting_id is null'); | |||||
| } | |||||
| $result = null; | |||||
| // Create Position | |||||
| if (!empty($_POST['create'])) { | |||||
| $code = $_POST['add-position']; | |||||
| $desc = $_POST['add-description']; | |||||
| if (empty($code) || empty($desc)) $error = "Both code and description are required"; | |||||
| if (empty($error)) { | |||||
| $result = $db->query('INSERT INTO positions (position, description) VALUES ("' . $db->sanitize($code) . '", "' . $db->sanitize($desc) . '")'); | |||||
| if ($result === false) | |||||
| $error = "That position already exists."; | |||||
| else | |||||
| $error = "Created position " . htmlspecialchars($desc); | |||||
| } | |||||
| } else if (!empty($_POST['setActive']) || !empty($_POST['deactivate'])) { | |||||
| $positions = loadPositions(); | |||||
| $position = $_POST['ballot']; | |||||
| if (!array_key_exists($position, $positions)) $error = "That position does not exist"; | |||||
| if (!empty($_POST['deactivate'])) | |||||
| $position=''; | |||||
| if (empty($error)) { | |||||
| $result = $db->query('UPDATE positions set active=(position="' . $db->sanitize($_POST['ballot']) . '")'); | |||||
| if ($result === false) | |||||
| $error = "Failed to set active position"; | |||||
| else if (empty($position)) | |||||
| $error = "Deactivated voting form"; | |||||
| else | |||||
| $error = "Set " . htmlspecialchars($positions[$_POST['ballot']]['label']) . " as active."; | |||||
| } | |||||
| } else if (!empty($_POST['remove'])) { | |||||
| $positions = loadPositions(); | |||||
| if (!array_key_exists($_POST['ballot'], $positions)) $error = "That position does not exist"; | |||||
| if (empty($error)) { | |||||
| $result = $db->query('DELETE FROM positions WHERE position="' . $db->sanitize($_POST['ballot']) . '"'); | |||||
| if ($result === false) | |||||
| $error = "Failed to remove position"; | |||||
| else | |||||
| $error = "Removed " . htmlspecialchars($positions[$_POST['ballot']]['label']) . " and discarded cast ballots."; | |||||
| } | |||||
| } else if (!empty($_POST['force'])) { | |||||
| $voters = loadVoters(); | |||||
| $values = []; | |||||
| $vid = []; | |||||
| foreach ($voters as $voter) { | |||||
| $vid[$voter['skymanager_id']] = $voter; | |||||
| if ($voter['voting_id']) | |||||
| array_push($values, $voter['voting_id']); | |||||
| } | |||||
| if (!array_key_exists($_POST['voter-smid'], $vid)) | |||||
| $error = "Voter does not exist"; | |||||
| sort($values); | |||||
| $count = count($values); | |||||
| $rand = rand(100, 999-$count); | |||||
| for ($i = 0; $i < $count && $values[$i] <= $rand; $i++) { | |||||
| $rand++; | |||||
| } | |||||
| if (empty($error)) { | |||||
| $result = $db->query('UPDATE members set voting_id=' . ((int) $rand) . ' where skymanager_id=' . ((int) $_POST['voter-smid'])); | |||||
| if ($result === false) | |||||
| $error = "Failed to force check-in. Please try again."; | |||||
| else | |||||
| $error = "Assigned voting id $rand to {$vid[$_POST['voter-smid']]['name']}"; | |||||
| } | |||||
| } | |||||
| $positions = loadPositions(); | |||||
| $voters = loadVoters(); | |||||
| $header = new Header("Michigan Flyers Election : Admin"); | |||||
| $header->addStyle("/styles/style.css"); | |||||
| $header->addStyle("/styles/admin.css"); | |||||
| $header->addStyle("/styles/vote.css"); | |||||
| $header->addScript("/js/jquery-1.11.3.min.js"); | |||||
| $header->addScript("/js/search.js"); | |||||
| $header->addScript("/js/admin-search.js"); | |||||
| $header->setAttribute('title', 'Michigan Flyers'); | |||||
| $header->setAttribute('tagline', 'Election Administration Tools'); | |||||
| $header->output(); | |||||
| ?> | |||||
| <script type="text/javascript"> | |||||
| var voters = <?= json_encode($voters); ?>; | |||||
| </script> | |||||
| <form action="voting.php" method="POST"> | |||||
| <!-- | |||||
| <div class="form-row"> | |||||
| <div class="selector"> | |||||
| <label class="radio"> | |||||
| <input type="radio" name="button" value="ci" /> | |||||
| <a class="radio-button-label" href="/admin/checkin.php">Check-In</a> | |||||
| </label> | |||||
| <label class="radio"> | |||||
| <input type="radio" name="button" value="pe" /> | |||||
| <a class="radio-button-label" href="/admin/paper.php">Paper Entry</a> | |||||
| </label> | |||||
| <label class="radio"> | |||||
| <input type="radio" name="button" value="vo" checked /> | |||||
| <a class="radio-button-label" href="#">Voting</a> | |||||
| </label> | |||||
| <label class="radio"> | |||||
| <input type="radio" name="button" value="re" /> | |||||
| <a class="radio-button-label" href="/admin/results.php">Results</a> | |||||
| </label> | |||||
| </div> | |||||
| </div> | |||||
| --> | |||||
| <?php if (!empty($error) || !empty($result)): ?> | |||||
| <div id="vote-result"> | |||||
| <div id="status" class="<?= $result ? "success" : "failure"; ?>"></div> | |||||
| <div id="message" class="<?= $result ? "success" : "failure"; ?>"> | |||||
| <?= !empty($error) ? $error : ($result ? "This Ballot has been successfully Submitted" : | |||||
| "This ballot has already been submitted.") ?> | |||||
| </div> | |||||
| </div> | |||||
| <?php endif; ?> | |||||
| <?php if (!empty($positions)): ?> | |||||
| <div class="form-section"> | |||||
| <h3>Manage Positions</h3> | |||||
| <div class="form-row"> | |||||
| <div class="selector"> | |||||
| <?php foreach ($positions as $code => $position): ?> | |||||
| <label class="radio"> | |||||
| <input type="radio" id="vote-<?= $code ?>" name="ballot" value="<?= $code ?>" <?= ($position['active']) ? 'checked' : '' ?> /> | |||||
| <span class="radio-button-label"><?= $position['label'] ?></span> | |||||
| </label> | |||||
| <?php endforeach; ?> | |||||
| </div> | |||||
| </div> | |||||
| <div class="form-row split-button"> | |||||
| <input class="submit danger" type="submit" name="remove" value="Remove Position & Ballots" /> | |||||
| <input class="submit" type="submit" name="deactivate" value="Deactivate" /> | |||||
| <input class="submit" type="submit" name="setActive" value="Set Active" /> | |||||
| </div> | |||||
| </div> | |||||
| <?php endif; ?> | |||||
| <div class="form-section"> | |||||
| <h3>Add Position</h3> | |||||
| <div class="form-row"> | |||||
| <label for="add-position">Add Position Code</label> | |||||
| <input type="text" placeholder="PRES" id="add-position" name="add-position" value="" /> | |||||
| </div> | |||||
| <div class="form-row"> | |||||
| <label for="add-description">Add Position Description</label> | |||||
| <input type="text" placeholder="President" id="add-description" name="add-description" value="" /> | |||||
| </div> | |||||
| <div class="form-row"> | |||||
| <input class="submit" type="submit" name="create" value="Create Position" /> | |||||
| </div> | |||||
| </div> | |||||
| <div class="form-section"> | |||||
| <h3>Force Check-In</h3> | |||||
| <div class="form-row"> | |||||
| <input type="text" placeholder="Voter Search" id="voter-searchbox" name="voter-searchbox" value="" /> | |||||
| <div id="voter-results"></div> | |||||
| <input type="hidden" name="voter" id="voter-input" value="0" /> | |||||
| <input type="hidden" name="voter-smid" id="voter-smid" value="0" /> | |||||
| <div id="selectedVoter" class="selected candidate voter"> | |||||
| <span class="placeholder">No Selected Voter</span> | |||||
| </div> | |||||
| </div> | |||||
| <div class="form-row"> | |||||
| <input class="submit" type="submit" name="force" value="Force Check In" /> | |||||
| </div> | |||||
| </div> | |||||
| </form> | |||||
| <?php | |||||
| $footer = new Footer(); | |||||
| $footer->output(); |
| <?php | |||||
| define('BASE', __DIR__); | |||||
| define('BASEURL', $_SERVER['SERVER_NAME']); | |||||
| require_once(BASE . '/inc/db.php'); | |||||
| require_once(BASE . '/inc/user.php'); | |||||
| $required = ['db-host', 'db-username', 'db-password', 'db-database', 'flyers-user', 'flyers-password']; | |||||
| function test_config($params) { | |||||
| global $required, $db, $user; | |||||
| if (!empty($params) && count($params) != count($required)) | |||||
| return "All fields are required"; | |||||
| mysqli_report(MYSQLI_REPORT_OFF); | |||||
| $mysql = mysqli_connect($params['db-host'], $params['db-username'], $params['db-password']); | |||||
| if (!$mysql) | |||||
| return "Unable to connect to the database."; | |||||
| mysqli_select_db($mysql, $params['db-database']); | |||||
| if (mysqli_error($mysql)) | |||||
| return "Unable to access database '" . htmlspecialchars($params['db-database']) . "': " . mysqli_error($mysql); | |||||
| mysqli_multi_query($mysql, " | |||||
| CREATE TABLE IF NOT EXISTS `members` ( | |||||
| `skymanager_id` integer NOT NULL PRIMARY KEY, | |||||
| `name` varchar(128) NOT NULL, | |||||
| `username` varchar(64) NOT NULL, | |||||
| `voting_id` int DEFAULT NULL UNIQUE, | |||||
| `email` varchar(128) DEFAULT NULL, | |||||
| `pollworker` BOOLEAN NOT NULL DEFAULT false, | |||||
| `checkedin` BOOLEAN NOT NULL DEFAULT false); | |||||
| CREATE TABLE IF NOT EXISTS `proxy` ( | |||||
| `voting_id` integer NOT NULL, | |||||
| `delegate_id` integer NOT NULL, | |||||
| PRIMARY KEY (`voting_id`, `delegate_id`)); | |||||
| CREATE TABLE IF NOT EXISTS `positions` ( | |||||
| `position` varchar(64) NOT NULL PRIMARY KEY, | |||||
| `description` varchar(128) NOT NULL UNIQUE, | |||||
| `active` BOOLEAN NOT NULL DEFAULT false | |||||
| ); | |||||
| CREATE TABLE IF NOT EXISTS `votes` ( | |||||
| `candidate_id` integer NOT NULL, | |||||
| `position` varchar(64) NOT NULL, | |||||
| `member_id` integer NOT NULL, | |||||
| `vote_type` enum('IN PERSON','ONLINE','PROXY IN PERSON','PROXY ONLINE','UNANIMOUS') NOT NULL DEFAULT 'ONLINE', | |||||
| `submitted_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, | |||||
| `submitter_id` integer NOT NULL, | |||||
| PRIMARY KEY (`position`,`member_id`), | |||||
| FOREIGN KEY (`position`) REFERENCES `positions` (`position`) ON DELETE CASCADE) | |||||
| "); | |||||
| do { | |||||
| if (mysqli_error($mysql)) | |||||
| return "Unable to set up tables: " . mysqli_error($mysql); | |||||
| } while (mysqli_next_result($mysql) || mysqli_error($mysql)); | |||||
| $db = DBHandler::wrap($mysql); | |||||
| $success = $user->login($params['flyers-user'], $params['flyers-password']); | |||||
| if (!$success) | |||||
| return "Login Failed"; | |||||
| $db->query("UPDATE members SET `pollworker`=TRUE where skymanager_id=" . ((int) $user->getUserId())); | |||||
| if ($db->getError()) | |||||
| return "Failed to update user permissions"; | |||||
| $conf = json_encode([ | |||||
| 'host' => $params['db-host'], | |||||
| 'user' => $params['db-username'], | |||||
| 'pass' => $params['db-password'], | |||||
| 'db' => $params['db-database'] | |||||
| ], JSON_PRETTY_PRINT); | |||||
| if (file_put_contents(BASE . "/inc/config.json", $conf) === false) | |||||
| return "Failed to write configuration."; | |||||
| return false; | |||||
| } | |||||
| $params = []; | |||||
| foreach ($required as $field) { | |||||
| if (array_key_exists($field, $_POST) && !empty($_POST[$field])) | |||||
| $params[$field] = $_POST[$field]; | |||||
| } | |||||
| $error = null; | |||||
| if (!empty($params)) | |||||
| $error = test_config($params); | |||||
| if ($error === false) { | |||||
| header('Location: /index.php'); | |||||
| die(); | |||||
| } | |||||
| ?> | |||||
| <!doctype html> | |||||
| <html> | |||||
| <head> | |||||
| <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" /> | |||||
| <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css2?family=Fira+Sans:wght@400;600;800&display=swap" /> | |||||
| <link rel="stylesheet" type="text/css" href="/styles/style.css" /> | |||||
| </head> | |||||
| <body> | |||||
| <div id="container"> | |||||
| <div class="header"> | |||||
| <h1>Michigan Flyers</h1> | |||||
| <h2>Voting System Setup</h2> | |||||
| </div> | |||||
| <div class="content"> | |||||
| <div class="page"> | |||||
| <?php if(!empty($error)) echo "<span class=\"errormessage\">$error</span>"; ?> | |||||
| <form action="configure.php" method="POST"> | |||||
| <div class="form-section"> | |||||
| <h3>Database Setup</h3> | |||||
| <div class="form-row"> | |||||
| <label for="db-host">Host</label> | |||||
| <input type="text" id="db-host" name="db-host" value="localhost" /> | |||||
| </div> | |||||
| <div class="form-row"> | |||||
| <label for="db-database">Database Name</label> | |||||
| <input type="text" id="db-database" name="db-database" /> | |||||
| </div> | |||||
| <div class="form-row"> | |||||
| <label for="db-username">Username</label> | |||||
| <input type="text" id="db-username" name="db-username" /> | |||||
| </div> | |||||
| <div class="form-row"> | |||||
| <label for="db-password">Password</label> | |||||
| <input type="password" id="db-password" name="db-password" /> | |||||
| </div> | |||||
| </div> | |||||
| <div class="form-section"> | |||||
| <h3>Flyers Access Setup</h3> | |||||
| <div class="form-row"> | |||||
| <label for="flyers-user">Voting Administrator</label> | |||||
| <input type="text" id="flyers-user" name="flyers-user" /> | |||||
| </div> | |||||
| <div class="form-row"> | |||||
| <label for="flyers-password">Password</label> | |||||
| <input type="password" name="flyers-password" /> | |||||
| </div> | |||||
| <div class="form-row"> | |||||
| <input type="submit" name="login" value="Setup!" /> | |||||
| </div> | |||||
| </div> | |||||
| </form> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </body> | |||||
| </html> |
| class DBHandler{ | class DBHandler{ | ||||
| private $mysql; | private $mysql; | ||||
| function __construct($hostname, $username, $password, $database){ | |||||
| global $dbs; | |||||
| private function __construct() {} | |||||
| $this->mysql = mysqli_connect($hostname, $username, $password); | |||||
| if(!$this->mysql) die("MySql error: " . mysql_error()); | |||||
| public static function Connect($hostname, $username, $password, $database){ | |||||
| $handler = new DBHandler(); | |||||
| mysqli_select_db($this->mysql, $database); | |||||
| $handler->mysql = mysqli_connect($hostname, $username, $password); | |||||
| if(!$handler->mysql) die("MySql error: " . mysql_error()); | |||||
| mysqli_select_db($handler->mysql, $database); | |||||
| return $handler; | |||||
| } | |||||
| public static function Wrap($mysql) { | |||||
| $handler = new DBHandler(); | |||||
| $handler->mysql = $mysql; | |||||
| return $handler; | |||||
| } | } | ||||
| public function sanitize($text){ | public function sanitize($text){ | ||||
| } | } | ||||
| public function query($query){ | public function query($query){ | ||||
| return mysqli_query($this->mysql, $query); | |||||
| try { | |||||
| return mysqli_query($this->mysql, $query); | |||||
| } catch (Throwable $err) { | |||||
| return false; | |||||
| } | |||||
| } | } | ||||
| public function fetchRow($query){ | public function fetchRow($query){ | ||||
| return base64_encode($str); | return base64_encode($str); | ||||
| } | } | ||||
| } | } | ||||
| $db = new DBHandler('localhost', '2022mfelection', '<password>', '2022mfelection'); |
| define('BASE', dirname(__DIR__)); | define('BASE', dirname(__DIR__)); | ||||
| define('BASEURL', $_SERVER['SERVER_NAME']); | define('BASEURL', $_SERVER['SERVER_NAME']); | ||||
| $config = json_decode(file_get_contents(BASE . "/inc/config.json")); | |||||
| if (empty($config)) { | |||||
| header('Location: /configure.php'); | |||||
| die(); | |||||
| } | |||||
| // Start the session | // Start the session | ||||
| session_start(); | session_start(); | ||||
| // Database and Authentication | // Database and Authentication | ||||
| require_once(BASE . '/inc/db.php'); | require_once(BASE . '/inc/db.php'); | ||||
| $db = DBHandler::Connect($config->host, $config->user, $config->pass, $config->db); | |||||
| require_once(BASE . '/inc/user.php'); | require_once(BASE . '/inc/user.php'); | ||||
| // Templates | // Templates |
| $this->username = $obj->preferred_username; | $this->username = $obj->preferred_username; | ||||
| $this->name = $obj->name; | $this->name = $obj->name; | ||||
| $this->uid = $obj->sub; | $this->uid = $obj->sub; | ||||
| $this->email = $obj->email; | |||||
| $this->email = $obj->email ?? null; | |||||
| $this->loggedin = true; | $this->loggedin = true; | ||||
| // Create user automatically on login | |||||
| $_ = $db->query('insert ignore into members (skymanager_id, name, username, email) VALUES (' . ((int) $this->uid) . ', "' . $db->sanitize($this->name) . '", "' . $db->sanitize($this->username) . '", ' . (empty($this->email) ? 'NULL' : '"' . $db->sanitize($this->email) . '"') . ')'); | |||||
| // Get voter ID | // Get voter ID | ||||
| $result = $db->fetchRow('select members.voting_id from members left join proxy on (members.voting_id=proxy.voting_id) where proxy.delegate_id is null and skymanager_id=' . ((int) $this->uid)); | $result = $db->fetchRow('select members.voting_id from members left join proxy on (members.voting_id=proxy.voting_id) where proxy.delegate_id is null and skymanager_id=' . ((int) $this->uid)); | ||||
| $admincheck = $db->fetchRow('select members.pollworker from members where skymanager_id=' . ((int) $this->uid)); | $admincheck = $db->fetchRow('select members.pollworker from members where skymanager_id=' . ((int) $this->uid)); | ||||
| if ($result) | |||||
| if ($result) { | |||||
| $this->voterId = $result['voting_id']; | $this->voterId = $result['voting_id']; | ||||
| else | |||||
| // Auto check in | |||||
| $_ = $db->query('update members set checkedin=1 where voting_id is not null and skymanager_id=' . ((int) $this->uid)); | |||||
| } else { | |||||
| $this->voterId = null; | $this->voterId = null; | ||||
| } | |||||
| if ($admincheck) | if ($admincheck) | ||||
| $this->role = $admincheck['pollworker']; | $this->role = $admincheck['pollworker']; |
| die(); | die(); | ||||
| } | } | ||||
| $header = new Header("2022 Michigan Flyers Election"); | |||||
| $header = new Header("Michigan Flyers Election"); | |||||
| $header->addStyle("/styles/style.css"); | $header->addStyle("/styles/style.css"); | ||||
| $header->addScript("/js/jquery-1.11.3.min.js"); | $header->addScript("/js/jquery-1.11.3.min.js"); | ||||
| $header->addScript("/js/search.js"); | $header->addScript("/js/search.js"); | ||||
| $header->setAttribute('title', 'Michigan Flyers'); | $header->setAttribute('title', 'Michigan Flyers'); | ||||
| $header->setAttribute('tagline', '2022 Online Ballot'); | |||||
| $header->setAttribute('tagline', 'Online Ballot'); | |||||
| $header->output(); | $header->output(); | ||||
| $candidates = $db->fetchAssoc('select skymanager_id, name, username, md5(coalesce(email, "")) as `gravatar_hash` from members where voting_id is not null'); | $candidates = $db->fetchAssoc('select skymanager_id, name, username, md5(coalesce(email, "")) as `gravatar_hash` from members where voting_id is not null'); | ||||
| $votes = $db->fetchAssoc("select position from votes where member_id={$user->voterId()}"); | $votes = $db->fetchAssoc("select position from votes where member_id={$user->voterId()}"); | ||||
| $position = $db->fetchRow("select position as code, description as label from positions where active<>0 limit 1"); | |||||
| foreach ($votes as &$vote) { | foreach ($votes as &$vote) { | ||||
| $vote = $vote['position']; | $vote = $vote['position']; | ||||
| } | } | ||||
| unset($vote); | unset($vote); | ||||
| $vicepresident_voted = in_array("VICEPRESIDENT", $votes); | |||||
| $secretary_voted = in_array("SECRETARY", $votes); | |||||
| $director_voted = in_array("DIRECTOR", $votes); | |||||
| $vicepresident_disabled = $vicepresident_voted; | |||||
| $secretary_disabled = $secretary_voted || !$vicepresident_voted; | |||||
| $director_disabled = $director_voted || !$secretary_voted || !$vicepresident_voted; | |||||
| $vicepresident_disabled_reason = $vicepresident_voted ? "You have already voted for Vice President." : ""; | |||||
| $secretary_disabled_reason = $secretary_disabled ? ($secretary_voted ? "You have already voted for Secretary." : "You must vote for Vice President first.") : ""; | |||||
| $director_disabled_reason = $director_disabled ? ($director_voted ? "You have already voted for Director." : "You must vote for Vice President and Secretary first.") : ""; | |||||
| ?> | ?> | ||||
| <?php if (empty($position)): ?> | |||||
| <h3>There are no active votes. Reload this page once voting starts.</h3> | |||||
| <?php else: ?> | |||||
| <script type="text/javascript"> | <script type="text/javascript"> | ||||
| var candidates = <?= json_encode($candidates); ?>; | var candidates = <?= json_encode($candidates); ?>; | ||||
| </script> | </script> | ||||
| <div class="form-row"> | <div class="form-row"> | ||||
| <div class="selector"> | <div class="selector"> | ||||
| <label class="radio"> | <label class="radio"> | ||||
| <input type="radio" id="vote-vicepresident" name="ballot" | |||||
| value="VICEPRESIDENT" <?= $vicepresident_disabled ? "disabled" : "checked"; ?> /> | |||||
| <span class="radio-button-label">Vice President</span> | |||||
| <?php if ($vicepresident_disabled_reason): ?> | |||||
| <div class="hover-tooltip"><?= $vicepresident_disabled_reason; ?></div> | |||||
| <?php endif; ?> | |||||
| </label> | |||||
| <label class="radio"> | |||||
| <input type="radio" id="vote-director" name="ballot" | |||||
| value="SECRETARY" <?= $secretary_disabled ? "disabled" : ($vicepresident_disabled ? "checked" : ""); ?> /> | |||||
| <span class="radio-button-label">Secretary</span> | |||||
| <?php if ($secretary_disabled_reason): ?> | |||||
| <div class="hover-tooltip"><?= $secretary_disabled_reason; ?></div> | |||||
| <?php endif; ?> | |||||
| </label> | |||||
| <label class="radio"> | |||||
| <input type="radio" id="vote-director" name="ballot" | |||||
| value="DIRECTOR" <?= $director_disabled ? "disabled" : ($vicepresident_disabled && $secretary_disabled ? "checked" : ""); ?> /> | |||||
| <span class="radio-button-label">Director-At-Large</span> | |||||
| <?php if ($director_disabled_reason): ?> | |||||
| <div class="hover-tooltip"><?= $director_disabled_reason; ?></div> | |||||
| <?php endif; ?> | |||||
| <input type="radio" id="vote-<?= $position['code']; ?>" name="ballot" | |||||
| value="<?= $position['code']; ?>" checked /> | |||||
| <span class="radio-button-label"><?= $position['label'] ?></span> | |||||
| </label> | </label> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </form> | </form> | ||||
| <?php | <?php | ||||
| endif; | |||||
| $footer = new Footer(); | $footer = new Footer(); | ||||
| $footer->output(); | $footer->output(); |
| csc.appendChild(profileimgsect); | csc.appendChild(profileimgsect); | ||||
| csc.appendChild(profiletext); | csc.appendChild(profiletext); | ||||
| var smid = document.getElementById('voter-smid'); | |||||
| if (smid) smid.value = candidate.skymanager_id; | |||||
| document.getElementById('voter-input').value = candidate.voting_id; | document.getElementById('voter-input').value = candidate.voting_id; | ||||
| document.getElementById('voter-searchbox').value = ""; | document.getElementById('voter-searchbox').value = ""; | ||||
| search(''); | search(''); |
| $header = new Header("Login Required"); | $header = new Header("Login Required"); | ||||
| $header->addStyle("/styles/style.css"); | $header->addStyle("/styles/style.css"); | ||||
| $header->setAttribute('title', 'Michigan Flyers'); | $header->setAttribute('title', 'Michigan Flyers'); | ||||
| $header->setAttribute('tagline', '2022 Online Ballot'); | |||||
| $header->setAttribute('tagline', 'Online Ballot'); | |||||
| $header->output(); | $header->output(); | ||||
| ?> | ?> | ||||
| <h3 id="login-help">Sign in with your Skymanager Account</h3> | <h3 id="login-help">Sign in with your Skymanager Account</h3> |
| margin: 0px -20px; | margin: 0px -20px; | ||||
| } | } | ||||
| form .form-row:nth-child(2n+1) { | |||||
| form .form-row:nth-child(2n+1 of .form-row) { | |||||
| background-color: #eee; | background-color: #eee; | ||||
| } | } | ||||
| form .form-section > .form-row { | |||||
| border-left: 4px solid #6ac; | |||||
| } | |||||
| form .form-section { | |||||
| margin-bottom: 20px; | |||||
| } | |||||
| form .form-section h3 { | |||||
| background-color: #6ac; | |||||
| color: #fff; | |||||
| margin: 0px -20px; | |||||
| padding: 10px; | |||||
| padding-left: 16px; | |||||
| border-left: 4px solid #6ac; | |||||
| } | |||||
| /* | |||||
| form .form-section:before, form .form-section:after { | |||||
| content: ''; | |||||
| display: block; | |||||
| border: 0px solid #6ac; | |||||
| width: 10px; | |||||
| margin-left: -20px; | |||||
| } | |||||
| form .form-section:before { border-width: 4px 0 0 0; } | |||||
| form .form-section:after { border-width: 0 0 4px 0; } | |||||
| */ | |||||
| form input { | form input { | ||||
| box-sizing: border-box; | box-sizing: border-box; | ||||
| width: 100%; | width: 100%; | ||||
| display:block; | display:block; | ||||
| padding: 10px; | padding: 10px; | ||||
| } | } | ||||
| form .split-button { | |||||
| display: flex; | |||||
| flex-direction: row; | |||||
| align-content: stretch; | |||||
| gap: 20px; | |||||
| } | |||||
| form .split-button > input { | |||||
| flex-grow: 1; | |||||
| } | |||||
| input[type=submit] { | |||||
| background: linear-gradient(#eee,#e7e7e7); | |||||
| border: 1px solid rgba(0,0,0,.2); | |||||
| border-radius: 3px; | |||||
| } | |||||
| input[type=submit].danger { | |||||
| background: linear-gradient(#900, #800); | |||||
| color: #fff; | |||||
| font-weight: bold; | |||||
| } | |||||
| input[type=submit]:hover { background: linear-gradient(#ddd,#d7d7d7); } | |||||
| input[type=submit].danger:hover { background: linear-gradient(#800,#700); } |
| if ($user->loggedin()) { | if ($user->loggedin()) { | ||||
| $html .= "\t\t\t\t" . $user->name() . "\n"; | $html .= "\t\t\t\t" . $user->name() . "\n"; | ||||
| $html .= "\t\t\t\t" . " <a href=\"/login.php?logout\">Log Out</a>\n"; | $html .= "\t\t\t\t" . " <a href=\"/login.php?logout\">Log Out</a>\n"; | ||||
| if ($user->getRole() === "admin") | |||||
| $html .= "\t\t\t\t" . " <a href=\"/admin/checkin.php\">Poll Worker</a>\n"; | |||||
| if ($user->getRole() === "admin") { | |||||
| $html .= "\t\t\t\t" . " <a href=\"/admin/checkin.php\">Volunteer</a>\n"; | |||||
| $html .= "\t\t\t\t" . " <a href=\"/admin/voting.php\">Admin</a>\n"; | |||||
| } | |||||
| $html .= "\t\t\t\t<a href=\"/index.php\">Home</a>\n"; | $html .= "\t\t\t\t<a href=\"/index.php\">Home</a>\n"; | ||||
| } else if (basename($_SERVER['PHP_SELF']) != 'login.php') { | } else if (basename($_SERVER['PHP_SELF']) != 'login.php') { | ||||
| $html .= "\t\t\t\t<a href=\"/login.php\">Log In</a>\n"; | $html .= "\t\t\t\t<a href=\"/login.php\">Log In</a>\n"; |
| die(); | die(); | ||||
| } | } | ||||
| $active_position = $db->fetchRow("select position as code, description as label from positions where active<>0 limit 1"); | |||||
| $candidate_selected = (int) $_POST['candidate']; | $candidate_selected = (int) $_POST['candidate']; | ||||
| $ballot = $_POST['ballot']; | $ballot = $_POST['ballot']; | ||||
| if ($candidate_selected != $_POST['candidate']) $error = "An eccor occurred while processing your ballot. Please retry."; | if ($candidate_selected != $_POST['candidate']) $error = "An eccor occurred while processing your ballot. Please retry."; | ||||
| if ($ballot !== "VICEPRESIDENT" && $ballot !== "SECRETARY" && $ballot !== "DIRECTOR") $error = "An eccor occurred while processing your ballot. Please retry."; | |||||
| if (empty($active_position) || $ballot !== $active_position['code']) $error = "An eccor occurred while processing your ballot. Please retry."; | |||||
| if (!$error) { | if (!$error) { | ||||
| //$result = $db->query("INSERT INTO votes (candidate_id, position, member_id) values ($candidate_selected, \"$ballot\", {$user->voterId()})"); | //$result = $db->query("INSERT INTO votes (candidate_id, position, member_id) values ($candidate_selected, \"$ballot\", {$user->voterId()})"); | ||||
| $result = $db->query("INSERT INTO votes (candidate_id, position, member_id, vote_type, submitter_id) SELECT $candidate_selected, \"$ballot\", {$user->voterId()}, 'ONLINE', {$user->voterId()} UNION SELECT $candidate_selected, \"$ballot\", voting_id, 'PROXY ONLINE', delegate_id from proxy where delegate_id={$user->voterId()}"); | |||||
| $result = false; | |||||
| try { | |||||
| $result = $db->query("INSERT INTO votes (candidate_id, position, member_id, vote_type, submitter_id) SELECT $candidate_selected, \"$ballot\", {$user->voterId()}, 'ONLINE', {$user->voterId()} UNION SELECT $candidate_selected, \"$ballot\", voting_id, 'PROXY ONLINE', delegate_id from proxy where delegate_id={$user->voterId()}"); | |||||
| } catch (Throwable $ignore) {} | |||||
| $candidate = $db->fetchRow('select skymanager_id, name, username, md5(coalesce(email, "")) as `gravatar_hash` from members where skymanager_id=' . $candidate_selected); | $candidate = $db->fetchRow('select skymanager_id, name, username, md5(coalesce(email, "")) as `gravatar_hash` from members where skymanager_id=' . $candidate_selected); | ||||
| if ($result) { | if ($result) { | ||||
| $to = 'mf2022elec@gmail.com'; | $to = 'mf2022elec@gmail.com'; | ||||
| } | } | ||||
| } | } | ||||
| $votes = $db->fetchAssoc("select position from votes where member_id={$user->voterId()}"); | |||||
| foreach ($votes as &$vote) { | |||||
| $vote = $vote['position']; | |||||
| } | |||||
| unset($vote); | |||||
| $positions = [ | |||||
| 'VICEPRESIDENT' => 'Vice President', | |||||
| 'SECRETARY' => 'Secretary', | |||||
| 'DIRECTOR' => 'Director' | |||||
| ]; | |||||
| $voteFor = null; | |||||
| if (count($votes) < count($positions)) { | |||||
| $voteFor = array_values($positions)[count($votes)]; | |||||
| } | |||||
| $header = new Header("2022 Michigan Flyers Election"); | |||||
| $header = new Header("Michigan Flyers Election"); | |||||
| $header->addStyle("/styles/style.css"); | $header->addStyle("/styles/style.css"); | ||||
| $header->addStyle("/styles/vote.css"); | $header->addStyle("/styles/vote.css"); | ||||
| $header->addScript("/js/jquery-1.11.3.min.js"); | $header->addScript("/js/jquery-1.11.3.min.js"); | ||||
| $header->addScript("/js/search.js"); | $header->addScript("/js/search.js"); | ||||
| $header->setAttribute('title', 'Michigan Flyers'); | $header->setAttribute('title', 'Michigan Flyers'); | ||||
| $header->setAttribute('tagline', '2022 Online Ballot'); | |||||
| $header->setAttribute('tagline', 'Online Ballot'); | |||||
| $header->output(); | $header->output(); | ||||
| ?> | ?> | ||||
| <div id="vote-result"> | <div id="vote-result"> | ||||
| "Your ballot has already been submitted.") ?> | "Your ballot has already been submitted.") ?> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <?php if ($voteFor): ?> | |||||
| <a href="/" id="vote-again">Vote for <?= $voteFor; ?></a> | |||||
| <?php endif; ?> | |||||
| <a href="/" id="vote-again">Return to voting</a> | |||||
| <?php if ($result): ?> | <?php if ($result): ?> | ||||
| <div id="ballot"> | <div id="ballot"> | ||||
| <div class="ballot-section"> | <div class="ballot-section"> | ||||
| <h4 class="section-heading">Vice Position</h4> | |||||
| <h2 class="ballot-position"><?= $positions[$ballot]; ?></h2> | |||||
| <h4 class="section-heading">Position</h4> | |||||
| <h2 class="ballot-position"><?= $active_position['label']; ?></h2> | |||||
| </div> | </div> | ||||
| <div class="ballot-section"> | <div class="ballot-section"> | ||||
| <h4 class="section-heading">Candidate</h4> | <h4 class="section-heading">Candidate</h4> |