Merge branch 'Justine/Issue1' into 'develop'

Collecting polled users emails

Closes #38

See merge request framasoft/framadate!266
This commit is contained in:
Thomas Citharel 2018-04-19 16:55:21 +02:00
commit 0409256588
18 changed files with 391 additions and 46 deletions

View File

@ -17,7 +17,9 @@
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
*/
use Framadate\Migration\AddColumn_collect_mail_In_poll;
use Framadate\Migration\AddColumn_hidden_In_poll_For_0_9;
use Framadate\Migration\AddColumn_mail_In_vote;
use Framadate\Migration\AddColumn_receiveNewComments_For_0_9;
use Framadate\Migration\AddColumn_uniqId_In_vote_For_0_9;
use Framadate\Migration\AddColumn_ValueMax_In_poll_For_1_1;
@ -53,6 +55,8 @@ $migrations = [
new Increase_pollId_size(),
new AddColumn_ValueMax_In_poll_For_1_1(),
new Fix_MySQL_No_Zero_Date(),
new AddColumn_mail_In_vote(),
new AddColumn_collect_mail_In_poll()
];
// ---------------------------------------

View File

@ -80,7 +80,7 @@ $messagePollCreated = $sessionService->get("Framadate", "messagePollCreated", FA
if ($messagePollCreated) {
$sessionService->remove("Framadate", "messagePollCreated");
$message = new Message('success', __('adminstuds', 'The poll is created.'));
}
@ -219,6 +219,11 @@ $selectedNewVotes = [];
if (!empty($_POST['save'])) { // Save edition of an old vote
$name = $inputService->filterName($_POST['name']);
if(empty($_POST['mail']) || $inputService->filterMail($_POST['mail'])===false) {
$mail = null;
} else {
$mail = $inputService->filterMail($_POST['mail']);
}
$editedVote = filter_input(INPUT_POST, 'save', FILTER_VALIDATE_INT);
$choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]);
$slots_hash = $inputService->filterMD5($_POST['control']);
@ -233,7 +238,7 @@ if (!empty($_POST['save'])) { // Save edition of an old vote
if ($message === null) {
// Update vote
try {
$result = $pollService->updateVote($poll_id, $editedVote, $name, $choices, $slots_hash);
$result = $pollService->updateVote($poll_id, $editedVote, $name, $choices, $slots_hash, $mail);
if ($result) {
$message = new Message('success', __('adminstuds', 'Vote updated'));
} else {
@ -249,6 +254,11 @@ if (!empty($_POST['save'])) { // Save edition of an old vote
}
} elseif (isset($_POST['save'])) { // Add a new vote
$name = $inputService->filterName($_POST['name']);
if(empty($_POST['mail']) || $inputService->filterMail($_POST['mail'])===false) {
$mail = null;
} else {
$mail = $inputService->filterMail($_POST['mail']);
}
$choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]);
$slots_hash = $inputService->filterMD5($_POST['control']);
@ -262,7 +272,7 @@ if (!empty($_POST['save'])) { // Save edition of an old vote
if ($message === null) {
// Add vote
try {
$result = $pollService->addVote($poll_id, $name, $choices, $slots_hash);
$result = $pollService->addVote($poll_id, $name, $choices, $slots_hash, $mail);
if ($result) {
$message = new Message('success', __('adminstuds', 'Vote added'));
} else {
@ -398,6 +408,37 @@ if (isset($_GET['delete_column'])) {
}
}
// -------------------------------
// Collect the mails of a column
// -------------------------------
if (isset($_GET['collect_mail'])) {
$column_str = strval(filter_input(INPUT_GET, 'collect_mail', FILTER_DEFAULT));
$column_str = strval(Utils::base64url_decode($column_str));
$column = intval($column_str);
$votes = $pollService->splitVotes($pollService->allVotesByPollId($poll_id));
$mails_yes = $mails_ifneedbe = $mails_no = [];
foreach ($votes as $vote) {
if (intval($vote->choices[$column]) === 2 && $vote->mail !== NULL) {
$mails_yes[] = $vote->mail;
} elseif (intval($vote->choices[$column]) === 1 && $vote->mail !== NULL) {
$mails_ifneedbe[] = $vote->mail;
} elseif($vote->mail !== NULL) {
$mails_no[] = $vote->mail;
}
}
$smarty->assign('poll_id', $poll_id);
$smarty->assign('admin_poll_id', $admin_poll_id);
$smarty->assign('admin', true);
$smarty->assign('title', __('Generic', 'Poll') . ' - ' . $poll->title . ' - ' . __('adminstuds', 'Collect the emails of the polled users for the choice'));
$smarty->assign('mails_yes', $mails_yes);
$smarty->assign('mails_ifneedbe', $mails_ifneedbe);
$smarty->assign('mails_no', $mails_no);
$smarty->display('display_mails.tpl');
exit;
}
// -------------------------------
// Add a slot
// -------------------------------

View File

@ -82,6 +82,12 @@ class Form
*/
public $results_publicly_visible;
/**
* If true, the users can leave an email address while voting in the poll
* @var boolean
*/
public $collect_users_mail;
/**
* List of available choices
*/

View File

@ -0,0 +1,70 @@
<?php
/**
* This software is governed by the CeCILL-B license. If a copy of this license
* is not distributed with this file, you can obtain one at
* http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt
*
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
*
* =============================
*
* Ce logiciel est régi par la licence CeCILL-B. Si une copie de cette licence
* ne se trouve pas avec ce fichier vous pouvez l'obtenir sur
* http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.txt
*
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
*/
namespace Framadate\Migration;
use Framadate\Utils;
/**
* This migration adds the field uniqId on the vote table.
*
* @package Framadate\Migration
* @version 0.9
*/
class AddColumn_collect_mail_In_poll implements Migration {
function __construct() {
}
/**
* This method should describe in english what is the purpose of the migration class.
*
* @return string The description of the migration class
*/
function description() {
return 'Add column collect_users_mail in table poll';
}
/**
* This method could check if the execute method should be called.
* It is called before the execute method.
*
* @param \PDO $pdo The connection to database
* @return bool true is the Migration should be executed.
*/
function preCondition(\PDO $pdo) {
return true;
}
/**
* This method is called only one time in the migration page.
*
* @param \PDO $pdo The connection to database
* @return bool true is the execution succeeded
*/
function execute(\PDO $pdo) {
$this->alterVoteTable($pdo);
return true;
}
private function alterVoteTable(\PDO $pdo) {
$pdo->exec('
ALTER TABLE `' . Utils::table('poll') . '`
ADD `collect_users_mail` TINYINT DEFAULT 0;');
}
}

View File

@ -0,0 +1,70 @@
<?php
/**
* This software is governed by the CeCILL-B license. If a copy of this license
* is not distributed with this file, you can obtain one at
* http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt
*
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
*
* =============================
*
* Ce logiciel est régi par la licence CeCILL-B. Si une copie de cette licence
* ne se trouve pas avec ce fichier vous pouvez l'obtenir sur
* http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.txt
*
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
*/
namespace Framadate\Migration;
use Framadate\Utils;
/**
* This migration adds the field uniqId on the vote table.
*
* @package Framadate\Migration
* @version 0.9
*/
class AddColumn_mail_In_vote implements Migration {
function __construct() {
}
/**
* This method should describe in english what is the purpose of the migration class.
*
* @return string The description of the migration class
*/
function description() {
return 'Add column mail in table vote';
}
/**
* This method could check if the execute method should be called.
* It is called before the execute method.
*
* @param \PDO $pdo The connection to database
* @return bool true is the Migration should be executed.
*/
function preCondition(\PDO $pdo) {
return true;
}
/**
* This method is called only one time in the migration page.
*
* @param \PDO $pdo The connection to database
* @return bool true is the execution succeeded
*/
function execute(\PDO $pdo) {
$this->alterVoteTable($pdo);
return true;
}
private function alterVoteTable(\PDO $pdo) {
$pdo->exec('
ALTER TABLE `' . Utils::table('vote') . '`
ADD `mail` VARCHAR(320) DEFAULT NULL;');
}
}

View File

@ -12,10 +12,10 @@ class PollRepository extends AbstractRepository {
public function insertPoll($poll_id, $admin_poll_id, $form) {
$sql = 'INSERT INTO `' . Utils::table('poll') . '`
(id, admin_id, title, description, admin_name, admin_mail, end_date, format, editable, receiveNewVotes, receiveNewComments, hidden, password_hash, results_publicly_visible,ValueMax)
VALUES (?,?,?,?,?,?,FROM_UNIXTIME(?),?,?,?,?,?,?,?,?)';
(id, admin_id, title, description, admin_name, admin_mail, end_date, format, editable, receiveNewVotes, receiveNewComments, hidden, password_hash, results_publicly_visible, ValueMax, collect_users_mail)
VALUES (?,?,?,?,?,?,FROM_UNIXTIME(?),?,?,?,?,?,?,?,?,?)';
$prepared = $this->prepare($sql);
$prepared->execute([$poll_id, $admin_poll_id, $form->title, $form->description, $form->admin_name, $form->admin_mail, $form->end_date, $form->format, ($form->editable>=0 && $form->editable<=2) ? $form->editable : 0, $form->receiveNewVotes ? 1 : 0, $form->receiveNewComments ? 1 : 0, $form->hidden ? 1 : 0, $form->password_hash, $form->results_publicly_visible ? 1 : 0,$form->ValueMax]);
$prepared->execute([$poll_id, $admin_poll_id, $form->title, $form->description, $form->admin_name, $form->admin_mail, $form->end_date, $form->format, ($form->editable>=0 && $form->editable<=2) ? $form->editable : 0, $form->receiveNewVotes ? 1 : 0, $form->receiveNewComments ? 1 : 0, $form->hidden ? 1 : 0, $form->password_hash, $form->results_publicly_visible ? 1 : 0, $form->ValueMax, $form->collect_users_mail? 1 : 0]);
}
function findById($poll_id) {

View File

@ -22,9 +22,9 @@ class VoteRepository extends AbstractRepository {
return $prepared->execute([$insert_position, $insert_position + 1, $poll_id]);
}
function insert($poll_id, $name, $choices, $token) {
$prepared = $this->prepare('INSERT INTO `' . Utils::table('vote') . '` (poll_id, name, choices, uniqId) VALUES (?,?,?,?)');
$prepared->execute([$poll_id, $name, $choices, $token]);
function insert($poll_id, $name, $choices, $token, $mail) {
$prepared = $this->prepare('INSERT INTO `' . Utils::table('vote') . '` (poll_id, name, choices, uniqId, mail) VALUES (?,?,?,?,?)');
$prepared->execute([$poll_id, $name, $choices, $token, $mail]);
$newVote = new \stdClass();
$newVote->poll_id = $poll_id;
@ -32,6 +32,7 @@ class VoteRepository extends AbstractRepository {
$newVote->name = $name;
$newVote->choices = $choices;
$newVote->uniqId = $token;
$newVote->mail=$mail;
return $newVote;
}
@ -73,10 +74,10 @@ class VoteRepository extends AbstractRepository {
return $prepared->execute([$index, $index + 2, $poll_id]);
}
function update($poll_id, $vote_id, $name, $choices) {
$prepared = $this->prepare('UPDATE `' . Utils::table('vote') . '` SET choices = ?, name = ? WHERE poll_id = ? AND id = ?');
function update($poll_id, $vote_id, $name, $choices, $mail) {
$prepared = $this->prepare('UPDATE `' . Utils::table('vote') . '` SET choices = ?, name = ?, mail = ? WHERE poll_id = ? AND id = ?');
return $prepared->execute([$choices, $name, $poll_id, $vote_id]);
return $prepared->execute([$choices, $name, $mail, $poll_id, $vote_id]);
}
/**

View File

@ -88,43 +88,45 @@ class PollService {
* @param $name
* @param $choices
* @param $slots_hash
* @param string $mail
* @throws AlreadyExistsException
* @throws ConcurrentEditionException
* @throws ConcurrentVoteException
* @return bool
*/
public function updateVote($poll_id, $vote_id, $name, $choices, $slots_hash) {
public function updateVote($poll_id, $vote_id, $name, $choices, $slots_hash, $mail) {
$this->checkVoteConstraints($choices, $poll_id, $slots_hash, $name, $vote_id);
// Update vote
$choices = implode($choices);
return $this->voteRepository->update($poll_id, $vote_id, $name, $choices);
return $this->voteRepository->update($poll_id, $vote_id, $name, $choices, $mail);
}
/**
* @param $poll_id
* @param $name
* @param $choices
* @param $slots_hash
* @param string $mail
* @throws AlreadyExistsException
* @throws ConcurrentEditionException
* @throws ConcurrentVoteException
* @return \stdClass
*/
function addVote($poll_id, $name, $choices, $slots_hash) {
function addVote($poll_id, $name, $choices, $slots_hash, $mail) {
$this->checkVoteConstraints($choices, $poll_id, $slots_hash, $name);
// Insert new vote
$choices = implode($choices);
$token = $this->random(16);
return $this->voteRepository->insert($poll_id, $name, $choices, $token);
return $this->voteRepository->insert($poll_id, $name, $choices, $token, $mail);
}
function addComment($poll_id, $name, $comment) {
if ($this->commentRepository->exists($poll_id, $name, $comment)) {
return true;
}
return $this->commentRepository->insert($poll_id, $name, $comment);
}
@ -224,6 +226,7 @@ class PollService {
$obj->name = $vote->name;
$obj->uniqId = $vote->uniqId;
$obj->choices = str_split($vote->choices);
$obj->mail = $vote->mail;
$splitted[] = $obj;
}
@ -292,7 +295,7 @@ class PollService {
private function random($length) {
return Token::getToken($length);
}
/**
* @param $choices
* @param $poll_id
@ -310,20 +313,20 @@ class PollService {
} else {
$exists = $this->voteRepository->existsByPollIdAndNameAndVoteId($poll_id, $name, $vote_id);
}
if ($exists) {
throw new AlreadyExistsException();
}
$poll = $this->findById($poll_id);
// Check that no-one voted in the meantime and it conflicts the maximum votes constraint
$this->checkMaxVotes($choices, $poll, $poll_id);
// Check if slots are still the same
$this->checkThatSlotsDidntChanged($poll, $slots_hash);
}
/**
* This method checks if the hash send by the user is the same as the computed hash.
*

View File

@ -57,6 +57,8 @@ if ($goToStep2) {
$use_ValueMax = isset($_POST['use_ValueMax']) ? $inputService->filterBoolean($_POST['use_ValueMax']) : false;
$ValueMax = $use_ValueMax === true ? $inputService->filterValueMax($_POST['ValueMax']) : null;
$collect_users_mail = isset($_POST['collect_users_mail']) ? $inputService->filterBoolean($_POST['collect_users_mail']) : false;
$use_customized_url = isset($_POST['use_customized_url']) ? $inputService->filterBoolean($_POST['use_customized_url']) : false;
$customized_url = $use_customized_url === true ? $inputService->filterId($_POST['customized_url']) : null;
$name = $inputService->filterName($_POST['name']);
@ -67,6 +69,8 @@ if ($goToStep2) {
$receiveNewComments = isset($_POST['receiveNewComments']) ? $inputService->filterBoolean($_POST['receiveNewComments']) : false;
$hidden = isset($_POST['hidden']) ? $inputService->filterBoolean($_POST['hidden']) : false;
$use_password = filter_input(INPUT_POST, 'use_password', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_REGEX]]);
$collect_users_mail = isset($_POST['collect_users_mail']) ? $inputService->filterBoolean($_POST['collect_users_mail']) : false;
$use_password = filter_input(INPUT_POST, 'use_password', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_REGEX]]);
$password = isset($_POST['password']) ? $_POST['password'] : null;
$password_repeat = isset($_POST['password_repeat']) ? $_POST['password_repeat'] : null;
$results_publicly_visible = filter_input(INPUT_POST, 'results_publicly_visible', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_REGEX]]);
@ -93,6 +97,7 @@ if ($goToStep2) {
$_SESSION['form']->receiveNewVotes = $receiveNewVotes;
$_SESSION['form']->receiveNewComments = $receiveNewComments;
$_SESSION['form']->hidden = $hidden;
$_SESSION['form']->collect_users_mail = $collect_users_mail;
$_SESSION['form']->use_password = ($use_password !== null);
$_SESSION['form']->results_publicly_visible = ($results_publicly_visible !== null);
@ -289,6 +294,7 @@ $smarty->assign('customized_url', Utils::fromPostOrDefault('customized_url', $_S
$smarty->assign('use_customized_url', Utils::fromPostOrDefault('use_customized_url', $_SESSION['form']->use_customized_url));
$smarty->assign('ValueMax', Utils::fromPostOrDefault('ValueMax', $_SESSION['form']->ValueMax));
$smarty->assign('use_ValueMax', Utils::fromPostOrDefault('use_ValueMax', $_SESSION['form']->use_ValueMax));
$smarty->assign('collect_users_mail', Utils::fromPostOrDefault('collect_users_mail', $_SESSION['form']->collect_users_mail));
$smarty->assign('poll_description', !empty($_POST['description']) ? $_POST['description'] : $_SESSION['form']->description);
$smarty->assign('poll_name', Utils::fromPostOrDefault('name', $_SESSION['form']->admin_name));
$smarty->assign('poll_mail', Utils::fromPostOrDefault('mail', $_SESSION['form']->admin_mail));

View File

@ -449,19 +449,10 @@ span.edit-username-left {
border-color: #949494 !important;
}
table.results .bg-danger .glyphicon {
/* TODO : Refactor me ! */
table.results .bg-danger .glyphicon:not(.glyphicon-alert) {
opacity:0;
-moz-animation-name: hideNoIcon;
-moz-animation-iteration-count: 1;
-moz-animation-timing-function: ease-in;
-moz-animation-duration: 2s;
-webkit-animation-name: hideNoIcon;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease-in;
-webkit-animation-duration: 2s;
animation-name: hideNoIcon;
animation-iteration-count: 1;
animation-timing-function: ease-in;

View File

@ -67,6 +67,25 @@ $(document).ready(function () {
}
});
/**
* Hide/Show Warning collect_users_mail + editable by all
*/
$("#collect_users_mail").change(function(){
if ($(this).prop("checked") && $("input[name='editable']:checked").val() == 1) {
$("#collect_warning").removeClass("hidden");
} else {
$("#collect_warning").addClass("hidden");
}
});
$("input[name='editable']").change(function(){
if ($("#collect_users_mail").prop("checked") && $("input[name='editable']:checked").val() == 1) {
$("#collect_warning").removeClass("hidden");
} else {
$("#collect_warning").addClass("hidden");
}
});
// Check cookies are enabled too
var cookieEnabled = function () {
var cookieEnabled = navigator.cookieEnabled;

View File

@ -302,7 +302,8 @@
"Vote yes for": "Vote \"yes\" for",
"Votes of the poll": "Votes",
"polled user": "polled user",
"polled users": "polled users"
"polled users": "polled users",
"Anyone will be able to access your email address after your vote" : "Anyone will be able to access your email address after your vote"
},
"PollInfo": {
"Admin link of the poll": "Admin link for the poll",
@ -344,7 +345,8 @@
"Simple editor": "Simple editor",
"Title": "Title of the poll",
"Votes and comments are locked": "Votes and comments are locked",
"Votes protected by password": "Votes protected by password"
"Votes protected by password": "Votes protected by password",
"Collecting the polled users emails" : "Collecting the polled users emails"
},
"Step 1": {
"All voters can modify any vote": "All voters can modify any vote",
@ -374,7 +376,10 @@
"Voters can modify their vote themselves": "Voters can modify their vote themselves",
"Votes cannot be modified": "Votes cannot be modified",
"You are in the poll creation section.": "You are in the poll creation section.",
"You can enable or disable the editor at will.": "You can enable or disable the editor at will."
"You can enable or disable the editor at will.": "You can enable or disable the editor at will.",
"Collect users email" : "Collect users email",
"Collect the polled users email addresses" : "Collect the polled users email addresses",
"Warning: anyone can access the polled users email addresses since all voters can modify any vote. You should restrict permission rules." : "Warning: anyone can access the polled users email addresses since all voters can modify any vote. You should restrict permission rules."
},
"Step 2": {
"Back to step 1": "Return to step 1",
@ -424,6 +429,7 @@
},
"adminstuds": {
"Add a column": "Add a column",
"Collect the emails of the polled users for the choice": "Collect the emails of the polled users for the choice",
"All comments deleted": "All comments deleted",
"All votes deleted": "All votes deleted",
"As poll administrator, you can change all the lines of this poll with this button": "As poll administrator, you can change all the lines of this poll with this button",
@ -467,5 +473,13 @@
"The poll is expired, it will be deleted soon.": "The poll has expired, it will soon be deleted.",
"Update vote succeeded": "Vote updated",
"Your vote has been registered successfully, but be careful: regarding this poll options, you need to keep this personal link to edit your own vote:": "Your vote has been saved, but please note: you need to keep this personalised link to be able to edit your vote."
},
"display_mails": {
"No one voted 'Yes' to this option." : "No one voted 'Yes' to this option.",
"No one voted 'If need be' to this option." : "No one voted 'If need be' to this option.",
"No one voted 'No' to this option." : "No one voted 'No' to this option.",
"People who have answered 'Yes' to this option have left these email addresses:" : "People who have answered 'Yes' to this option have left these email addresses:",
"People who have answered 'If need be' to this option have left these email addresses:" : "People who have answered 'If need be' to this option have left these email addresses:",
"People who have answered 'No' to this option have left these email addresses:" : "People who have answered 'No' to this option have left these email addresses:"
}
}

View File

@ -120,6 +120,11 @@ if ($accessGranted) {
if (!empty($_POST['save'])) { // Save edition of an old vote
$name = $inputService->filterName($_POST['name']);
if(empty($_POST['mail']) || $inputService->filterMail($_POST['mail']) === false) {
$mail = null;
} else {
$mail = $inputService->filterMail($_POST['mail']);
}
$editedVote = filter_input(INPUT_POST, 'save', FILTER_VALIDATE_INT);
$choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]);
$slots_hash = $inputService->filterMD5($_POST['control']);
@ -134,7 +139,7 @@ if ($accessGranted) {
if ($message === null) {
// Update vote
try {
$result = $pollService->updateVote($poll_id, $editedVote, $name, $choices, $slots_hash);
$result = $pollService->updateVote($poll_id, $editedVote, $name, $choices, $slots_hash, $mail);
if ($result) {
if ($poll->editable === Editable::EDITABLE_BY_OWN) {
$editedVoteUniqueId = filter_input(INPUT_POST, 'edited_vote', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
@ -156,6 +161,11 @@ if ($accessGranted) {
}
} elseif (isset($_POST['save'])) { // Add a new vote
$name = $inputService->filterName($_POST['name']);
if(empty($_POST['mail']) || $inputService->filterMail($_POST['mail']) === false) {
$mail = null;
} else {
$mail = $inputService->filterMail($_POST['mail']);
}
$choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]);
$slots_hash = $inputService->filterMD5($_POST['control']);
@ -169,7 +179,7 @@ if ($accessGranted) {
if ($message === null) {
// Add vote
try {
$result = $pollService->addVote($poll_id, $name, $choices, $slots_hash);
$result = $pollService->addVote($poll_id, $name, $choices, $slots_hash, $mail);
if ($result) {
if (intval($poll->editable) === Editable::EDITABLE_BY_OWN) {
$editedVoteUniqueId = $result->uniqId;

View File

@ -325,9 +325,30 @@
</div>
</div>
</div>
{* Collect users email *}
<div class="form-group">
<label for="collect_mail" class="col-sm-4 control-label">
{__('Step 1', 'Collect users email')}
</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
<input type="checkbox" name="collect_users_mail"
id="collect_users_mail">
{__('Step 1', "Collect the polled users email addresses")}
</label>
</div>
</div>
<div id="collect_warning" class="hidden">
<div class="col-sm-offset-4 col-sm-8">
<label class="bg-danger"><i class="glyphicon glyphicon-alert"> </i> {__('Step 1', 'Warning: anyone can access the polled users email addresses since all voters can modify any vote. You should restrict permission rules.')} </label>
</div>
</div>
</div>
</div>
<p class="text-right">
<button name="{$goToStep2}" value="{$poll_type}" type="submit"
class="btn btn-success">{__('Step 1', 'Go to step 2')}</button>

45
tpl/display_mails.tpl Normal file
View File

@ -0,0 +1,45 @@
{extends file='page.tpl'}
{block name=main}
<main>
{if ($mails_yes|count) === 0}
{__('display_mails', "No one voted 'Yes' to this option.")}</br>
{else}
{__('display_mails', "People who have answered 'Yes' to this option have left these email addresses:")}</br>
{strip}
<pre>
{foreach $mails_yes as $mail}
{$mail|html}<br />
{/foreach}
</pre>
{/strip}
{/if}
<br />
{if ($mails_ifneedbe|count) === 0}
{__('display_mails', "No one voted 'If need be' to this option.")}</br>
{else}
{__('display_mails', "People who have answered 'If need be' to this option have left these email addresses:")}</br>
{strip}
<pre>
{foreach $mails_ifneedbe as $mail}
{$mail|html}<br />
{/foreach}
</pre>
{/strip}
{/if}
<br />
{if ($mails_no|count) === 0}
{__('display_mails', "No one voted 'No' to this option.")}</br>
{else}
{__('display_mails', "People who have answered 'No' to this option have left these email addresses:")}</br>
{strip}
<pre>
{foreach $mails_no as $mail}
{$mail|html}<br />
{/foreach}
</pre>
{/strip}
{/if}
<br />
<a href="{poll_url id=$admin_poll_id admin=true}" class="btn btn-default" name="back">{__('adminstuds', 'Back to the poll')}</a>
{/block}

View File

@ -232,6 +232,11 @@
</div>
</div>
</div>
<div id="collect_users_mail">
{if $poll->collect_users_mail}
<p><span class="glyphicon glyphicon-envelope"> </span> {__('PollInfo', 'Collecting the polled users emails')}</p>
{/if}
</div>
{/if}
</div>
{if $admin}</form>{/if}

View File

@ -16,12 +16,13 @@
<div id="tableContainer" class="tableContainer">
<form action="{if $admin}{poll_url id=$admin_poll_id admin=true}{else}{poll_url id=$poll_id}{/if}" method="POST" id="poll_form">
<input type="hidden" name="control" value="{$slots_hash}"/>
<table class="results">
<table class="results">
<caption class="sr-only">{__('Poll results', 'Votes of the poll')} {$poll->title|html}</caption>
<thead>
{if $admin && !$expired}
<tr class="hidden-print">
<th role="presentation"></th>
{$headersDCount=0}
{foreach $slots as $id=>$slot}
<td headers="C{$id}">
<a href="{poll_url id=$admin_poll_id admin=true action='delete_column' action_value=$slot->title}"
@ -29,7 +30,15 @@
class="btn btn-link btn-sm remove-column" title="{__('adminstuds', 'Remove the column')} {$slot->title|html}">
<i class="glyphicon glyphicon-remove text-danger"></i><span class="sr-only">{__('Generic', 'Remove')}</span>
</a>
{if $poll->collect_users_mail}
<a href="{poll_url id=$admin_poll_id admin=true action='collect_mail' action_value=($headersDCount)}"
class="btn btn-link btn-sm collect-mail"
title="{__('adminstuds', 'Collect the emails of the polled users for the choice')} {$slot->title|html}">
<i class="glyphicon glyphicon-envelope"></i><span class="sr-only">{__('Generic', 'Collect emails')}</span>
</a>
{/if}
</td>
{$headersDCount = $headersDCount+1}
{/foreach}
<td>
<a href="{poll_url id=$admin_poll_id admin=true action='add_column'}"
@ -59,6 +68,9 @@
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input type="hidden" name="edited_vote" value="{$vote->uniqId}"/>
<input type="text" id="name" name="name" value="{$vote->name|html}" class="form-control" title="{__('Generic', 'Your name')}" placeholder="{__('Generic', 'Your name')}" />
{if $poll->collect_users_mail}
<input type="email" required id="mail" name="mail" value="{$vote->mail|html}" class="form-control" title="{__('Generic', 'Your email address')}" placeholder="{__('Generic', 'Your email address')}" />
{/if}
</div>
</td>
@ -172,7 +184,16 @@
<div class="input-group input-group-sm">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input type="text" id="name" name="name" class="form-control" title="{__('Generic', 'Your name')}" placeholder="{__('Generic', 'Your name')}" />
{if $poll->collect_users_mail}
<input type="email" required id="mail" name="mail" class="form-control" title="{__('Generic', 'Your email address')}" placeholder="{__('Generic', 'Your email address')}" />
{/if}
</div>
{if $poll->collect_users_mail && $poll->editable == constant('Framadate\Editable::EDITABLE_BY_ALL')}
<div class="bg-danger">
<i class="glyphicon glyphicon-alert"> </i>
<label> {__('Poll results', 'Anyone will be able to access your email address after your vote')} </label>
</div>
{/if}
</td>
{$i = 0}
{foreach $slots as $id=>$slot}
@ -205,7 +226,7 @@
</label>
</li>
<li class="hide">
<input type="radio" id="n-choice-{$id}" name="choices[{$id}]" value=" "
<input type="radio" id="n-choice-{$id}" name="choices[{$id}]" value=" "
{(isset($selectedNewVotes[$id]) && ("" !== $selectedNewVotes[$id])) ? "" : " checked"}
/>
</li>

View File

@ -32,6 +32,13 @@
title="{__('adminstuds', 'Remove the column')} {$slot->day|date_format:$date_format.txt_short|html} - {$moment|html}">
<i class="glyphicon glyphicon-remove text-danger"></i><span class="sr-only">{__('Generic', 'Remove')}</span>
</a>
{if $poll->collect_users_mail}
<a href="{poll_url id=$admin_poll_id admin=true action='collect_mail' action_value=($headersDCount)}"
class="btn btn-link btn-sm collect-mail"
title="{__('adminstuds', 'Collect the emails of the polled users for the choice')} {$slot->day|date_format:$date_format.txt_short|html} - {$moment|html}">
<i class="glyphicon glyphicon-envelope"></i><span class="sr-only">{__('Generic', 'Collect emails')}</span>
</a>
{/if}
</td>
{$headersDCount = $headersDCount+1}
{/foreach}
@ -105,7 +112,9 @@
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input type="hidden" name="edited_vote" value="{$vote->uniqId}"/>
<input type="text" id="name" name="name" value="{$vote->name|html}" class="form-control" title="{__('Generic', 'Your name')}" placeholder="{__('Generic', 'Your name')}" />
{if $poll->collect_users_mail}
<input type="email" required id="mail" name="mail" value="{$vote->mail|html}" class="form-control" title="{__('Generic', 'Your email address')}" placeholder="{__('Generic', 'Your email address')}" />
{/if}
</div>
</td>
@ -230,7 +239,16 @@
<div class="input-group input-group-sm">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input type="text" id="name" name="name" class="form-control" title="{__('Generic', 'Your name')}" placeholder="{__('Generic', 'Your name')}" />
{if $poll->collect_users_mail}
<input type="email" required id="mail" name="mail" class="form-control" title="{__('Generic', 'Your email address')}" placeholder="{__('Generic', 'Your email address')}" />
{/if}
</div>
{if $poll->collect_users_mail && $poll->editable == constant('Framadate\Editable::EDITABLE_BY_ALL')}
<div class="bg-danger">
<i class="glyphicon glyphicon-alert"> </i>
<label> {__('Poll results', 'Anyone will be able to access your email address after your vote')} </label>
</div>
{/if}
</td>