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));
|
Flight::json(format_poll($poll));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Flight::render("poll", ["poll" => $poll], "body_content");
|
// If unique_ip option is enabled => Only allow unregistered IPs.
|
||||||
Flight::render("layout");
|
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
|
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"]))
|
if (isset(Flight::request()->data["options"]) && is_array(Flight::request()->data["options"]))
|
||||||
{ // Check that an options id array exists.
|
{ // 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"])) // Vote for the given options.
|
||||||
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
|
|
||||||
{
|
{
|
||||||
// Then save and show poll data.
|
// Then save and show poll data.
|
||||||
$poll->save();
|
$poll->save();
|
||||||
Flight::json(format_poll($poll));
|
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
|
else
|
||||||
Flight::halt(403, "<h1>403 Forbidden</h1><h3>Invalid data.</h3>");
|
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"]))
|
if (isset(Flight::request()->data["options"]))
|
||||||
{ // Check that any data has been sent.
|
{ // Check that any data has been sent.
|
||||||
$selected_options = Flight::request()->data["options"];
|
$selected_options = Flight::request()->data["options"];
|
||||||
if (is_string($selected_options))
|
if (is_array($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.
|
if($poll->vote($selected_options)) // Vote for the selected option.
|
||||||
{
|
|
||||||
Flight::redirect('/', 401);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
$poll->save();
|
$poll->save();
|
||||||
Flight::redirect("/polls/$id/results"); // Redirect to the results.
|
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
|
else
|
||||||
Flight::redirect("/polls/$id"); // Error: Redirect to the vote page.
|
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("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
|
class Poll
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -23,7 +33,7 @@ class Poll
|
|||||||
"votes" => 0,
|
"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->gen_new_id();
|
||||||
$poll->delete_token = bin2hex(openssl_random_pseudo_bytes(16));
|
$poll->delete_token = bin2hex(openssl_random_pseudo_bytes(16));
|
||||||
$poll->save();
|
$poll->save();
|
||||||
@ -70,7 +80,7 @@ class Poll
|
|||||||
public $title;
|
public $title;
|
||||||
public $creation_date;
|
public $creation_date;
|
||||||
public $options = [];
|
public $options = [];
|
||||||
public $settings = [];
|
public $settings;
|
||||||
public $ips = [];
|
public $ips = [];
|
||||||
public $delete_token;
|
public $delete_token;
|
||||||
|
|
||||||
@ -98,14 +108,20 @@ class Poll
|
|||||||
*/
|
*/
|
||||||
public function vote(array $options)
|
public function vote(array $options)
|
||||||
{
|
{
|
||||||
if($this->settings->unique_ip === false)
|
if (empty($options))
|
||||||
{
|
return false; // Disallow void selection vote. TODO: Allow it in settings?
|
||||||
if(isset($this->ips[Flight::request()->ip]))
|
|
||||||
return false;
|
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
|
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.
|
// For each option in the list, add 1 to the vote number in the poll data.
|
||||||
foreach ($options as $option)
|
foreach ($options as $option)
|
||||||
if (isset($this->options[intval($option)])) // Check invalid options id.
|
if (isset($this->options[intval($option)])) // Check invalid options id.
|
||||||
@ -125,7 +141,7 @@ class Poll
|
|||||||
"options" => $this->options,
|
"options" => $this->options,
|
||||||
"delete_token" => $this->delete_token,
|
"delete_token" => $this->delete_token,
|
||||||
"ips" => $this->ips,
|
"ips" => $this->ips,
|
||||||
"settings" => $this->settings
|
"settings" => $this->settings,
|
||||||
]), $db);
|
]), $db);
|
||||||
dba_close($db);
|
dba_close($db);
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ main a.button:hover
|
|||||||
|
|
||||||
main hr
|
main hr
|
||||||
{
|
{
|
||||||
border: solid #343434 thin;
|
border: solid #0088E5 thin;
|
||||||
width: 25rem;
|
width: 25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,9 +37,10 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
title: form.querySelector(`input[name="title"]`).value,
|
title: form.querySelector(`input[name="title"]`).value,
|
||||||
options: get_choices(form),
|
options: get_choices(form),
|
||||||
settings: {
|
settings: {
|
||||||
"unique_ip": form.querySelector(`input[name="unique_ip"]`).checked,
|
unique_ip: form.querySelector(`input[name="unique_ip"]`).checked,
|
||||||
}
|
multiple_choices: form.querySelector(`input[name="multiple_choices"]`).checked,
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
@ -15,6 +15,11 @@
|
|||||||
<label for="unique_ip" class="check"></label>
|
<label for="unique_ip" class="check"></label>
|
||||||
<label for="unique_ip">Allow multiple votes from a single IP</label>
|
<label for="unique_ip">Allow multiple votes from a single IP</label>
|
||||||
</div>
|
</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" />
|
<input type="submit" value="Create poll" />
|
||||||
</form>
|
</form>
|
||||||
<div id="result" hidden>
|
<div id="result" hidden>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<form action="/polls/<?= $poll->id ?>/vote" method="POST" id="poll">
|
<form action="/polls/<?= $poll->id ?>/vote" method="POST" id="poll">
|
||||||
<?php foreach ($poll->options as $id => $option): ?>
|
<?php foreach ($poll->options as $id => $option): ?>
|
||||||
<div class="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 ?>" class="check"></label>
|
||||||
<label for="option-<?= $id ?>"><?= $option->label ?></label>
|
<label for="option-<?= $id ?>"><?= $option->label ?></label>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user