From 64ff414900bff2214c707cc38a1c9bfa2be7b0ec Mon Sep 17 00:00:00 2001 From: Erwan TERTRAIS Date: Tue, 20 Feb 2018 13:06:58 +0100 Subject: [PATCH 1/5] ValueMax : limit the number of voters per option Signed-off-by: Thomas Citharel --- admin/migration.php | 13 ++-- app/classes/Framadate/Form.php | 7 ++ .../AddColumn_ValueMax_In_poll_For_1_1.php | 73 +++++++++++++++++++ .../Framadate/Repositories/PollRepository.php | 6 +- .../Framadate/Services/InputService.php | 8 ++ .../Framadate/Services/PollService.php | 4 +- app/inc/constants.php | 1 + create_date_poll.php | 1 + create_poll.php | 32 +++++++- js/app/create_poll.js | 12 +++ locale/en.json | 5 +- locale/fr.json | 5 +- php.ini | 4 + studs.php | 4 + tpl/create_poll.tpl | 35 +++++++++ tpl/part/vote_table_classic.tpl | 29 +++++--- tpl/part/vote_table_date.tpl | 14 +++- 17 files changed, 227 insertions(+), 26 deletions(-) create mode 100644 app/classes/Framadate/Migration/AddColumn_ValueMax_In_poll_For_1_1.php diff --git a/admin/migration.php b/admin/migration.php index 93cb189..b2de049 100644 --- a/admin/migration.php +++ b/admin/migration.php @@ -17,14 +17,15 @@ * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) */ -use Framadate\Migration\AddColumn_hidden_In_poll_For_0_9; -use Framadate\Migration\AddColumn_receiveNewComments_For_0_9; -use Framadate\Migration\AddColumn_uniqId_In_vote_For_0_9; use Framadate\Migration\AddColumns_password_hash_And_results_publicly_visible_In_poll_For_0_9; -use Framadate\Migration\Alter_Comment_table_adding_date; -use Framadate\Migration\Alter_Comment_table_for_name_length; use Framadate\Migration\From_0_0_to_0_8_Migration; use Framadate\Migration\From_0_8_to_0_9_Migration; +use Framadate\Migration\AddColumn_receiveNewComments_For_0_9; +use Framadate\Migration\AddColumn_uniqId_In_vote_For_0_9; +use Framadate\Migration\AddColumn_hidden_In_poll_For_0_9; +use Framadate\Migration\Alter_Comment_table_for_name_length; +use Framadate\Migration\Alter_Comment_table_adding_date; +use Framadate\Migration\AddColumn_ValueMax_In_poll_For_1_1; use Framadate\Migration\Generate_uniqId_for_old_votes; use Framadate\Migration\Increase_pollId_size; use Framadate\Migration\Migration; @@ -42,12 +43,14 @@ $migrations = [ new AddColumn_receiveNewComments_For_0_9(), new AddColumn_uniqId_In_vote_For_0_9(), new AddColumn_hidden_In_poll_For_0_9(), + new AddColumn_ValueMax_In_poll_For_1_1(), new Generate_uniqId_for_old_votes(), new RPadVotes_from_0_8(), new Alter_Comment_table_for_name_length(), new Alter_Comment_table_adding_date(), new AddColumns_password_hash_And_results_publicly_visible_In_poll_For_0_9(), new Increase_pollId_size() + ]; // --------------------------------------- diff --git a/app/classes/Framadate/Form.php b/app/classes/Framadate/Form.php index f1ad031..716400d 100644 --- a/app/classes/Framadate/Form.php +++ b/app/classes/Framadate/Form.php @@ -28,6 +28,7 @@ class Form public $format; public $end_date; public $choix_sondage; + public $ValueMax; /** * Tells if users can modify their choices. @@ -49,6 +50,12 @@ class Form * If true, only the poll maker can see the poll's results * @var boolean */ + public $use_ValueMax; + + /** + * if true, there will be a limit of voters per option + * @var boolean + */ public $hidden; /** diff --git a/app/classes/Framadate/Migration/AddColumn_ValueMax_In_poll_For_1_1.php b/app/classes/Framadate/Migration/AddColumn_ValueMax_In_poll_For_1_1.php new file mode 100644 index 0000000..dbf129c --- /dev/null +++ b/app/classes/Framadate/Migration/AddColumn_ValueMax_In_poll_For_1_1.php @@ -0,0 +1,73 @@ +alterPollTable($pdo); + + return true; + } + + private function alterPollTable(\PDO $pdo) { + $pdo->exec(' + ALTER TABLE `' . Utils::table('poll') . '` + ADD `ValueMax` TINYINT, + ADD CHECK (ValueMax > 0)'); + } + +} diff --git a/app/classes/Framadate/Repositories/PollRepository.php b/app/classes/Framadate/Repositories/PollRepository.php index 4f5e62e..9427813 100644 --- a/app/classes/Framadate/Repositories/PollRepository.php +++ b/app/classes/Framadate/Repositories/PollRepository.php @@ -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) - 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) + 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]); + $prepared->execute(array($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)); } function findById($poll_id) { diff --git a/app/classes/Framadate/Services/InputService.php b/app/classes/Framadate/Services/InputService.php index 23f6e00..ffb2266 100644 --- a/app/classes/Framadate/Services/InputService.php +++ b/app/classes/Framadate/Services/InputService.php @@ -76,6 +76,14 @@ class InputService { public function filterMD5($control) { return filter_var($control, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => MD5_REGEX]]); } + + public function filterInteger($int) { + if (filter_var($int, FILTER_VALIDATE_INT)) { + return $int; + } else { + return null; + } + } public function filterBoolean($boolean) { return !!filter_var($boolean, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_TRUE_REGEX]]); diff --git a/app/classes/Framadate/Services/PollService.php b/app/classes/Framadate/Services/PollService.php index 43efd42..f2466d0 100644 --- a/app/classes/Framadate/Services/PollService.php +++ b/app/classes/Framadate/Services/PollService.php @@ -26,6 +26,8 @@ use Framadate\Repositories\RepositoryFactory; use Framadate\Security\Token; use Framadate\Utils; + + class PollService { private $connect; private $logService; @@ -151,7 +153,7 @@ class PollService { return $this->pollRepository->findAllByAdminMail($mail); } - function computeBestChoices($votes) { + function computeBestChoices($votes) { $result = ['y' => [0], 'inb' => [0]]; foreach ($votes as $vote) { $choices = str_split($vote->choices); diff --git a/app/inc/constants.php b/app/inc/constants.php index d36106a..b631b9e 100644 --- a/app/inc/constants.php +++ b/app/inc/constants.php @@ -17,6 +17,7 @@ * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) */ + // FRAMADATE version const VERSION = '1.0'; diff --git a/create_date_poll.php b/create_date_poll.php index 05261b0..89f805b 100644 --- a/create_date_poll.php +++ b/create_date_poll.php @@ -48,6 +48,7 @@ if ($_SESSION['form']->format !== 'D') { $_SESSION['form']->clearChoices(); } + if (!isset($_SESSION['form']->title) || !isset($_SESSION['form']->admin_name) || ($config['use_smtp'] && !isset($_SESSION['form']->admin_mail))) { $step = 1; } else if (!empty($_POST['confirmation'])) { diff --git a/create_poll.php b/create_poll.php index a55fdbf..015b63e 100644 --- a/create_poll.php +++ b/create_poll.php @@ -55,6 +55,10 @@ if (isset($_GET['type']) && $_GET['type'] === 'date' || $goToStep2 = filter_input(INPUT_POST, GO_TO_STEP_2, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^(date|classic)$/']]); if ($goToStep2) { $title = $inputService->filterTitle($_POST['title']); + + $use_ValueMax = isset($_POST['use_ValueMax']) ? $inputService->filterBoolean($_POST['use_ValueMax']) : false; + $ValueMax = $use_ValueMax == true ? $inputService->filterInteger($_POST['ValueMax']) : null; + $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']); @@ -77,10 +81,14 @@ if ($goToStep2) { $error_on_password = false; $error_on_password_repeat = false; $error_on_customized_url = false; + $error_on_ValueMax = false; + $_SESSION['form']->title = $title; $_SESSION['form']->id = $customized_url; $_SESSION['form']->use_customized_url = $use_customized_url; + $_SESSION['form']->use_ValueMax = $use_ValueMax; + $_SESSION['form']->ValueMax = $ValueMax; $_SESSION['form']->admin_name = $name; $_SESSION['form']->admin_mail = $mail; $_SESSION['form']->description = $description; @@ -110,6 +118,14 @@ if ($goToStep2) { } } + if ($use_ValueMax) { + if ($use_ValueMax === false) { + $error_on_ValueMax = true; + $error_on_customized_url_msg = __('Error', 'Mauvaise valeur'); + } + } + + if ($name !== $_POST['name']) { $error_on_name = true; } @@ -134,7 +150,7 @@ if ($goToStep2) { } if ($title && $name && $email_OK && !$error_on_title && !$error_on_customized_url && !$error_on_description && !$error_on_name - && !$error_on_password && !$error_on_password_repeat + && !$error_on_password && !$error_on_password_repeat &&!$error_on_ValueMax ) { // If no errors, we hash the password if needed if ($_SESSION['form']->use_password) { @@ -193,12 +209,17 @@ $errors = [ 'msg' => '', 'aria' => '', 'class' => '' + ], + 'ValueMax' => [ + 'msg' => '', + 'aria' => '', + 'class' => '' ], 'password_repeat' => [ 'msg' => '', 'aria' => '', 'class' => '' - ] + ], ]; if (!empty($_POST[GO_TO_STEP_2])) { @@ -254,6 +275,11 @@ if (!empty($_POST[GO_TO_STEP_2])) { $errors['password_repeat']['class'] = ' has-error'; $errors['password_repeat']['msg'] = __('Error', 'Passwords do not match'); } + if ($error_on_ValueMax) { + $errors['ValueMax']['aria'] = 'aria-describeby="poll_ValueMax" '; + $errors['ValueMax']['class'] = ' has-error'; + $errors['ValueMax']['msg'] = __('Error', 'error on ValueMax'); + } } $useRemoteUser = USE_REMOTE_USER && isset($_SERVER['REMOTE_USER']); @@ -268,6 +294,8 @@ $smarty->assign('poll_type', $poll_type); $smarty->assign('poll_title', Utils::fromPostOrDefault('title', $_SESSION['form']->title)); $smarty->assign('customized_url', Utils::fromPostOrDefault('customized_url', $_SESSION['form']->id)); $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('poll_description', Utils::fromPostOrDefault('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)); diff --git a/js/app/create_poll.js b/js/app/create_poll.js index f98370a..26fc42c 100644 --- a/js/app/create_poll.js +++ b/js/app/create_poll.js @@ -44,6 +44,18 @@ $(document).ready(function () { } }); + /** + * Enable/Disable ValueMax options + */ + $("#use_ValueMax").change(function () { + if ($(this).prop("checked")) { + $("#ValueMax").removeClass("hidden"); + } else { + $("#ValueMax").addClass("hidden"); + } + }); + + /** * Hide/Show password options */ diff --git a/locale/en.json b/locale/en.json index cf005a9..c412a76 100644 --- a/locale/en.json +++ b/locale/en.json @@ -247,7 +247,10 @@ "Password confirmation": "Confirmation", "Permissions": "Permissions", "Optional parameters": "Optional parameters", - "Go to step 2": "Go to step 2" + "Go to step 2": "Go to step 2", + "Limit the ammount of voters per option": "Limit the ammount of voters per option", + "ValueMax instructions": "voters per options ", + "Value Max" : "Value Max" }, "Step 2": { "Back to step 1": "Return to step 1", diff --git a/locale/fr.json b/locale/fr.json index d6288a4..6486504 100644 --- a/locale/fr.json +++ b/locale/fr.json @@ -247,7 +247,10 @@ "Password confirmation": "Confirmation", "Permissions": "Permissions", "Optional parameters": "Paramètres facultatifs", - "Go to step 2": "Aller à l'étape 2" + "Go to step 2": "Aller à l'étape 2", + "Limit the ammount of voters per option":"limiter le nombre de votants par option", + "Value Max": "Valeur Maximale", + "ValueMax instructions": "Votants maximum par option" }, "Step 2": { "Back to step 1": "Revenir à l’étape 1", diff --git a/php.ini b/php.ini index 347e2e3..bde5cfc 100644 --- a/php.ini +++ b/php.ini @@ -4,3 +4,7 @@ log_errors = On error_log = /var/log/apache2/error.log ignore_repeated_errors = On register_globals = Off + + +[Date] +date.timezone = "Europe/Paris" diff --git a/studs.php b/studs.php index adb1eb1..1b71197 100644 --- a/studs.php +++ b/studs.php @@ -30,6 +30,9 @@ use Framadate\Services\SecurityService; use Framadate\Services\SessionService; use Framadate\Utils; + + + include_once __DIR__ . '/app/inc/init.php'; /* Constantes */ @@ -231,5 +234,6 @@ $smarty->assign('hidden', $poll->hidden); $smarty->assign('accessGranted', $accessGranted); $smarty->assign('resultPubliclyVisible', $resultPubliclyVisible); $smarty->assign('editedVoteUniqueId', $editedVoteUniqueId); +$smarty->assign('ValueMax', $poll->ValueMax); $smarty->display('studs.tpl'); diff --git a/tpl/create_poll.tpl b/tpl/create_poll.tpl index d71e4f9..7167d22 100644 --- a/tpl/create_poll.tpl +++ b/tpl/create_poll.tpl @@ -116,6 +116,41 @@
+ + {* Value MAX *} + + + +
+ +
+
+ +
+
+
+ +
+ +
+ + + {* Poll identifier *}
diff --git a/tpl/part/vote_table_classic.tpl b/tpl/part/vote_table_classic.tpl index 0ccdcae..6ebed25 100644 --- a/tpl/part/vote_table_classic.tpl +++ b/tpl/part/vote_table_classic.tpl @@ -160,21 +160,24 @@
+ {$i = 0} {foreach $slots as $id=>$slot}
    -
  • - - -
  • -
  • - - -
  • + {if $best_choices['y'][$i] lt $poll->ValueMax || $poll->ValueMax eq NULL} +
  • + + +
  • +
  • + + +
  • + {/if}
