mirror of
https://git.cant.at/Madeorsk/PollVerlaine
synced 2024-11-24 23:04:33 +01:00
Multiple choices and redirections
+ Now possible to allow multiple choices; * Add partial settings support; * Fixed and moved some redirections to appropriate pages; * CSS adjustments.
This commit is contained in:
parent
b7ece5cdad
commit
7b0a619b0e
33
index.php
33
index.php
@ -41,8 +41,14 @@ Flight::route("GET /polls/@id:[a-fA-F0-9]+", function ($id) {
|
||||
Flight::json(format_poll($poll));
|
||||
else
|
||||
{
|
||||
Flight::render("poll", ["poll" => $poll], "body_content");
|
||||
Flight::render("layout");
|
||||
// If unique_ip option is enabled => Only allow unregistered IPs.
|
||||
if (!$poll->settings->unique_ip && isset($poll->ips[Flight::request()->ip]))
|
||||
Flight::redirect("/polls/$id/results"); // A vote is already registered with this IP: redirect.
|
||||
else
|
||||
{
|
||||
Flight::render("poll", ["poll" => $poll], "body_content");
|
||||
Flight::render("layout");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -59,17 +65,14 @@ Flight::route("POST /polls/@id:[a-fA-F0-9]+/vote", function ($id) {
|
||||
{
|
||||
if (isset(Flight::request()->data["options"]) && is_array(Flight::request()->data["options"]))
|
||||
{ // Check that an options id array exists.
|
||||
//TODO Check that only the authorized number of options are selected.
|
||||
if($poll->vote(Flight::request()->data["options"]) === false) // Vote for the given options.
|
||||
{
|
||||
Flight::halt(403, "<h1>403 Forbidden</h1><h3>Too many votes for this IP address.</h3>");
|
||||
}
|
||||
else
|
||||
if ($poll->vote(Flight::request()->data["options"])) // Vote for the given options.
|
||||
{
|
||||
// Then save and show poll data.
|
||||
$poll->save();
|
||||
Flight::json(format_poll($poll));
|
||||
}
|
||||
else
|
||||
Flight::halt(403, "<h1>403 Forbidden</h1><h3>Too many votes for this IP address or too many options selected.</h3>");
|
||||
}
|
||||
else
|
||||
Flight::halt(403, "<h1>403 Forbidden</h1><h3>Invalid data.</h3>");
|
||||
@ -79,18 +82,16 @@ Flight::route("POST /polls/@id:[a-fA-F0-9]+/vote", function ($id) {
|
||||
if (isset(Flight::request()->data["options"]))
|
||||
{ // Check that any data has been sent.
|
||||
$selected_options = Flight::request()->data["options"];
|
||||
if (is_string($selected_options))
|
||||
{ // If it is a string, input[type="radio"] were used so only one option is selected.
|
||||
if($poll->vote([intval($selected_options)]) === false) // Vote for the selected option.
|
||||
{
|
||||
Flight::redirect('/', 401);
|
||||
}
|
||||
else
|
||||
if (is_array($selected_options))
|
||||
{
|
||||
if($poll->vote($selected_options)) // Vote for the selected option.
|
||||
{
|
||||
$poll->save();
|
||||
Flight::redirect("/polls/$id/results"); // Redirect to the results.
|
||||
}
|
||||
} //TODO: Multiple options case.
|
||||
else
|
||||
Flight::redirect("/polls/$id"); // Error: Redirect to the vote page.
|
||||
}
|
||||
else
|
||||
Flight::redirect("/polls/$id"); // Error: Redirect to the vote page.
|
||||
}
|
||||
|
@ -4,6 +4,16 @@ require __DIR__ . "/../config/app.php";
|
||||
|
||||
define("SAVE_PATH", __DIR__ . "/../db");
|
||||
|
||||
define("DEFAULT_SETTINGS", ["unique_ip" => true, "multiple_choices" => false]);
|
||||
|
||||
function settings_or_default($settings)
|
||||
{
|
||||
return [
|
||||
"unique_ip" => isset($settings["unique_ip"]) ? $settings["unique_ip"] : DEFAULT_SETTINGS["unique_ip"],
|
||||
"multiple_choices" => isset($settings["multiple_choices"]) ? $settings["multiple_choices"] : DEFAULT_SETTINGS["multiple_choices"],
|
||||
];
|
||||
}
|
||||
|
||||
class Poll
|
||||
{
|
||||
/**
|
||||
@ -23,7 +33,7 @@ class Poll
|
||||
"votes" => 0,
|
||||
];
|
||||
}
|
||||
$poll->settings = $request_data->settings;
|
||||
$poll->settings = isset($request_data->settings) ? settings_or_default($request_data->settings) : DEFAULT_SETTINGS;
|
||||
$poll->gen_new_id();
|
||||
$poll->delete_token = bin2hex(openssl_random_pseudo_bytes(16));
|
||||
$poll->save();
|
||||
@ -70,7 +80,7 @@ class Poll
|
||||
public $title;
|
||||
public $creation_date;
|
||||
public $options = [];
|
||||
public $settings = [];
|
||||
public $settings;
|
||||
public $ips = [];
|
||||
public $delete_token;
|
||||
|
||||
@ -98,14 +108,20 @@ class Poll
|
||||
*/
|
||||
public function vote(array $options)
|
||||
{
|
||||
if($this->settings->unique_ip === false)
|
||||
{
|
||||
if(isset($this->ips[Flight::request()->ip]))
|
||||
return false;
|
||||
if (empty($options))
|
||||
return false; // Disallow void selection vote. TODO: Allow it in settings?
|
||||
|
||||
if (!$this->settings->unique_ip)
|
||||
{ // If unique_ip option is enabled => Only allow unregistered IPs.
|
||||
if (isset($this->ips[Flight::request()->ip]))
|
||||
return false; // A vote is already registered with this IP: error.
|
||||
else
|
||||
$this->ips[Flight::request()->ip] = true;
|
||||
$this->ips[Flight::request()->ip] = true; // We register the IP in the used IPs array.
|
||||
}
|
||||
|
||||
if (!$this->settings->multiple_choices && count($options) > 1)
|
||||
return false; // If multiple_choices is not selected, disallow an options array with more than one selected option.
|
||||
|
||||
// For each option in the list, add 1 to the vote number in the poll data.
|
||||
foreach ($options as $option)
|
||||
if (isset($this->options[intval($option)])) // Check invalid options id.
|
||||
@ -125,7 +141,7 @@ class Poll
|
||||
"options" => $this->options,
|
||||
"delete_token" => $this->delete_token,
|
||||
"ips" => $this->ips,
|
||||
"settings" => $this->settings
|
||||
"settings" => $this->settings,
|
||||
]), $db);
|
||||
dba_close($db);
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ main a.button:hover
|
||||
|
||||
main hr
|
||||
{
|
||||
border: solid #343434 thin;
|
||||
border: solid #0088E5 thin;
|
||||
width: 25rem;
|
||||
}
|
||||
|
||||
|
@ -37,9 +37,10 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
body: JSON.stringify({
|
||||
title: form.querySelector(`input[name="title"]`).value,
|
||||
options: get_choices(form),
|
||||
settings: {
|
||||
"unique_ip": form.querySelector(`input[name="unique_ip"]`).checked,
|
||||
}
|
||||
settings: {
|
||||
unique_ip: form.querySelector(`input[name="unique_ip"]`).checked,
|
||||
multiple_choices: form.querySelector(`input[name="multiple_choices"]`).checked,
|
||||
}
|
||||
}),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
@ -15,6 +15,11 @@
|
||||
<label for="unique_ip" class="check"></label>
|
||||
<label for="unique_ip">Allow multiple votes from a single IP</label>
|
||||
</div>
|
||||
<div class="option">
|
||||
<input type="checkbox" name="multiple_choices" value="multiple_choices" id="multiple_choices" />
|
||||
<label for="multiple_choices" class="check"></label>
|
||||
<label for="multiple_choices">Allow to select multiple choices in one vote</label>
|
||||
</div>
|
||||
<input type="submit" value="Create poll" />
|
||||
</form>
|
||||
<div id="result" hidden>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<form action="/polls/<?= $poll->id ?>/vote" method="POST" id="poll">
|
||||
<?php foreach ($poll->options as $id => $option): ?>
|
||||
<div class="option">
|
||||
<input type="radio" name="options" value="<?= $id ?>" id="option-<?= $id ?>" />
|
||||
<input type="<?= $poll->settings->multiple_choices ? "checkbox" : "radio" ?>" name="options[]" value="<?= $id ?>" id="option-<?= $id ?>" />
|
||||
<label for="option-<?= $id ?>" class="check"></label>
|
||||
<label for="option-<?= $id ?>"><?= $option->label ?></label>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user