+ {$i = $i+1} + {/foreach} diff --git a/tpl/part/vote_table_date.tpl b/tpl/part/vote_table_date.tpl index 6384b87..2494be2 100644 --- a/tpl/part/vote_table_date.tpl +++ b/tpl/part/vote_table_date.tpl @@ -219,11 +219,17 @@
+ + {$i = 0} - {foreach $slots as $slot} + {foreach $slots as $slot} {foreach $slot->moments as $moment} + + + + + + {$i = $i+1} {/foreach} {/foreach} From 2d39a83a7fd0ecabaaf63c48c59dd504e4f0a29b Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Tue, 20 Feb 2018 13:12:46 +0100 Subject: [PATCH 2/5] rebase and run php-cs-fixer Signed-off-by: Thomas Citharel --- admin/migration.php | 13 ++++++------- .../AddColumn_ValueMax_In_poll_For_1_1.php | 2 -- .../Framadate/Repositories/PollRepository.php | 2 +- app/classes/Framadate/Services/InputService.php | 3 +-- app/classes/Framadate/Services/PollService.php | 4 +--- app/inc/constants.php | 1 - create_date_poll.php | 1 - create_poll.php | 4 +--- studs.php | 3 --- 9 files changed, 10 insertions(+), 23 deletions(-) diff --git a/admin/migration.php b/admin/migration.php index b2de049..166f790 100644 --- a/admin/migration.php +++ b/admin/migration.php @@ -17,15 +17,15 @@ * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) */ -use Framadate\Migration\AddColumns_password_hash_And_results_publicly_visible_In_poll_For_0_9; -use Framadate\Migration\From_0_0_to_0_8_Migration; -use Framadate\Migration\From_0_8_to_0_9_Migration; +use Framadate\Migration\AddColumn_hidden_In_poll_For_0_9; use Framadate\Migration\AddColumn_receiveNewComments_For_0_9; use Framadate\Migration\AddColumn_uniqId_In_vote_For_0_9; -use Framadate\Migration\AddColumn_hidden_In_poll_For_0_9; -use Framadate\Migration\Alter_Comment_table_for_name_length; -use Framadate\Migration\Alter_Comment_table_adding_date; use Framadate\Migration\AddColumn_ValueMax_In_poll_For_1_1; +use Framadate\Migration\AddColumns_password_hash_And_results_publicly_visible_In_poll_For_0_9; +use Framadate\Migration\Alter_Comment_table_adding_date; +use Framadate\Migration\Alter_Comment_table_for_name_length; +use Framadate\Migration\From_0_0_to_0_8_Migration; +use Framadate\Migration\From_0_8_to_0_9_Migration; use Framadate\Migration\Generate_uniqId_for_old_votes; use Framadate\Migration\Increase_pollId_size; use Framadate\Migration\Migration; @@ -50,7 +50,6 @@ $migrations = [ new Alter_Comment_table_adding_date(), new AddColumns_password_hash_And_results_publicly_visible_In_poll_For_0_9(), new Increase_pollId_size() - ]; // --------------------------------------- diff --git a/app/classes/Framadate/Migration/AddColumn_ValueMax_In_poll_For_1_1.php b/app/classes/Framadate/Migration/AddColumn_ValueMax_In_poll_For_1_1.php index dbf129c..6715f9b 100644 --- a/app/classes/Framadate/Migration/AddColumn_ValueMax_In_poll_For_1_1.php +++ b/app/classes/Framadate/Migration/AddColumn_ValueMax_In_poll_For_1_1.php @@ -27,7 +27,6 @@ use Framadate\Utils; * @version 0.9 */ class AddColumn_ValueMax_In_poll_For_1_1 implements Migration { - function __construct() { } @@ -69,5 +68,4 @@ class AddColumn_ValueMax_In_poll_For_1_1 implements Migration { ADD `ValueMax` TINYINT, ADD CHECK (ValueMax > 0)'); } - } diff --git a/app/classes/Framadate/Repositories/PollRepository.php b/app/classes/Framadate/Repositories/PollRepository.php index 9427813..0b8167b 100644 --- a/app/classes/Framadate/Repositories/PollRepository.php +++ b/app/classes/Framadate/Repositories/PollRepository.php @@ -15,7 +15,7 @@ class PollRepository extends AbstractRepository { (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(?),?,?,?,?,?,?,?,?)'; $prepared = $this->prepare($sql); - $prepared->execute(array($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]); } function findById($poll_id) { diff --git a/app/classes/Framadate/Services/InputService.php b/app/classes/Framadate/Services/InputService.php index ffb2266..0a06a68 100644 --- a/app/classes/Framadate/Services/InputService.php +++ b/app/classes/Framadate/Services/InputService.php @@ -80,9 +80,8 @@ class InputService { public function filterInteger($int) { if (filter_var($int, FILTER_VALIDATE_INT)) { return $int; - } else { + } return null; - } } public function filterBoolean($boolean) { diff --git a/app/classes/Framadate/Services/PollService.php b/app/classes/Framadate/Services/PollService.php index f2466d0..43efd42 100644 --- a/app/classes/Framadate/Services/PollService.php +++ b/app/classes/Framadate/Services/PollService.php @@ -26,8 +26,6 @@ use Framadate\Repositories\RepositoryFactory; use Framadate\Security\Token; use Framadate\Utils; - - class PollService { private $connect; private $logService; @@ -153,7 +151,7 @@ class PollService { return $this->pollRepository->findAllByAdminMail($mail); } - function computeBestChoices($votes) { + function computeBestChoices($votes) { $result = ['y' => [0], 'inb' => [0]]; foreach ($votes as $vote) { $choices = str_split($vote->choices); diff --git a/app/inc/constants.php b/app/inc/constants.php index b631b9e..d36106a 100644 --- a/app/inc/constants.php +++ b/app/inc/constants.php @@ -17,7 +17,6 @@ * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) */ - // FRAMADATE version const VERSION = '1.0'; diff --git a/create_date_poll.php b/create_date_poll.php index 89f805b..05261b0 100644 --- a/create_date_poll.php +++ b/create_date_poll.php @@ -48,7 +48,6 @@ if ($_SESSION['form']->format !== 'D') { $_SESSION['form']->clearChoices(); } - if (!isset($_SESSION['form']->title) || !isset($_SESSION['form']->admin_name) || ($config['use_smtp'] && !isset($_SESSION['form']->admin_mail))) { $step = 1; } else if (!empty($_POST['confirmation'])) { diff --git a/create_poll.php b/create_poll.php index 015b63e..75f4240 100644 --- a/create_poll.php +++ b/create_poll.php @@ -57,7 +57,7 @@ if ($goToStep2) { $title = $inputService->filterTitle($_POST['title']); $use_ValueMax = isset($_POST['use_ValueMax']) ? $inputService->filterBoolean($_POST['use_ValueMax']) : false; - $ValueMax = $use_ValueMax == true ? $inputService->filterInteger($_POST['ValueMax']) : null; + $ValueMax = $use_ValueMax === true ? $inputService->filterInteger($_POST['ValueMax']) : null; $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; @@ -83,7 +83,6 @@ if ($goToStep2) { $error_on_customized_url = false; $error_on_ValueMax = false; - $_SESSION['form']->title = $title; $_SESSION['form']->id = $customized_url; $_SESSION['form']->use_customized_url = $use_customized_url; @@ -125,7 +124,6 @@ if ($goToStep2) { } } - if ($name !== $_POST['name']) { $error_on_name = true; } diff --git a/studs.php b/studs.php index 1b71197..64d1a89 100644 --- a/studs.php +++ b/studs.php @@ -30,9 +30,6 @@ use Framadate\Services\SecurityService; use Framadate\Services\SessionService; use Framadate\Utils; - - - include_once __DIR__ . '/app/inc/init.php'; /* Constantes */ From 76b19ee9ba5557b746bfe3ef47349aeb2026df3c Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Tue, 20 Feb 2018 15:17:14 +0100 Subject: [PATCH 3/5] fix votes wrongly calculated because of type check Signed-off-by: Thomas Citharel --- app/classes/Framadate/Services/PollService.php | 6 +++--- tpl/part/vote_table_classic.tpl | 2 +- tpl/part/vote_table_date.tpl | 14 +++++++------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/classes/Framadate/Services/PollService.php b/app/classes/Framadate/Services/PollService.php index 43efd42..c36c55c 100644 --- a/app/classes/Framadate/Services/PollService.php +++ b/app/classes/Framadate/Services/PollService.php @@ -113,7 +113,7 @@ class PollService { function addComment($poll_id, $name, $comment) { if ($this->commentRepository->exists($poll_id, $name, $comment)) { return true; - } + } return $this->commentRepository->insert($poll_id, $name, $comment); } @@ -160,10 +160,10 @@ class PollService { $result['inb'][$i] = 0; $result['y'][$i] = 0; } - if ($choice === 1) { + if ($choice === "1") { $result['inb'][$i]++; } - if ($choice === 2) { + if ($choice === "2") { $result['y'][$i]++; } } diff --git a/tpl/part/vote_table_classic.tpl b/tpl/part/vote_table_classic.tpl index 6ebed25..5f4a155 100644 --- a/tpl/part/vote_table_classic.tpl +++ b/tpl/part/vote_table_classic.tpl @@ -190,7 +190,7 @@ {$i = $i+1} - + {/foreach} diff --git a/tpl/part/vote_table_date.tpl b/tpl/part/vote_table_date.tpl index 2494be2..4366895 100644 --- a/tpl/part/vote_table_date.tpl +++ b/tpl/part/vote_table_date.tpl @@ -219,17 +219,17 @@ - - + + {$i = 0} - {foreach $slots as $slot} + {foreach $slots as $slot} {foreach $slot->moments as $moment} - +
    - {if $best_choices['y'][$i] lt $poll->ValueMax || $poll->ValueMax eq NULL} + {if $best_choices['y'][$i] lt $poll->ValueMax || $poll->ValueMax eq NULL}
  • - + {/if}
  • @@ -257,7 +257,7 @@
- + {$i = $i+1} {/foreach} From ff47a21ac292b190a4558256a9ef761e91536033 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Tue, 20 Feb 2018 16:47:10 +0100 Subject: [PATCH 4/5] Check that conditions on valueMax are acceptable before adding the vote Handles people voting when the answers valueMax has been reached by someone else in the background Signed-off-by: Thomas Citharel --- adminstuds.php | 5 +++ .../Exception/ConcurrentVoteException.php | 12 +++++ .../Framadate/Services/PollService.php | 45 +++++++++++++++++++ locale/br.json | 1 + locale/de.json | 1 + locale/en.json | 1 + locale/es.json | 1 + locale/fr.json | 1 + locale/it.json | 1 + locale/nl.json | 1 + locale/oc.json | 3 +- studs.php | 5 +++ 12 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 app/classes/Framadate/Exception/ConcurrentVoteException.php diff --git a/adminstuds.php b/adminstuds.php index 0d03059..74a205a 100644 --- a/adminstuds.php +++ b/adminstuds.php @@ -19,6 +19,7 @@ use Framadate\Editable; use Framadate\Exception\AlreadyExistsException; use Framadate\Exception\ConcurrentEditionException; +use Framadate\Exception\ConcurrentVoteException; use Framadate\Exception\MomentAlreadyExistsException; use Framadate\Message; use Framadate\Security\PasswordHasher; @@ -224,6 +225,8 @@ if (!empty($_POST['save'])) { // Save edition of an old vote } } catch (ConcurrentEditionException $cee) { $message = new Message('danger', __('Error', 'Poll has been updated before you vote')); + } catch (ConcurrentVoteException $cve) { + $message = new Message('danger', __('Error', "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.")); } } } elseif (isset($_POST['save'])) { // Add a new vote @@ -251,6 +254,8 @@ if (!empty($_POST['save'])) { // Save edition of an old vote $message = new Message('danger', __('Error', 'You already voted')); } catch (ConcurrentEditionException $cee) { $message = new Message('danger', __('Error', 'Poll has been updated before you vote')); + } catch (ConcurrentVoteException $cve) { + $message = new Message('danger', __('Error', "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.")); } } } diff --git a/app/classes/Framadate/Exception/ConcurrentVoteException.php b/app/classes/Framadate/Exception/ConcurrentVoteException.php new file mode 100644 index 0000000..26b29ec --- /dev/null +++ b/app/classes/Framadate/Exception/ConcurrentVoteException.php @@ -0,0 +1,12 @@ +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); @@ -93,9 +107,22 @@ class PollService { return $this->voteRepository->update($poll_id, $vote_id, $name, $choices); } + /** + * @param $poll_id + * @param $name + * @param $choices + * @param $slots_hash + * @return \stdClass + * @throws AlreadyExistsException + * @throws ConcurrentEditionException + * @throws ConcurrentVoteException + */ function addVote($poll_id, $name, $choices, $slots_hash) { $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); @@ -252,4 +279,22 @@ class PollService { throw new ConcurrentEditionException(); } } + + /** + * This method checks if the votes doesn't conflicts the maximum votes constraint + * + * @param $user_choice + * @param \stdClass $poll + * @param string $poll_id + * @throws ConcurrentVoteException + */ + private function checkMaxVotes($user_choice, $poll, $poll_id) { + $best_choices = $this->computeBestChoices($this->allVotesByPollId($poll_id)); + foreach ($best_choices['y'] as $i => $nb_choice) { + // if for this option we have reached maximum value and user wants to add itself too + if ($nb_choice >= $poll->ValueMax && $user_choice[$i] === "2") { + throw new ConcurrentVoteException(); + } + } + } } diff --git a/locale/br.json b/locale/br.json index 9f8990a..b20e00e 100644 --- a/locale/br.json +++ b/locale/br.json @@ -395,6 +395,7 @@ "Adding vote failed": "C'hwitadenn war ouzhpennadenn ar vouezh", "You already voted": "Mouezhzt ho peus endeo", "Poll has been updated before you vote": "Hizivaet eo bet ar sontadeg a-raok ho mouezh", + "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.": "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.", "Comment failed": "C'hiwtadenn war an evezhiadenn", "You can't create a poll with hidden results with the following edition option:": "N'hallit ket krouiñ ur sontadeg gant respontoù kuzhet gant an dibarzhioù embann da heul:", "Failed to delete column": "C'hwitadenn war zilemel ar bann", diff --git a/locale/de.json b/locale/de.json index 8b32bb7..1e100a5 100644 --- a/locale/de.json +++ b/locale/de.json @@ -396,6 +396,7 @@ "Adding vote failed": "Stimmabgabe fehlgeschlagen", "You already voted": "Sie haben bereits abgestimmt", "Poll has been updated before you vote": "Die Abstimmung wurde vor Ihrer Stimmabgabe aktualisiert", + "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.": "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.", "Comment failed": "Abgabe des Kommentars gescheitert", "You can't create a poll with hidden results with the following edition option:": "Sie können mit der folgenden Editier-Option keine Umfrage mit versteckten Ergebnissen erzeugen:", "Failed to delete column": "Löschen der Spalte fehlgeschlagen", diff --git a/locale/en.json b/locale/en.json index c412a76..c487a84 100644 --- a/locale/en.json +++ b/locale/en.json @@ -399,6 +399,7 @@ "Adding vote failed": "Adding vote failed", "You already voted": "You already voted", "Poll has been updated before you vote": "Poll has been updated before you vote", + "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.": "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.", "Comment failed": "Comment failed", "You can't create a poll with hidden results with the following edition option:": "You can't create a poll with hidden results with the following option: ", "Failed to delete column": "Failed to delete column", diff --git a/locale/es.json b/locale/es.json index a267524..3c0ebc9 100644 --- a/locale/es.json +++ b/locale/es.json @@ -396,6 +396,7 @@ "Adding vote failed": "Error al crear el voto", "You already voted": "Usted ya votó", "Poll has been updated before you vote": "La encuesta fue actualizada antes de su voto", + "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.": "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.", "Comment failed": "Error al crear el comentario", "You can't create a poll with hidden results with the following edition option:": "No puede crear una encuesta con resultados no visibles con los siguientes opciones de edición", "Failed to delete column": "Error al eliminar la columna", diff --git a/locale/fr.json b/locale/fr.json index 6486504..1de86bb 100644 --- a/locale/fr.json +++ b/locale/fr.json @@ -399,6 +399,7 @@ "Adding vote failed": "Échec de l'ajout d'un vote", "You already voted": "Vous avez déjà voté", "Poll has been updated before you vote": "Le sondage a été mis à jour avant votre vote", + "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.": "Votre vote n'a pas été pris en compte, car quelqu'un a voté entre temps et cela entre en conflit avec vos choix et les conditions du sondage. Merci de réessayer.", "Comment failed": "Échec du commentaire", "You can't create a poll with hidden results with the following edition option:": "Vous ne pouvez pas créer de sondage avec résulats cachés avec les options d'édition suivantes : ", "Failed to delete column": "Échec de la suppression de colonne", diff --git a/locale/it.json b/locale/it.json index 112a881..83f1368 100644 --- a/locale/it.json +++ b/locale/it.json @@ -396,6 +396,7 @@ "Adding vote failed": "Aggiunta del voto fallito", "You already voted": "IT_Vous avez déjà voté", "Poll has been updated before you vote": "IT_Le sondage a été mis à jour avant votre vote", + "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.": "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.", "Comment failed": "Commento fallito", "You can't create a poll with hidden results with the following edition option:": "Non potete creare un sondaggio con i risultati nascosti con queste opzioni: ", "Failed to delete column": "Impossibile eliminare la colonna", diff --git a/locale/nl.json b/locale/nl.json index 3f17a53..14499e0 100644 --- a/locale/nl.json +++ b/locale/nl.json @@ -396,6 +396,7 @@ "Adding vote failed": "Toevoegen stem gefaald", "You already voted": "Je hebt al gestemd", "Poll has been updated before you vote": "De poll is gewijzigd voordat je stemde", + "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.": "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.", "Comment failed": "Opmerking mislukt", "You can't create a poll with hidden results with the following edition option:": "Je kan geen poll met verborgen resultaten maken met de volgende optie: ", "Failed to delete column": "Kolom verwijderen mislukt", diff --git a/locale/oc.json b/locale/oc.json index e2a9811..8bdac4b 100644 --- a/locale/oc.json +++ b/locale/oc.json @@ -396,6 +396,7 @@ "Adding vote failed": "Fracàs de l’apondon d’un vòte", "You already voted": "Avètz ja votat", "Poll has been updated before you vote": "Lo sondatge es estat mes a jorn abans vòstre vòte", + "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.": "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.", "Comment failed": "Fracàs del comentari", "You can't create a poll with hidden results with the following edition option:": "Podètz pas crear de sondatges amb de resultats amagats amb las opcions d’edicion seguentas : ", "Failed to delete column": "Fracàs de la supression de colomna", @@ -428,4 +429,4 @@ "Check again": "Tornar verificar", "Continue the installation": "Contunhar l’installacion" } -} \ No newline at end of file +} diff --git a/studs.php b/studs.php index 64d1a89..b9a30b2 100644 --- a/studs.php +++ b/studs.php @@ -19,6 +19,7 @@ use Framadate\Editable; use Framadate\Exception\AlreadyExistsException; use Framadate\Exception\ConcurrentEditionException; +use Framadate\Exception\ConcurrentVoteException; use Framadate\Message; use Framadate\Security\Token; use Framadate\Services\InputService; @@ -146,6 +147,8 @@ if ($accessGranted) { } } catch (ConcurrentEditionException $cee) { $message = new Message('danger', __('Error', 'Poll has been updated before you vote')); + } catch (ConcurrentVoteException $cve) { + $message = new Message('danger', __('Error', "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.")); } } } elseif (isset($_POST['save'])) { // Add a new vote @@ -179,6 +182,8 @@ if ($accessGranted) { $message = new Message('danger', __('Error', 'You already voted')); } catch (ConcurrentEditionException $cee) { $message = new Message('danger', __('Error', 'Poll has been updated before you vote')); + } catch (ConcurrentVoteException $cve) { + $message = new Message('danger', __('Error', "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry.")); } } } From a442cc5ee723e7c12d67b97c4812c33be46bcd2f Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Tue, 20 Feb 2018 16:50:14 +0100 Subject: [PATCH 5/5] CS Signed-off-by: Thomas Citharel --- app/classes/Framadate/Services/PollService.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/classes/Framadate/Services/PollService.php b/app/classes/Framadate/Services/PollService.php index a47edc2..c967d0a 100644 --- a/app/classes/Framadate/Services/PollService.php +++ b/app/classes/Framadate/Services/PollService.php @@ -89,9 +89,9 @@ class PollService { * @param $name * @param $choices * @param $slots_hash - * @return bool * @throws ConcurrentEditionException * @throws ConcurrentVoteException + * @return bool */ public function updateVote($poll_id, $vote_id, $name, $choices, $slots_hash) { $poll = $this->findById($poll_id); @@ -112,10 +112,10 @@ class PollService { * @param $name * @param $choices * @param $slots_hash - * @return \stdClass * @throws AlreadyExistsException * @throws ConcurrentEditionException * @throws ConcurrentVoteException + * @return \stdClass */ function addVote($poll_id, $name, $choices, $slots_hash) { $poll = $this->findById($poll_id);