From a219ccdee3b7736182129cd7768c35750cc9fe6d Mon Sep 17 00:00:00 2001 From: Antonin Date: Mon, 30 Nov 2015 21:16:17 +0100 Subject: [PATCH 01/35] Added SessionService --- .../Framadate/Services/SessionService.php | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 app/classes/Framadate/Services/SessionService.php diff --git a/app/classes/Framadate/Services/SessionService.php b/app/classes/Framadate/Services/SessionService.php new file mode 100644 index 0000000..c30e978 --- /dev/null +++ b/app/classes/Framadate/Services/SessionService.php @@ -0,0 +1,53 @@ +initSectionIfNeeded($section); + + $returnValue = $defaultValue; + if (isset($_SESSION[$section][$key])) { + $returnValue = $_SESSION[$section][$key]; + } + + return $returnValue; + } + + /** + * Set a $value for $key in $section + * + * @param $section + * @param $key + * @param $value + */ + public function set($section, $key, $value) { + assert(!empty($key)); + assert(!empty($section)); + + $this->initSectionIfNeeded($section); + + $_SESSION[$section][$key] = $value; + } + + private function initSectionIfNeeded($section) { + if (!isset($_SESSION[$section])) { + $_SESSION[$section] = array(); + } + } + +} \ No newline at end of file From 65a753129a85cc343e5970d7787a84ce93920413 Mon Sep 17 00:00:00 2001 From: Antonin Date: Mon, 30 Nov 2015 22:23:26 +0100 Subject: [PATCH 02/35] Remembering last user vote in session --- adminstuds.php | 1 + studs.php | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/adminstuds.php b/adminstuds.php index aa7eb24..ce091fa 100644 --- a/adminstuds.php +++ b/adminstuds.php @@ -395,5 +395,6 @@ $smarty->assign('admin', true); $smarty->assign('hidden', false); $smarty->assign('accessGranted', true); $smarty->assign('resultPubliclyVisible', true); +$smarty->assign('editedVoteUniqueId', ''); $smarty->display('studs.tpl'); diff --git a/studs.php b/studs.php index 47a5626..afbdf30 100644 --- a/studs.php +++ b/studs.php @@ -22,12 +22,19 @@ use Framadate\Services\InputService; use Framadate\Services\MailService; use Framadate\Services\NotificationService; use Framadate\Services\SecurityService; +use Framadate\Services\SessionService; use Framadate\Message; use Framadate\Utils; use Framadate\Editable; include_once __DIR__ . '/app/inc/init.php'; +/* Constantes */ +/* ---------- */ + +const USER_REMEMBER_VOTES_KEY = 'UserVotes'; + + /* Variables */ /* --------- */ @@ -40,7 +47,6 @@ $resultPubliclyVisible = true; $slots = array(); $votes = array(); $comments = array(); -$editedVoteUniqueId = null; /* Services */ /*----------*/ @@ -51,6 +57,7 @@ $inputService = new InputService(); $mailService = new MailService($config['use_smtp']); $notificationService = new NotificationService($mailService); $securityService = new SecurityService(); +$sessionService = new SessionService(); /* PAGE */ @@ -69,6 +76,8 @@ if (!$poll) { exit; } +$editedVoteUniqueId = $sessionService->get(USER_REMEMBER_VOTES_KEY, $poll_id, ''); + // ------------------------------- // Password verification // ------------------------------- @@ -127,8 +136,9 @@ if ($accessGranted) { $result = $pollService->updateVote($poll_id, $editedVote, $name, $choices); if ($result) { if ($poll->editable == Editable::EDITABLE_BY_OWN) { - $editedVoteUniqId = filter_input(INPUT_POST, 'edited_vote', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); - $urlEditVote = Utils::getUrlSondage($poll_id, false, $editedVoteUniqId); + $editedVoteUniqueId = filter_input(INPUT_POST, 'edited_vote', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); + $sessionService->set(USER_REMEMBER_VOTES_KEY, $poll_id, $editedVoteUniqueId); + $urlEditVote = Utils::getUrlSondage($poll_id, false, $editedVoteUniqueId); $message = new Message('success', __('studs', '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:'), $urlEditVote); } else { $message = new Message('success', __('studs', 'Update vote succeeded')); @@ -154,7 +164,9 @@ if ($accessGranted) { $result = $pollService->addVote($poll_id, $name, $choices); if ($result) { if ($poll->editable == Editable::EDITABLE_BY_OWN) { - $urlEditVote = Utils::getUrlSondage($poll_id, false, $result->uniqId); + $editedVoteUniqueId = $result->uniqId; + $sessionService->set(USER_REMEMBER_VOTES_KEY, $poll_id, $editedVoteUniqueId); + $urlEditVote = Utils::getUrlSondage($poll_id, false, $editedVoteUniqueId); $message = new Message('success', __('studs', '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:'), $urlEditVote); } else { $message = new Message('success', __('studs', 'Adding the vote succeeded')); From 2b9f68780e98f39e6f1b6c0fc8b9ff1ac16e53b3 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Tue, 1 Dec 2015 22:20:24 +0100 Subject: [PATCH 03/35] Fixes #122 use the right method to use table names --- app/classes/Framadate/Migration/RPadVotes_from_0_8.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/classes/Framadate/Migration/RPadVotes_from_0_8.php b/app/classes/Framadate/Migration/RPadVotes_from_0_8.php index fcd03c9..506a705 100644 --- a/app/classes/Framadate/Migration/RPadVotes_from_0_8.php +++ b/app/classes/Framadate/Migration/RPadVotes_from_0_8.php @@ -52,13 +52,13 @@ class RPadVotes_from_0_8 implements Migration { } private function rpadVotes($pdo) { - $pdo->exec('UPDATE fd_vote fv + $pdo->exec('UPDATE '. Utils::table('vote') .' fv INNER JOIN ( SELECT v.id, RPAD(v.choices, inn.slots_count, \'0\') new_choices - FROM fd_vote v + FROM '. Utils::table('vote') .' v INNER JOIN (SELECT s.poll_id, SUM(IFNULL(LENGTH(s.moments) - LENGTH(REPLACE(s.moments, \',\', \'\')) + 1, 1)) slots_count - FROM fd_slot s + FROM '. Utils::table('slot') .' s GROUP BY s.poll_id ORDER BY s.poll_id) inn ON inn.poll_id = v.poll_id WHERE LENGTH(v.choices) != inn.slots_count From a9bddc94b364a9a124c805bfe4780a73aa3d6ae7 Mon Sep 17 00:00:00 2001 From: Antonin Date: Wed, 2 Dec 2015 17:29:42 +0100 Subject: [PATCH 04/35] =?UTF-8?q?Affichage=20d'un=20titre=20sur=20l'ent?= =?UTF-8?q?=C3=AAte=20des=20colonnes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tpl/part/vote_table_classic.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tpl/part/vote_table_classic.tpl b/tpl/part/vote_table_classic.tpl index 1a3df94..b5593bd 100644 --- a/tpl/part/vote_table_classic.tpl +++ b/tpl/part/vote_table_classic.tpl @@ -36,7 +36,7 @@ {foreach $slots as $id=>$slot} - {$slot->title|markdown} + {$slot->title|markdown} {/foreach} From 421f86d8a303559151329eb5737b0f652347b068 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Sat, 5 Dec 2015 14:24:38 +0100 Subject: [PATCH 05/35] UrlNaming - Increase size of poll's id column --- admin/migration.php | 2 + .../Migration/Increase_pollId_size.php | 46 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 app/classes/Framadate/Migration/Increase_pollId_size.php diff --git a/admin/migration.php b/admin/migration.php index ad58d66..cf8f8f9 100644 --- a/admin/migration.php +++ b/admin/migration.php @@ -26,6 +26,7 @@ use Framadate\Migration\Alter_Comment_table_for_name_length; use Framadate\Migration\Alter_Comment_table_adding_date; use Framadate\Migration\Generate_uniqId_for_old_votes; use Framadate\Migration\AddColumns_password_hash_And_results_publicly_visible_In_poll_For_0_9; +use Framadate\Migration\Increase_pollId_size; use Framadate\Migration\Migration; use Framadate\Migration\RPadVotes_from_0_8; use Framadate\Utils; @@ -46,6 +47,7 @@ $migrations = [ 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/Migration/Increase_pollId_size.php b/app/classes/Framadate/Migration/Increase_pollId_size.php new file mode 100644 index 0000000..80fb500 --- /dev/null +++ b/app/classes/Framadate/Migration/Increase_pollId_size.php @@ -0,0 +1,46 @@ +alterPollTable($pdo); + } + + private function alterPollTable(\PDO $pdo) { + $pdo->exec(' + ALTER TABLE `' . Utils::table('poll') . '` + CHANGE `id` `id` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;'); + } +} From 86fb49d51e0d19789e68ea272a364856c4ff5a8b Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Sat, 5 Dec 2015 14:38:24 +0100 Subject: [PATCH 06/35] Fix tpl binding --- tpl/create_poll.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tpl/create_poll.tpl b/tpl/create_poll.tpl index 8ab82d1..09443c6 100644 --- a/tpl/create_poll.tpl +++ b/tpl/create_poll.tpl @@ -16,7 +16,7 @@ {__('Step 1', 'Required fields cannot be left blank.')}

-
+
@@ -32,7 +32,7 @@
{/if} -
+
From fac20a590883870cc5f68b036c1e89c3dde7902b Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Sat, 5 Dec 2015 16:03:01 +0100 Subject: [PATCH 07/35] UrlNaming - Add ID field to creation form --- app/classes/Framadate/Form.php | 1 + .../Framadate/Services/InputService.php | 5 ++++ app/inc/constants.php | 2 +- create_poll.php | 28 +++++++++++++++---- js/app/create_poll.js | 25 +++++++++++++++++ tpl/create_poll.tpl | 25 +++++++++++++++++ 6 files changed, 80 insertions(+), 6 deletions(-) diff --git a/app/classes/Framadate/Form.php b/app/classes/Framadate/Form.php index 07b7868..52437e5 100644 --- a/app/classes/Framadate/Form.php +++ b/app/classes/Framadate/Form.php @@ -22,6 +22,7 @@ class Form { public $title; + public $id; public $description; public $admin_name; public $admin_mail; diff --git a/app/classes/Framadate/Services/InputService.php b/app/classes/Framadate/Services/InputService.php index 29e8a42..ff1d999 100644 --- a/app/classes/Framadate/Services/InputService.php +++ b/app/classes/Framadate/Services/InputService.php @@ -54,6 +54,11 @@ class InputService { return $this->returnIfNotBlank($title); } + public function filterId($id) { + $filtered = filter_var($id, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); + return $filtered ? substr($filtered, 0, 64) : false; + } + public function filterName($name) { $filtered = trim($name); return $this->returnIfNotBlank($filtered); diff --git a/app/inc/constants.php b/app/inc/constants.php index 166b21b..2430cce 100644 --- a/app/inc/constants.php +++ b/app/inc/constants.php @@ -21,7 +21,7 @@ const VERSION = '0.9'; // Regex -const POLL_REGEX = '/^[a-z0-9]+$/i'; +const POLL_REGEX = '/^[a-z0-9-]*$/i'; const CHOICE_REGEX = '/^[012]$/'; const BOOLEAN_REGEX = '/^(on|off|true|false|1|0)$/i'; const BOOLEAN_TRUE_REGEX = '/^(on|true|1)$/i'; diff --git a/create_poll.php b/create_poll.php index 06b4143..15f4a80 100644 --- a/create_poll.php +++ b/create_poll.php @@ -18,10 +18,9 @@ */ use Framadate\Form; -use Framadate\Services\InputService; -use Framadate\Editable; -use Framadate\Utils; use Framadate\Security\PasswordHasher; +use Framadate\Services\InputService; +use Framadate\Utils; include_once __DIR__ . '/app/inc/init.php'; @@ -55,6 +54,7 @@ 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']); + $id = $inputService->filterId($_POST['id']); $name = $inputService->filterName($_POST['name']); $mail = $inputService->filterMail($_POST['mail']); $description = $inputService->filterDescription($_POST['description']); @@ -76,6 +76,7 @@ if ($goToStep2) { $error_on_password_repeat = false; $_SESSION['form']->title = $title; + $_SESSION['form']->id = $id; $_SESSION['form']->admin_name = $name; $_SESSION['form']->admin_mail = $mail; $_SESSION['form']->description = $description; @@ -97,6 +98,10 @@ if ($goToStep2) { $error_on_title = true; } + if ($id === false) { + $error_on_id = true; + } + if ($name !== $_POST['name']) { $error_on_name = true; } @@ -120,8 +125,9 @@ if ($goToStep2) { } } - if ($title && $name && $email_OK && !$error_on_title && !$error_on_description && !$error_on_name - && !$error_on_password && !$error_on_password_repeat) { + if ($title && $name && $email_OK && !$error_on_title && !$error_on_id && !$error_on_description && !$error_on_name + && !$error_on_password && !$error_on_password_repeat + ) { // If no errors, we hash the password if needed if ($_SESSION['form']->use_password) { @@ -157,6 +163,11 @@ $errors = array( 'aria' => '', 'class' => '' ), + 'id' => array( + 'msg' => '', + 'aria' => '', + 'class' => '' + ), 'description' => array( 'msg' => '', 'aria' => '', @@ -195,6 +206,12 @@ if (!empty($_POST[GO_TO_STEP_2])) { $errors['title']['msg'] = __('Error', 'Something is wrong with the format'); } + if ($error_on_id) { + $errors['id']['aria'] = 'aria-describeby="poll_comment_error" '; + $errors['id']['class'] = ' has-error'; + $errors['id']['msg'] = __('Error', 'Something is wrong with the format'); + } + if ($error_on_description) { $errors['description']['aria'] = 'aria-describeby="poll_comment_error" '; $errors['description']['class'] = ' has-error'; @@ -243,6 +260,7 @@ $smarty->assign('goToStep2', GO_TO_STEP_2); $smarty->assign('poll_type', $poll_type); $smarty->assign('poll_title', Utils::fromPostOrDefault('title', $_SESSION['form']->title)); +$smarty->assign('poll_id', Utils::fromPostOrDefault('id', $_SESSION['form']->id)); $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 ebd8744..0ee8bdb 100644 --- a/js/app/create_poll.js +++ b/js/app/create_poll.js @@ -33,6 +33,31 @@ $(document).ready(function () { } }); + /** + * Enable/Disable custom id options + */ + var $pollId = $("#poll_id"); + var $customId = $("#custom_id"); + + // Init checkbox + input + if (($pollId.val() || $pollId.attr('value') || "").length > 0) { + $customId.attr('checked', 'checked'); + $pollId.removeAttr("disabled"); + } + // Listen for checkbox changes + $customId.change(function () { + if ($(this).prop("checked")) { + $pollId + .removeAttr("disabled") + .val($pollId.attr("tmp") || $pollId.attr('value')); + } else { + $pollId + .attr("disabled", "disabled") + .attr("tmp", $pollId.val()) + .val(""); + } + }); + /** * Hide/Show password options */ diff --git a/tpl/create_poll.tpl b/tpl/create_poll.tpl index 09443c6..9b576c2 100644 --- a/tpl/create_poll.tpl +++ b/tpl/create_poll.tpl @@ -16,6 +16,7 @@ {__('Step 1', 'Required fields cannot be left blank.')}

+
@@ -32,6 +33,30 @@
{/if} +
+ + +
+
+ + + + +
+ {__('Step 1', 'Poll id rules')} + {__('Step 1', 'Poll id warning')} +
+
+ {if !empty($errors['id']['msg'])} +
+

+ {$errors['id']['msg']} +

+
+ {/if} +
From 1efd7b9ab0ab1ce376cf7e66fc3879f1ae5662fe Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Sat, 5 Dec 2015 16:30:49 +0100 Subject: [PATCH 08/35] UrlNaming - Generate id unless if user has already choosen one --- .../Framadate/Repositories/PollRepository.php | 8 +++++++ .../Framadate/Services/PollService.php | 22 +++++++++++++------ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/app/classes/Framadate/Repositories/PollRepository.php b/app/classes/Framadate/Repositories/PollRepository.php index fd62e55..e2315a3 100644 --- a/app/classes/Framadate/Repositories/PollRepository.php +++ b/app/classes/Framadate/Repositories/PollRepository.php @@ -47,6 +47,14 @@ class PollRepository extends AbstractRepository { return $prepared->rowCount() > 0; } + public function existsByAdminId($admin_poll_id) { + $prepared = $this->prepare('SELECT 1 FROM `' . Utils::table('poll') . '` WHERE admin_id = ?'); + + $prepared->execute(array($admin_poll_id)); + + return $prepared->rowCount() > 0; + } + function update($poll) { $prepared = $this->prepare('UPDATE `' . Utils::table('poll') . '` SET title=?, admin_name=?, admin_mail=?, description=?, end_date=?, active=?, editable=?, hidden=?, password_hash=?, results_publicly_visible=? WHERE id = ?'); diff --git a/app/classes/Framadate/Services/PollService.php b/app/classes/Framadate/Services/PollService.php index 3897791..2ccb9f8 100644 --- a/app/classes/Framadate/Services/PollService.php +++ b/app/classes/Framadate/Services/PollService.php @@ -20,9 +20,8 @@ namespace Framadate\Services; use Framadate\Form; use Framadate\FramaDB; -use Framadate\Utils; -use Framadate\Security\Token; use Framadate\Repositories\RepositoryFactory; +use Framadate\Security\Token; class PollService { @@ -112,12 +111,21 @@ class PollService { * @return string */ function createPoll(Form $form) { - // Generate poll IDs, loop while poll ID already exists - do { - $poll_id = $this->random(16); - } while ($this->pollRepository->existsById($poll_id)); - $admin_poll_id = $poll_id . $this->random(8); + + if (empty($form->id)) { // User want us to generate an id for him + do { + $poll_id = $this->random(16); + } while ($this->pollRepository->existsById($poll_id)); + $admin_poll_id = $poll_id . $this->random(8); + + } else { // User have choosen the poll id + $poll_id = $form->id; + do { + $admin_poll_id = $this->random(24); + } while ($this->pollRepository->existsByAdminId($admin_poll_id)); + + } // Insert poll + slots $this->pollRepository->beginTransaction(); From 17d050507b9080581582f270c449715e48b63285 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Sat, 5 Dec 2015 16:35:32 +0100 Subject: [PATCH 09/35] UrlNaming - Allow new id format when loading a poll --- app/classes/Framadate/Services/PollService.php | 4 ++-- app/inc/constants.php | 1 + studs.php | 4 +--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/classes/Framadate/Services/PollService.php b/app/classes/Framadate/Services/PollService.php index 2ccb9f8..2c4ed39 100644 --- a/app/classes/Framadate/Services/PollService.php +++ b/app/classes/Framadate/Services/PollService.php @@ -49,7 +49,7 @@ class PollService { * @return \stdClass|null The found poll, or null */ function findById($poll_id) { - if (preg_match('/^[\w\d]{16}$/i', $poll_id)) { + if (preg_match(POLL_REGEX, $poll_id)) { return $this->pollRepository->findById($poll_id); } @@ -57,7 +57,7 @@ class PollService { } public function findByAdminId($admin_poll_id) { - if (preg_match('/^[\w\d]{24}$/i', $admin_poll_id)) { + if (preg_match(ADMIN_POLL_REGEX, $admin_poll_id)) { return $this->pollRepository->findByAdminId($admin_poll_id); } diff --git a/app/inc/constants.php b/app/inc/constants.php index 2430cce..43a1fc4 100644 --- a/app/inc/constants.php +++ b/app/inc/constants.php @@ -22,6 +22,7 @@ const VERSION = '0.9'; // Regex const POLL_REGEX = '/^[a-z0-9-]*$/i'; +const ADMIN_POLL_REGEX = '/^[\w\d]{24}$/i'; const CHOICE_REGEX = '/^[012]$/'; const BOOLEAN_REGEX = '/^(on|off|true|false|1|0)$/i'; const BOOLEAN_TRUE_REGEX = '/^(on|true|1)$/i'; diff --git a/studs.php b/studs.php index 47a5626..67ff873 100644 --- a/studs.php +++ b/studs.php @@ -58,9 +58,7 @@ $securityService = new SecurityService(); if (!empty($_GET['poll'])) { $poll_id = filter_input(INPUT_GET, 'poll', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); - if (strlen($poll_id) === 16) { - $poll = $pollService->findById($poll_id); - } + $poll = $pollService->findById($poll_id); } if (!$poll) { From 013aeaecd11cbc9fa711a56f8d67b5e6f1a02b95 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Sat, 5 Dec 2015 17:27:18 +0100 Subject: [PATCH 10/35] UrlNaming - Check if poll id is already used --- create_poll.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/create_poll.php b/create_poll.php index 15f4a80..fefdbe9 100644 --- a/create_poll.php +++ b/create_poll.php @@ -18,6 +18,7 @@ */ use Framadate\Form; +use Framadate\Repositories\RepositoryFactory; use Framadate\Security\PasswordHasher; use Framadate\Services\InputService; use Framadate\Utils; @@ -31,6 +32,7 @@ const GO_TO_STEP_2 = 'gotostep2'; /*----------*/ $inputService = new InputService(); +$pollRepository = RepositoryFactory::pollRepository(); /* PAGE */ /* ---- */ @@ -100,6 +102,9 @@ if ($goToStep2) { if ($id === false) { $error_on_id = true; + } else if ($pollRepository->existsById($id)) { + $error_on_id = true; + $error_on_id_msg = __('Error', 'Poll id already used'); } if ($name !== $_POST['name']) { @@ -209,7 +214,7 @@ if (!empty($_POST[GO_TO_STEP_2])) { if ($error_on_id) { $errors['id']['aria'] = 'aria-describeby="poll_comment_error" '; $errors['id']['class'] = ' has-error'; - $errors['id']['msg'] = __('Error', 'Something is wrong with the format'); + $errors['id']['msg'] = isset($error_on_id_msg) ? $error_on_id_msg : __('Error', 'Something is wrong with the format'); } if ($error_on_description) { From 604be480c41c58445108567778f59c8bb1fe9922 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Sat, 5 Dec 2015 19:26:32 +0100 Subject: [PATCH 11/35] UrlNaming - "Translate" --- locale/de.json | 9 ++++++--- locale/en.json | 6 +++++- locale/es.json | 9 ++++++--- locale/fr.json | 6 +++++- locale/it.json | 6 +++++- tpl/create_poll.tpl | 2 +- 6 files changed, 28 insertions(+), 10 deletions(-) diff --git a/locale/de.json b/locale/de.json index 43bd686..6fa1eef 100644 --- a/locale/de.json +++ b/locale/de.json @@ -216,6 +216,9 @@ "You are in the poll creation section.": "Hier erstellen Sie die Umfrage", "Required fields cannot be left blank.": "Mit * markierte Felder müssen ausgefüllt sein.", "Poll title": "Titel der Umfrage", + "Poll id": "DE_Identifiant", + "Poll id rules": "DE_L'identifiant peut contenir des lettres, des chiffres et des tirets \"-\".", + "Poll id warning": "DE_En définissant un identifiant cela peut faciliter l'accès à ce sondage pour des personnes non désirées. Il est recommandé de le protéger par mot de passe.", "Votes cannot be modified.": "Wertungen können nicht verändert werden.", "All voters can modify any vote": "Jeder Teilnehmer kann jede abgegebene Wertung ändern.", "Voters can modify their vote themselves": "Teilnehmer können ihre Wertungen verändern", @@ -355,8 +358,8 @@ "The column already exists": "DE_La colonne existe déjà", "MISSING_VALUES": "Fehlende Werte", "CANT_CONNECT_TO_DATABASE": "Kann nicht mit der Datenbank verbinden", - "Password is empty": "DE_Le mot de passe est vide.", - "Passwords do not match": "DE_Les mot de passes ne correspondent pas." - + "Password is empty": "DE_Le mot de passe est vide.", + "Passwords do not match": "DE_Les mot de passes ne correspondent pas.", + "Poll id already used": "DE_L'identifiant est déjà utilisé" } } diff --git a/locale/en.json b/locale/en.json index c83615e..82fe21f 100644 --- a/locale/en.json +++ b/locale/en.json @@ -216,6 +216,9 @@ "You are in the poll creation section.": "You are in the poll creation section.", "Required fields cannot be left blank.": "Required fields cannot be left blank.", "Poll title": "Poll title", + "Poll id": "Identifier", + "Poll id rules": "The identifier can contain letters, numbers and dashes \"-\".", + "Poll id warning": "By defining an identifier that can facilitate access to the poll for unwanted people. It is recommended to protect it with a password.", "Votes cannot be modified.": "Votes cannot be modified", "All voters can modify any vote": "All voters can modify any vote", "Voters can modify their vote themselves": "Voters can modify their vote themselves", @@ -356,6 +359,7 @@ "MISSING_VALUES": "Missing values", "CANT_CONNECT_TO_DATABASE": "Unable to connect to database", "Password is empty": "Password is empty.", - "Passwords do not match": "Passwords do not match." + "Passwords do not match": "Passwords do not match.", + "Poll id already used": "Identifier is already used" } } diff --git a/locale/es.json b/locale/es.json index 195ec65..9364e81 100644 --- a/locale/es.json +++ b/locale/es.json @@ -216,6 +216,9 @@ "You are in the poll creation section.": "Usted ha eligiendo de crear une nueva encuesta!", "Required fields cannot be left blank.": "Gracias por completar los campos con una *.", "Poll title": "ES_Titre du sondage", + "Poll id": "ES_Identifiant", + "Poll id rules": "ES_L'identifiant peut contenir des lettres, des chiffres et des tirets \"-\".", + "Poll id warning": "ES_En définissant un identifiant cela peut faciliter l'accès à ce sondage pour des personnes non désirées. Il est recommandé de le protéger par mot de passe.", "Votes cannot be modified.": "ES_Aucun vote ne peut être modifié", "All voters can modify any vote": "ES_Tous les sondés peuvent modifier tous les votes", "Voters can modify their vote themselves": "Los encuentados pueden cambiar su línea ellos mismos", @@ -355,8 +358,8 @@ "The column already exists": "ES_La colonne existe déjà", "MISSING_VALUES": "Los valores perdidos", "CANT_CONNECT_TO_DATABASE": "No se puede conectar a la base de datos", - "Password is empty": "ES_Le mot de passe est vide.", - "Passwords do not match": "ES_Les mot de passes ne correspondent pas." - + "Password is empty": "ES_Le mot de passe est vide.", + "Passwords do not match": "ES_Les mot de passes ne correspondent pas.", + "Poll id already used": "ES_L'identifiant est déjà utilisé" } } diff --git a/locale/fr.json b/locale/fr.json index 2fcbb16..7e22bad 100644 --- a/locale/fr.json +++ b/locale/fr.json @@ -216,6 +216,9 @@ "You are in the poll creation section.": "Vous avez choisi de créer un nouveau sondage.", "Required fields cannot be left blank.": "Merci de remplir les champs obligatoires, marqués d'une *.", "Poll title": "Titre du sondage", + "Poll id": "Identifiant", + "Poll id rules": "L'identifiant peut contenir des lettres, des chiffres et des tirets \"-\".", + "Poll id warning": "En définissant un identifiant cela peut faciliter l'accès à ce sondage pour des personnes non désirées. Il est recommandé de le protéger par mot de passe.", "Votes cannot be modified.": "Aucun vote ne peut être modifié", "All voters can modify any vote": "Tous les sondés peuvent modifier tous les votes", "Voters can modify their vote themselves": "Chaque sondé peut modifier son propre vote", @@ -370,6 +373,7 @@ "MISSING_VALUES": "Il manque des valeurs", "CANT_CONNECT_TO_DATABASE": "Impossible de se connecter à la base de données", "Password is empty": "Le mot de passe est vide.", - "Passwords do not match": "Les mots de passe ne correspondent pas." + "Passwords do not match": "Les mots de passe ne correspondent pas.", + "Poll id already used": "L'identifiant est déjà utilisé" } } diff --git a/locale/it.json b/locale/it.json index e6ac2a5..b513e56 100644 --- a/locale/it.json +++ b/locale/it.json @@ -216,6 +216,9 @@ "You are in the poll creation section.": "Avete scelto di creare un nuovo sondaggio.", "Required fields cannot be left blank.": "Riempire i campi obbligatori, segnati con *.", "Poll title": "Titolo del sondaggio", + "Poll id": "IT_Identifiant", + "Poll id rules": "IT_L'identifiant peut contenir des lettres, des chiffres et des tirets \"-\".", + "Poll id warning": "IT_En définissant un identifiant cela peut faciliter l'accès à ce sondage pour des personnes non désirées. Il est recommandé de le protéger par mot de passe.", "Votes cannot be modified.": "Nessun voto può essere modificato", "All voters can modify any vote": "Tutti i votanti possono cambiare tutti i voti", "Voters can modify their vote themselves": "I partecipanti possono modificare il loro voto in autonomia", @@ -354,6 +357,7 @@ "Failed to delete column": "Impossibile eliminare la colonna", "The column already exists": "IT_La colonne existe déjà", "MISSING_VALUES": "Valori mancanti", - "CANT_CONNECT_TO_DATABASE": "Impossibile connettersi al database" + "CANT_CONNECT_TO_DATABASE": "Impossibile connettersi al database", + "Poll id already used": "IT_L'identifiant est déjà utilisé" } } \ No newline at end of file diff --git a/tpl/create_poll.tpl b/tpl/create_poll.tpl index 9b576c2..e8fba49 100644 --- a/tpl/create_poll.tpl +++ b/tpl/create_poll.tpl @@ -34,7 +34,7 @@ {/if}
- +
From a10220642ef5d7e28ec8554d2ea41edf62f7fe40 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Sat, 5 Dec 2015 19:30:10 +0100 Subject: [PATCH 12/35] UrlNaming - Update htaccess example --- htaccess.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htaccess.txt b/htaccess.txt index 640cb13..dca4213 100644 --- a/htaccess.txt +++ b/htaccess.txt @@ -8,10 +8,10 @@ RewriteCond %{REQUEST_FILENAME} -d RewriteRule . - [L] - RewriteRule ^([a-zA-Z0-9]{16})$ studs.php?poll=$1 [L] - RewriteRule ^([a-zA-Z0-9]{16})/action/([a-zA-Z_-]+)/(.+)$ studs.php?poll=$1&$2=$3 - RewriteRule ^([a-zA-Z0-9]{16})/vote/([a-zA-Z0-9]{16})$ studs.php?poll=$1&vote=$2 - RewriteRule ^([a-zA-Z0-9]{24})/admin$ adminstuds.php?poll=$1 - RewriteRule ^([a-zA-Z0-9]{24})/admin/vote/([a-zA-Z0-9]{16})$ adminstuds.php?poll=$1&vote=$2 - RewriteRule ^([a-zA-Z0-9]{24})/admin/action/([a-zA-Z_-]+)(/(.+))?$ adminstuds.php?poll=$1&$2=$4 + RewriteRule ^([a-zA-Z0-9-]+)$ studs.php?poll=$1 [L] + RewriteRule ^([a-zA-Z0-9-]+)/action/([a-zA-Z_-]+)/(.+)$ studs.php?poll=$1&$2=$3 + RewriteRule ^([a-zA-Z0-9-]+)/vote/([a-zA-Z0-9]{16})$ studs.php?poll=$1&vote=$2 + RewriteRule ^([a-zA-Z0-9-]{24})/admin$ adminstuds.php?poll=$1 + RewriteRule ^([a-zA-Z0-9-]{24})/admin/vote/([a-zA-Z0-9]{16})$ adminstuds.php?poll=$1&vote=$2 + RewriteRule ^([a-zA-Z0-9-]{24})/admin/action/([a-zA-Z_-]+)(/(.+))?$ adminstuds.php?poll=$1&$2=$4 \ No newline at end of file From 68231333220cc4f412da5a6b9660160cfc6dcb59 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Sat, 5 Dec 2015 21:19:59 +0100 Subject: [PATCH 13/35] Update Framadate version number --- app/inc/constants.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/inc/constants.php b/app/inc/constants.php index 166b21b..3d24af2 100644 --- a/app/inc/constants.php +++ b/app/inc/constants.php @@ -18,7 +18,7 @@ */ // FRAMADATE version -const VERSION = '0.9'; +const VERSION = '1.0'; // Regex const POLL_REGEX = '/^[a-z0-9]+$/i'; From 0c5f623ce05ddbe25e9a77cfdf9d75872b9f7423 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Sun, 6 Dec 2015 03:21:04 +0100 Subject: [PATCH 14/35] Fixes #102 - Increase the number of moments available to 99 per date --- js/app/date_poll.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/app/date_poll.js b/js/app/date_poll.js index 6e894d2..a570ce4 100644 --- a/js/app/date_poll.js +++ b/js/app/date_poll.js @@ -110,11 +110,11 @@ $(document).ready(function () { '
'; // After 11 + button is disable - if (hj < 10) { + if (hj < 99) { last_hour.after(new_hour_html); $('#d' + di + '-h' + (hj + 1)).focus(); $(this).prev('.remove-an-hour').removeClass('disabled'); - if (hj == 9) { + if (hj == 98) { $(this).addClass('disabled'); } } From a4ff2aaaa6988578b0a70d27984365bbdd626542 Mon Sep 17 00:00:00 2001 From: Olivier Perez Date: Mon, 7 Dec 2015 10:35:06 +0100 Subject: [PATCH 15/35] Standardization of regex format --- app/inc/constants.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/inc/constants.php b/app/inc/constants.php index 43a1fc4..e68ca93 100644 --- a/app/inc/constants.php +++ b/app/inc/constants.php @@ -22,11 +22,11 @@ const VERSION = '0.9'; // Regex const POLL_REGEX = '/^[a-z0-9-]*$/i'; -const ADMIN_POLL_REGEX = '/^[\w\d]{24}$/i'; +const ADMIN_POLL_REGEX = '/^[a-z0-9]{24}$/i'; const CHOICE_REGEX = '/^[012]$/'; const BOOLEAN_REGEX = '/^(on|off|true|false|1|0)$/i'; const BOOLEAN_TRUE_REGEX = '/^(on|true|1)$/i'; const EDITABLE_CHOICE_REGEX = '/^[0-2]$/'; // CSRF (300s = 5min) -const TOKEN_TIME = 300; +const TOKEN_TIME = 300; \ No newline at end of file From 128b5f5dd3f69af7d2641d8bf2c1e131469215f2 Mon Sep 17 00:00:00 2001 From: Olivier Perez Date: Mon, 7 Dec 2015 13:57:29 +0100 Subject: [PATCH 16/35] Fix slots/votes/comments selection for granted users --- studs.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/studs.php b/studs.php index 459ebba..7311efa 100644 --- a/studs.php +++ b/studs.php @@ -178,7 +178,7 @@ if ($accessGranted) { } // Retrieve data -if ($resultPubliclyVisible) { +if ($resultPubliclyVisible || $accessGranted) { $slots = $pollService->allSlotsByPoll($poll); $votes = $pollService->allVotesByPollId($poll_id); $comments = $pollService->allCommentsByPollId($poll_id); From cb0e74fba8df9d1ee1e57604ce003a5f9c186f70 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Tue, 8 Dec 2015 00:12:20 +0100 Subject: [PATCH 17/35] Fixes #124 - vote deletion --- adminstuds.php | 4 ++-- app/inc/constants.php | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/adminstuds.php b/adminstuds.php index b9497dd..d09b218 100644 --- a/adminstuds.php +++ b/adminstuds.php @@ -245,9 +245,9 @@ if (!empty($_POST['save'])) { // Save edition of an old vote // ------------------------------- if (!empty($_GET['delete_vote'])) { - $vote_id = filter_input(INPUT_GET, 'delete_vote', FILTER_VALIDATE_INT); + $vote_id = filter_input(INPUT_GET, 'delete_vote', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BASE64_REGEX]]); $vote_id = Utils::base64url_decode($vote_id); - if ($adminPollService->deleteVote($poll_id, $vote_id)) { + if ($vote_id && $adminPollService->deleteVote($poll_id, $vote_id)) { $message = new Message('success', __('adminstuds', 'Vote deleted')); } else { $message = new Message('danger', __('Error', 'Failed to delete the vote')); diff --git a/app/inc/constants.php b/app/inc/constants.php index 166b21b..227b129 100644 --- a/app/inc/constants.php +++ b/app/inc/constants.php @@ -26,6 +26,7 @@ const CHOICE_REGEX = '/^[012]$/'; const BOOLEAN_REGEX = '/^(on|off|true|false|1|0)$/i'; const BOOLEAN_TRUE_REGEX = '/^(on|true|1)$/i'; const EDITABLE_CHOICE_REGEX = '/^[0-2]$/'; +const BASE64_REGEX = '/^[A-Za-z0-9]+$/'; // CSRF (300s = 5min) const TOKEN_TIME = 300; From c6f3b9b527563d9d8b9ac8c030c3362b376853c2 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Tue, 8 Dec 2015 00:16:32 +0100 Subject: [PATCH 18/35] Fill "action" attribute in comments form --- tpl/part/comments.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tpl/part/comments.tpl b/tpl/part/comments.tpl index c25adf2..bc7453b 100644 --- a/tpl/part/comments.tpl +++ b/tpl/part/comments.tpl @@ -1,5 +1,5 @@ -
+ {* Comment list *} From 310aa596cccaecb0b601df81fcd904330c6c4466 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Tue, 8 Dec 2015 00:19:17 +0100 Subject: [PATCH 19/35] Fix missing key --- adminstuds.php | 2 +- locale/de.json | 1 + locale/en.json | 1 + locale/es.json | 1 + locale/fr.json | 1 + locale/it.json | 1 + 6 files changed, 6 insertions(+), 1 deletion(-) diff --git a/adminstuds.php b/adminstuds.php index d09b218..871812b 100644 --- a/adminstuds.php +++ b/adminstuds.php @@ -250,7 +250,7 @@ if (!empty($_GET['delete_vote'])) { if ($vote_id && $adminPollService->deleteVote($poll_id, $vote_id)) { $message = new Message('success', __('adminstuds', 'Vote deleted')); } else { - $message = new Message('danger', __('Error', 'Failed to delete the vote')); + $message = new Message('danger', __('Error', 'Failed to delete the vote!')); } } diff --git a/locale/de.json b/locale/de.json index 0096ec0..e3f0b07 100644 --- a/locale/de.json +++ b/locale/de.json @@ -328,6 +328,7 @@ "The name you've chosen already exist in this poll!": "Der von Ihnen eingegebenen Name existiert schon in dieser Umfrage", "Enter a name and a comment!": "Geben Sie einen Namen und ein Kommentar ein!", "Failed to insert the comment!": "Einfügen des Kommentars gescheitert!", + "Failed to delete the vote!": "DE_Échec de la suppression du vote !", "Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "Framadate ist nicht richtig installiert. Bevor Sie fortfahren, beachten Sie bitte die Angaben zum Aufsetzen der Datenbank in \"INSTALL\".", "Failed to save poll": "Speichern der Umfrage fehlgeschlagen", "Update vote failed": "Aktualisierung der Wertung fehlgeschlagen", diff --git a/locale/en.json b/locale/en.json index 756caa6..d70604d 100644 --- a/locale/en.json +++ b/locale/en.json @@ -328,6 +328,7 @@ "The name you've chosen already exist in this poll!": "The name you've chosen already exists in this poll!", "Enter a name and a comment!": "Enter a name and a comment!", "Failed to insert the comment!": "Failed to insert the comment!", + "Failed to delete the vote!": "Failed to delete the vote!", "Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "Framadate is not properly installed, please see the 'INSTALL' file for instructions on setting up the database before continuing.", "Failed to save poll": "Failed to save poll", "Update vote failed": "Update vote failed", diff --git a/locale/es.json b/locale/es.json index 36ab06c..e6fed3f 100644 --- a/locale/es.json +++ b/locale/es.json @@ -328,6 +328,7 @@ "The name you've chosen already exist in this poll!": "El nombre entrado existe ya!", "Enter a name and a comment!": "Introduzca su nombre y un comentario!", "Failed to insert the comment!": "ES_Échec à l'insertion du commentaire !", + "Failed to delete the vote!": "ES_Échec de la suppression du vote !", "Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "ES_Framadate n'est pas installé correctement, lisez le fichier INSTALL pour configurer la base de données avant de continuer.", "Failed to save poll": "ES_Echec de la sauvegarde du sondage", "Update vote failed": "ES_Mise à jour du vote échoué", diff --git a/locale/fr.json b/locale/fr.json index 57a20ad..4a5ce6c 100644 --- a/locale/fr.json +++ b/locale/fr.json @@ -343,6 +343,7 @@ "The name you've chosen already exist in this poll!": "Le nom que vous avez choisi existe déjà !", "Enter a name and a comment!": "Merci de remplir les deux champs !", "Failed to insert the comment!": "Échec à l'insertion du commentaire !", + "Failed to delete the vote!": "Échec de la suppression du vote !", "Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "Framadate n'est pas installé correctement, lisez le fichier INSTALL pour configurer la base de données avant de continuer.", "Failed to save poll": "Echec de la sauvegarde du sondage", "Update vote failed": "Mise à jour du vote échoué", diff --git a/locale/it.json b/locale/it.json index 573665a..a34bc4e 100644 --- a/locale/it.json +++ b/locale/it.json @@ -328,6 +328,7 @@ "The name you've chosen already exist in this poll!": "Il nome che avete scelto esiste già !", "Enter a name and a comment!": "Inserire un nome e un commento!", "Failed to insert the comment!": "Errore nell'inserimento del commento !", + "Failed to delete the vote!": "IT_Échec de la suppression du vote !", "Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "Framadate non è installato correttamente, leggete la cartella INSTALL per configurare il database prima di continuare.", "Failed to save poll": "Errore nel salvataggio del sondaggio", "Update vote failed": "Aggiornamento del voto fallito", From 3fc25c0c4a2d085e4a08e4db4e2954433b0f9184 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Tue, 8 Dec 2015 22:53:51 +0100 Subject: [PATCH 20/35] Can't vote if admin made some changes on slots --- adminstuds.php | 35 ++++++++---- .../Exception/AlreadyExistsException.php | 9 +++ .../Exception/ConcurrentEditionException.php | 9 +++ .../Framadate/Services/InputService.php | 4 ++ .../Framadate/Services/PollService.php | 43 +++++++++++++-- app/inc/constants.php | 1 + locale/de.json | 2 + locale/en.json | 2 + locale/es.json | 2 + locale/fr.json | 2 + locale/it.json | 2 + studs.php | 55 ++++++++++++------- tpl/part/vote_table_classic.tpl | 1 + tpl/part/vote_table_date.tpl | 1 + 14 files changed, 134 insertions(+), 34 deletions(-) create mode 100644 app/classes/Framadate/Exception/AlreadyExistsException.php create mode 100644 app/classes/Framadate/Exception/ConcurrentEditionException.php diff --git a/adminstuds.php b/adminstuds.php index 871812b..0c74ed4 100644 --- a/adminstuds.php +++ b/adminstuds.php @@ -17,6 +17,8 @@ * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) */ use Framadate\Editable; +use Framadate\Exception\AlreadyExistsException; +use Framadate\Exception\ConcurrentEditionException; use Framadate\Exception\MomentAlreadyExistsException; use Framadate\Message; use Framadate\Services\AdminPollService; @@ -201,6 +203,7 @@ if (!empty($_POST['save'])) { // Save edition of an old vote $name = $inputService->filterName($_POST['name']); $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']); if (empty($editedVote)) { $message = new Message('danger', __('Error', 'Something is going wrong...')); @@ -211,16 +214,21 @@ if (!empty($_POST['save'])) { // Save edition of an old vote if ($message == null) { // Update vote - $result = $pollService->updateVote($poll_id, $editedVote, $name, $choices); - if ($result) { - $message = new Message('success', __('adminstuds', 'Vote updated')); - } else { - $message = new Message('danger', __('Error', 'Update vote failed')); + try { + $result = $pollService->updateVote($poll_id, $editedVote, $name, $choices, $slots_hash); + if ($result) { + $message = new Message('success', __('adminstuds', 'Vote updated')); + } else { + $message = new Message('danger', __('Error', 'Update vote failed')); + } + } catch (ConcurrentEditionException $cee) { + $message = new Message('danger', __('Error', 'Poll has been updated before you vote')); } } } elseif (isset($_POST['save'])) { // Add a new vote $name = $inputService->filterName($_POST['name']); $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]); + $slots_hash = $inputService->filterMD5($_POST['control']); if ($name == null) { $message = new Message('danger', __('Error', 'The name is invalid.')); @@ -231,11 +239,17 @@ if (!empty($_POST['save'])) { // Save edition of an old vote if ($message == null) { // Add vote - $result = $pollService->addVote($poll_id, $name, $choices); - if ($result) { - $message = new Message('success', __('adminstuds', 'Vote added')); - } else { - $message = new Message('danger', __('Error', 'Adding vote failed')); + try { + $result = $pollService->addVote($poll_id, $name, $choices, $slots_hash); + if ($result) { + $message = new Message('success', __('adminstuds', 'Vote added')); + } else { + $message = new Message('danger', __('Error', 'Adding vote failed')); + } + } catch (AlreadyExistsException $aee) { + $message = new Message('danger', __('Error', 'You already voted')); + } catch (ConcurrentEditionException $cee) { + $message = new Message('danger', __('Error', 'Poll has been updated before you vote')); } } } @@ -428,6 +442,7 @@ $smarty->assign('title', __('Generic', 'Poll') . ' - ' . $poll->title); $smarty->assign('expired', strtotime($poll->end_date) < time()); $smarty->assign('deletion_date', strtotime($poll->end_date) + PURGE_DELAY * 86400); $smarty->assign('slots', $poll->format === 'D' ? $pollService->splitSlots($slots) : $slots); +$smarty->assign('slots_hash', $pollService->hashSlots($slots)); $smarty->assign('votes', $pollService->splitVotes($votes)); $smarty->assign('best_choices', $pollService->computeBestChoices($votes)); $smarty->assign('comments', $comments); diff --git a/app/classes/Framadate/Exception/AlreadyExistsException.php b/app/classes/Framadate/Exception/AlreadyExistsException.php new file mode 100644 index 0000000..510b798 --- /dev/null +++ b/app/classes/Framadate/Exception/AlreadyExistsException.php @@ -0,0 +1,9 @@ + ['regexp' => MD5_REGEX]]); + } + 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 a666041..fa2ab46 100644 --- a/app/classes/Framadate/Services/PollService.php +++ b/app/classes/Framadate/Services/PollService.php @@ -18,10 +18,13 @@ */ namespace Framadate\Services; +use Framadate\Exception\AlreadyExistsException; +use Framadate\Exception\ConcurrentEditionException; use Framadate\Form; use Framadate\FramaDB; use Framadate\Repositories\RepositoryFactory; use Framadate\Security\Token; +use Framadate\Utils; class PollService { @@ -82,17 +85,25 @@ class PollService { return $slots; } - public function updateVote($poll_id, $vote_id, $name, $choices) { - $choices = implode($choices); + public function updateVote($poll_id, $vote_id, $name, $choices, $slots_hash) { + // Check if slots are still the same + $this->checkThatSlotsDidntChanged($poll_id, $slots_hash); + // Update vote + $choices = implode($choices); return $this->voteRepository->update($poll_id, $vote_id, $name, $choices); } - function addVote($poll_id, $name, $choices) { + function addVote($poll_id, $name, $choices, $slots_hash) { + // Check if slots are still the same + $this->checkThatSlotsDidntChanged($poll_id, $slots_hash); + + // Check if vote already exists if ($this->voteRepository->existsByPollIdAndName($poll_id, $name)) { - return false; + throw new AlreadyExistsException(); } + // Insert new vote $choices = implode($choices); $token = $this->random(16); return $this->voteRepository->insert($poll_id, $name, $choices, $token); @@ -167,6 +178,16 @@ class PollService { return $splitted; } + /** + * @param $slots array The slots to hash + * @return string The hash + */ + public function hashSlots($slots) { + return md5(array_reduce($slots, function($carry, $item) { + return $carry . $item->id . '@' . $item->moments . ';'; + })); + } + function splitVotes($votes) { $splitted = array(); foreach ($votes as $vote) { @@ -201,4 +222,18 @@ class PollService { return time() + 86400; } + /** + * This method checks if the hash send by the user is the same as the computed hash. + * + * @param $poll_id int The id of the poll + * @param $slots_hash string The hash sent by the user + * @throws ConcurrentEditionException Thrown when hashes are differents + */ + private function checkThatSlotsDidntChanged($poll_id, $slots_hash) { + $slots = $this->slotRepository->listByPollId($poll_id); + if ($slots_hash !== $this->hashSlots($slots)) { + throw new ConcurrentEditionException(); + } + } + } diff --git a/app/inc/constants.php b/app/inc/constants.php index 227b129..2aaecaa 100644 --- a/app/inc/constants.php +++ b/app/inc/constants.php @@ -27,6 +27,7 @@ const BOOLEAN_REGEX = '/^(on|off|true|false|1|0)$/i'; const BOOLEAN_TRUE_REGEX = '/^(on|true|1)$/i'; const EDITABLE_CHOICE_REGEX = '/^[0-2]$/'; const BASE64_REGEX = '/^[A-Za-z0-9]+$/'; +const MD5_REGEX = '/^[A-Fa-f0-9]+$/'; // CSRF (300s = 5min) const TOKEN_TIME = 300; diff --git a/locale/de.json b/locale/de.json index e3f0b07..9dd9a09 100644 --- a/locale/de.json +++ b/locale/de.json @@ -333,6 +333,8 @@ "Failed to save poll": "Speichern der Umfrage fehlgeschlagen", "Update vote failed": "Aktualisierung der Wertung fehlgeschlagen", "Adding vote failed": "Stimmabgabe fehlgeschlagen", + "You already voted": "DE_Vous avez déjà voté", + "Poll has been updated before you vote": "DE_Le sondage a été mis à jour avant votre vote", "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 d70604d..02b1781 100644 --- a/locale/en.json +++ b/locale/en.json @@ -333,6 +333,8 @@ "Failed to save poll": "Failed to save poll", "Update vote failed": "Update vote failed", "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", "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 e6fed3f..4264b92 100644 --- a/locale/es.json +++ b/locale/es.json @@ -333,6 +333,8 @@ "Failed to save poll": "ES_Echec de la sauvegarde du sondage", "Update vote failed": "ES_Mise à jour du vote échoué", "Adding vote failed": "ES_Ajout d'un vote échoué", + "You already voted": "ES_Vous avez déjà voté", + "Poll has been updated before you vote": "ES_Le sondage a été mis à jour avant votre vote", "Comment failed": "ES_Commentaire échoué", "You can't create a poll with hidden results with the following edition option:": "ES_Vous ne pouvez pas créer de sondage avec résulats cachés avec les options d'éditions suivantes : ", "Failed to delete column": "Error al eliminar la columna", diff --git a/locale/fr.json b/locale/fr.json index 4a5ce6c..1c3381a 100644 --- a/locale/fr.json +++ b/locale/fr.json @@ -348,6 +348,8 @@ "Failed to save poll": "Echec de la sauvegarde du sondage", "Update vote failed": "Mise à jour du vote échoué", "Adding vote failed": "Ajout d'un vote échoué", + "You already voted": "Vous avez déjà voté", + "Poll has been updated before you vote": "Le sondage a été mis à jour avant votre vote", "Comment failed": "Commentaire échoué", "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'éditions suivantes : ", "Failed to delete column": "Échec de la suppression de colonne", diff --git a/locale/it.json b/locale/it.json index a34bc4e..3942846 100644 --- a/locale/it.json +++ b/locale/it.json @@ -333,6 +333,8 @@ "Failed to save poll": "Errore nel salvataggio del sondaggio", "Update vote failed": "Aggiornamento del voto fallito", "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", "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/studs.php b/studs.php index 6a57efb..8816394 100644 --- a/studs.php +++ b/studs.php @@ -16,6 +16,8 @@ * Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) */ +use Framadate\Exception\AlreadyExistsException; +use Framadate\Exception\ConcurrentEditionException; use Framadate\Services\LogService; use Framadate\Services\PollService; use Framadate\Services\InputService; @@ -121,6 +123,7 @@ if (!empty($_POST['save'])) { // Save edition of an old vote $name = $inputService->filterName($_POST['name']); $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']); if (empty($editedVote)) { $message = new Message('danger', __('Error', 'Something is going wrong...')); @@ -131,23 +134,28 @@ if (!empty($_POST['save'])) { // Save edition of an old vote if ($message == null) { // Update vote - $result = $pollService->updateVote($poll_id, $editedVote, $name, $choices); - if ($result) { - if ($poll->editable == Editable::EDITABLE_BY_OWN) { - $editedVoteUniqueId = filter_input(INPUT_POST, 'edited_vote', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); - $urlEditVote = Utils::getUrlSondage($poll_id, false, $editedVoteUniqueId); - $message = new Message('success', __('studs', '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:'), $urlEditVote); + try { + $result = $pollService->updateVote($poll_id, $editedVote, $name, $choices, $slots_hash); + if ($result) { + if ($poll->editable == Editable::EDITABLE_BY_OWN) { + $editedVoteUniqueId = filter_input(INPUT_POST, 'edited_vote', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); + $urlEditVote = Utils::getUrlSondage($poll_id, false, $editedVoteUniqueId); + $message = new Message('success', __('studs', '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:'), $urlEditVote); + } else { + $message = new Message('success', __('studs', 'Update vote succeeded')); + } + sendUpdateNotification($poll, $mailService, $name, UPDATE_VOTE); } else { - $message = new Message('success', __('studs', 'Update vote succeeded')); + $message = new Message('danger', __('Error', 'Update vote failed')); } - sendUpdateNotification($poll, $mailService, $name, UPDATE_VOTE); - } else { - $message = new Message('danger', __('Error', 'Update vote failed')); + } catch (ConcurrentEditionException $cee) { + $message = new Message('danger', __('Error', 'Poll has been updated before you vote')); } } } elseif (isset($_POST['save'])) { // Add a new vote $name = $inputService->filterName($_POST['name']); $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]); + $slots_hash = $inputService->filterMD5($_POST['control']); if ($name == null) { $message = new Message('danger', __('Error', 'The name is invalid.')); @@ -158,18 +166,24 @@ if (!empty($_POST['save'])) { // Save edition of an old vote if ($message == null) { // Add vote - $result = $pollService->addVote($poll_id, $name, $choices); - if ($result) { - if ($poll->editable == Editable::EDITABLE_BY_OWN) { - $urlEditVote = Utils::getUrlSondage($poll_id, false, $result->uniqId); - $editedVoteUniqueId = $result->uniqId; - $message = new Message('success', __('studs', '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:'), $urlEditVote); + try { + $result = $pollService->addVote($poll_id, $name, $choices, $slots_hash); + if ($result) { + if ($poll->editable == Editable::EDITABLE_BY_OWN) { + $urlEditVote = Utils::getUrlSondage($poll_id, false, $result->uniqId); + $editedVoteUniqueId = $result->uniqId; + $message = new Message('success', __('studs', '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:'), $urlEditVote); + } else { + $message = new Message('success', __('studs', 'Adding the vote succeeded')); + } + sendUpdateNotification($poll, $mailService, $name, ADD_VOTE); } else { - $message = new Message('success', __('studs', 'Adding the vote succeeded')); + $message = new Message('danger', __('Error', 'Adding vote failed')); } - sendUpdateNotification($poll, $mailService, $name, ADD_VOTE); - } else { - $message = new Message('danger', __('Error', 'Adding vote failed')); + } catch (AlreadyExistsException $aee) { + $message = new Message('danger', __('Error', 'You already voted')); + } catch (ConcurrentEditionException $cee) { + $message = new Message('danger', __('Error', 'Poll has been updated before you vote')); } } } @@ -211,6 +225,7 @@ $smarty->assign('title', __('Generic', 'Poll') . ' - ' . $poll->title); $smarty->assign('expired', strtotime($poll->end_date) < time()); $smarty->assign('deletion_date', strtotime($poll->end_date) + PURGE_DELAY * 86400); $smarty->assign('slots', $poll->format === 'D' ? $pollService->splitSlots($slots) : $slots); +$smarty->assign('slots_hash', $pollService->hashSlots($slots)); $smarty->assign('votes', $pollService->splitVotes($votes)); $smarty->assign('best_choices', $pollService->computeBestChoices($votes)); $smarty->assign('comments', $comments); diff --git a/tpl/part/vote_table_classic.tpl b/tpl/part/vote_table_classic.tpl index c321cc0..b297982 100644 --- a/tpl/part/vote_table_classic.tpl +++ b/tpl/part/vote_table_classic.tpl @@ -6,6 +6,7 @@
+ diff --git a/tpl/part/vote_table_date.tpl b/tpl/part/vote_table_date.tpl index 03ad351..2f5145f 100644 --- a/tpl/part/vote_table_date.tpl +++ b/tpl/part/vote_table_date.tpl @@ -7,6 +7,7 @@
+
{__('Poll results', 'Votes of the poll')} {$poll->title|html}
From 2109ef3469f00a630ddaf4c527ef532340f7c249 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Wed, 6 Jan 2016 19:38:19 +0100 Subject: [PATCH 21/35] More precision on MD5 regex --- app/inc/constants.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/inc/constants.php b/app/inc/constants.php index 2aaecaa..d82a95e 100644 --- a/app/inc/constants.php +++ b/app/inc/constants.php @@ -27,7 +27,7 @@ const BOOLEAN_REGEX = '/^(on|off|true|false|1|0)$/i'; const BOOLEAN_TRUE_REGEX = '/^(on|true|1)$/i'; const EDITABLE_CHOICE_REGEX = '/^[0-2]$/'; const BASE64_REGEX = '/^[A-Za-z0-9]+$/'; -const MD5_REGEX = '/^[A-Fa-f0-9]+$/'; +const MD5_REGEX = '/^[A-Fa-f0-9]{32}$/'; // CSRF (300s = 5min) const TOKEN_TIME = 300; From 510b797f853bb1af476b3da9dd4b1af615c90629 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Tue, 19 Jan 2016 22:28:34 +0100 Subject: [PATCH 22/35] Check if current user is admin BEFORE check editedVoteUniqueId --- tpl/part/vote_table_classic.tpl | 2 +- tpl/part/vote_table_date.tpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tpl/part/vote_table_classic.tpl b/tpl/part/vote_table_classic.tpl index b297982..e1feac7 100644 --- a/tpl/part/vote_table_classic.tpl +++ b/tpl/part/vote_table_classic.tpl @@ -98,8 +98,8 @@ {if $active && !$expired && ( $poll->editable == constant('Framadate\Editable::EDITABLE_BY_ALL') - or ($poll->editable == constant('Framadate\Editable::EDITABLE_BY_OWN') && $editedVoteUniqueId == $vote->uniqId) or $admin + or ($poll->editable == constant('Framadate\Editable::EDITABLE_BY_OWN') && $editedVoteUniqueId == $vote->uniqId) ) } diff --git a/tpl/part/vote_table_date.tpl b/tpl/part/vote_table_date.tpl index 2f5145f..762f2b7 100644 --- a/tpl/part/vote_table_date.tpl +++ b/tpl/part/vote_table_date.tpl @@ -149,8 +149,8 @@ {if $active && !$expired && ( $poll->editable == constant('Framadate\Editable::EDITABLE_BY_ALL') - or ($poll->editable == constant('Framadate\Editable::EDITABLE_BY_OWN') && $editedVoteUniqueId == $vote->uniqId) or $admin + or ($poll->editable == constant('Framadate\Editable::EDITABLE_BY_OWN') && $editedVoteUniqueId == $vote->uniqId) ) }
{__('Poll results', 'Votes of the poll')} {$poll->title|html}
From 7d9a1140a430d01cd10062d36668d9be52d22b9e Mon Sep 17 00:00:00 2001 From: Vincent Gatignol-Jamon Date: Thu, 4 Feb 2016 15:20:35 +0100 Subject: [PATCH 23/35] add missing translation : ref #127 --- locale/de.json | 6 +++++- locale/en.json | 6 +++++- locale/es.json | 6 +++++- locale/fr.json | 6 +++++- locale/it.json | 8 ++++++-- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/locale/de.json b/locale/de.json index e3f0b07..8b7577c 100644 --- a/locale/de.json +++ b/locale/de.json @@ -252,7 +252,9 @@ "Create the poll": "Umfrage erstellen", "Your poll will be automatically archived in %d days.": "Ihre Umfrage wird automatisch in %d Tage archiviert werden.", "You can set a closer archiving date for it.": "Sie können das Datum der Archivierung vorverlegen.", - "Archiving date:": "Tag der Archivierung:" + "Archiving date:": "Tag der Archivierung:", + "Your poll will automatically be archived": "DE_Your poll will automatically be archived", + "after the last date of your poll.": "DE_after the last date of your poll." }, "Admin": { "Back to administration": "Zurück zur Verwaltung", @@ -333,6 +335,8 @@ "Failed to save poll": "Speichern der Umfrage fehlgeschlagen", "Update vote failed": "Aktualisierung der Wertung fehlgeschlagen", "Adding vote failed": "Stimmabgabe fehlgeschlagen", + "You already voted": "DE_Vous avez déjà voté", + "Poll has been updated before you vote": "DE_Le sondage a été mis à jour avant votre vote", "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 d70604d..0d8dd59 100644 --- a/locale/en.json +++ b/locale/en.json @@ -252,7 +252,9 @@ "Create the poll": "Create the poll", "Your poll will be automatically archived in %d days.": "Your poll will be automatically archived in %d days.", "You can set a closer archiving date for it.": "You can set a specific expiry date for the poll.", - "Archiving date:": "Expiry date:" + "Archiving date:": "Expiry date:", + "Your poll will automatically be archived": "Your poll will automatically be archived", + "after the last date of your poll.": "after the last date of your poll." }, "Admin": { "Back to administration": "Back to administration", @@ -333,6 +335,8 @@ "Failed to save poll": "Failed to save poll", "Update vote failed": "Update vote failed", "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", "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 e6fed3f..e10eeb0 100644 --- a/locale/es.json +++ b/locale/es.json @@ -252,7 +252,9 @@ "Create the poll": "Crear la encuesta", "Your poll will be automatically archived in %d days.": "ES_Votre sondage sera automatiquement archivé dans %d jours.", "You can set a closer archiving date for it.": "ES_Vous pouvez décider d'une date d'archivage plus proche.", - "Archiving date:": "ES_Date d'archivage :" + "Archiving date:": "ES_Date d'archivage :", + "Your poll will automatically be archived": "ES_Your poll will automatically be archived", + "after the last date of your poll.": "ES_after the last date of your poll." }, "Admin": { "Back to administration": "ES_Retour à l'administration", @@ -333,6 +335,8 @@ "Failed to save poll": "ES_Echec de la sauvegarde du sondage", "Update vote failed": "ES_Mise à jour du vote échoué", "Adding vote failed": "ES_Ajout d'un vote échoué", + "You already voted": "ES_Vous avez déjà voté", + "Poll has been updated before you vote": "ES_Le sondage a été mis à jour avant votre vote", "Comment failed": "ES_Commentaire échoué", "You can't create a poll with hidden results with the following edition option:": "ES_Vous ne pouvez pas créer de sondage avec résulats cachés avec les options d'éditions suivantes : ", "Failed to delete column": "Error al eliminar la columna", diff --git a/locale/fr.json b/locale/fr.json index 4a5ce6c..f1683ee 100644 --- a/locale/fr.json +++ b/locale/fr.json @@ -252,7 +252,9 @@ "Create the poll": "Créer le sondage", "Your poll will be automatically archived in %d days.": "Votre sondage sera automatiquement archivé dans %d jours.", "You can set a closer archiving date for it.": "Vous pouvez décider d'une date d'archivage plus proche.", - "Archiving date:": "Date d'archivage :" + "Archiving date:": "Date d'archivage :", + "Your poll will automatically be archived": "Votre sondage sera automatiquement archivé", + "after the last date of your poll.": "après le dernier jour de votre sondage." }, "Admin": { "Back to administration": "Retour à l'administration", @@ -348,6 +350,8 @@ "Failed to save poll": "Echec de la sauvegarde du sondage", "Update vote failed": "Mise à jour du vote échoué", "Adding vote failed": "Ajout d'un vote échoué", + "You already voted": "Vous avez déjà voté", + "Poll has been updated before you vote": "Le sondage a été mis à jour avant votre vote", "Comment failed": "Commentaire échoué", "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'éditions suivantes : ", "Failed to delete column": "Échec de la suppression de colonne", diff --git a/locale/it.json b/locale/it.json index a34bc4e..01b616b 100644 --- a/locale/it.json +++ b/locale/it.json @@ -252,7 +252,9 @@ "Create the poll": "Creare il sondaggio", "Your poll will be automatically archived in %d days.": "Il vostro sondaggio verrà archiviata automaticamente in %d giorni.", "You can set a closer archiving date for it.": "Si può decidere su una data più vicina di archiviazione.", - "Archiving date:": "Archivio Data:" + "Archiving date:": "Archivio Data:", + "Your poll will automatically be archived": "IT_Your poll will automatically be archived", + "after the last date of your poll.": "IT_after the last date of your poll." }, "Admin": { "Back to administration": "Ritorna all'amministrazione", @@ -333,6 +335,8 @@ "Failed to save poll": "Errore nel salvataggio del sondaggio", "Update vote failed": "Aggiornamento del voto fallito", "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", "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", @@ -340,4 +344,4 @@ "MISSING_VALUES": "Valori mancanti", "CANT_CONNECT_TO_DATABASE": "Impossibile connettersi al database" } -} \ No newline at end of file +} From d537d5028c66ac12f6c60520746305b00f2944d1 Mon Sep 17 00:00:00 2001 From: Quentin Date: Fri, 12 Feb 2016 17:27:15 +0100 Subject: [PATCH 24/35] Added the Occitan version --- locale/oc.json | 362 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 362 insertions(+) create mode 100644 locale/oc.json diff --git a/locale/oc.json b/locale/oc.json new file mode 100644 index 0000000..060460b --- /dev/null +++ b/locale/oc.json @@ -0,0 +1,362 @@ +{ + "Generic": { + "Make your polls": "Organizar de rencontres simplament, liurament", + "Home": "Acuèlh", + "Poll": "Sondage", + "Save": "Enregistrar", + "Cancel": "Annllar", + "Add": "Apondre", + "Remove": "Suprimir", + "Validate": "Validar", + "Edit": "Modificar", + "Next": "Contunhar", + "Back": "Tornar", + "Close": "Tampar", + "Your name": "Vòstre nom", + "Your email address": "Vòstre adreça", + "(in the format name@mail.com)": "(al format nom@mail.com)", + "Description": "Descripcion", + "Back to the homepage of": "Tornar a la pagina d'acuèlh de", + "days": "jors", + "months": "meses", + "Day": "Jor", + "Time": "Ora", + "with": "amb", + "vote": "vote", + "votes": "votes", + "for": "per", + "Yes": "Òc", + "Ifneedbe": "Se cal", + "No": "Non", + "Legend:": "Légende :", + "Date": "Data", + "Classic": "Classic", + "Page generated in": "Pagina generada en", + "seconds": "segondas", + "Choice": "Causida", + "Link": "Ligam", + "Search": "Cercar", + "Creation date:": "Data de creacion :", + "ASTERISK": "*" + }, + "Date": { + "dd/mm/yyyy": "jj/mm/aaaa", + "%A, den %e. %B %Y": "%A %e %B %Y", + "FULL": "%A %e %B %Y", + "SHORT": "%A %e %B %Y", + "DAY": "%a %e", + "DATE": "%Y-%m-%d", + "MONTH_YEAR": "%B %Y" + }, + "Language selector": { + "Select the language": "Triar la lengar", + "Change the language": "Cambiar la lenga" + }, + "Homepage": { + "Schedule an event": "Crear un sondatge especial datas", + "Make a classic poll": "Crear un sondatge classic", + "Where are my polls": "Ont son mos sondatges ?" + }, + "Maintenance": { + "The application": "L'aplicacion", + "is currently under maintenance.": "es en mantenença.", + "Thank you for your understanding.": "Mercés de tornar dins un momenton." + }, + "1st section": { + "What is that?": "Primièrs passes", + "Framadate is an online service for planning an appointment or make a decision quickly and easily. No registration is required.": "Framadate es un servici en linha que permet d'organizar un rendètz-vos o de prendre de decisions rapidament e simplament. Cap inscripcion es demandada.", + "Here is how it works:": "Vaquí cossí marcha :", + "Make a poll": "Creatz un sondatge", + "Define dates or subjects to choose": "Determinatz las datas o los tèmas a causir", + "Send the poll link to your friends or colleagues": "Mandatz lo ligam del sondatge a vos amisc o companhs", + "Discuss and make a decision": "Charratz e prenètz vòstra decision", + "Do you want to": "Volètz", + "view an example?": "veire un example ?" + }, + "2nd section": { + "The software": "Lo logicial", + "Framadate was initially based on ": "Framadate es a sa debuta basat sus ", + "a software developed by the University of Strasbourg. Today, it is devevoped by the association Framasoft.": "un logicial desvolopat per l'Universitat d'Estrasborg. Uèi son devolopament es fach per l’associacion Framasoft.", + "This software needs javascript and cookies enabled. It is compatible with the following web browsers:": "Aqueste logicial requerís l’activacion del javascript e dels cookies. Es compatible amb los navigadors web seguents :", + "It is governed by the": "Es regit per la", + "CeCILL-B license": "licéncia CeCILL-B" + }, + "3rd section": { + "Cultivate your garden": "Cultivatz vòstre òrt", + "To participate in the software development, suggest improvements or simply download it, please visit ": "Per participar al devolopament del logicial, prepausar de milhoraments o simplament lo telecargar, anatz sus ", + "the development site": "lo siti de devolopament", + "If you want to install the software for your own use and thus increase your independence, we help you on:": "Se volètz installar aqueste logicial per la vòstra pròpia utilizacion e aital aver mai d'automonia, nos podètz ajudar sus :" + }, + "PollInfo": { + "Remove the poll": "Suprimir lo sondatge", + "Remove all the comments": "Suprimir tots los comentaris", + "Remove all the votes": "Suprimir tots los vòtes", + "Print": "Imprimir", + "Export to CSV": "Exportar en CSV", + "Title": "Títol del sondatge", + "Edit the title": "Modificar l títol", + "Save the new title": "Enregistrar lo nòu títol", + "Cancel the title edit": "Anullar lo cambi de títol", + "Initiator of the poll": "Autor duel sondatge", + "Edit the name": "Modificacion de l'autor", + "Save the new name": "Enregistrar l'autor", + "Cancel the name edit": "Anullar lo cambi d'autor", + "Email": "Adreça", + "Edit the email adress": "Modificar l'adreça", + "Save the email address": "Enregistrar l'adreça", + "Cancel the email address edit": "Anullar lo cambi d'adreça", + "Edit the description": "Modificar la descripcion", + "Save the description": "Enregistrar la descripcion", + "Cancel the description edit": "Anullar lo cambi de descripcion", + "Public link of the poll": "Ligam public del sondatge", + "Admin link of the poll": "Ligam d'administracion del sondatge", + "Expiration date": "Data d'expiracion", + "Edit the expiration date": "Modificar la data d'expiracion", + "Save the new expiration date": "Enregistrar la data d'expiracion", + "Cancel the expiration date edit": "Anullar lo cambi de data d'expiracion", + "Poll rules": "Permissions del sondatge", + "Edit the poll rules": "Modificar las permissions del sondatge", + "Votes and comments are locked": "Los vòtes e comentaris son clavats", + "Votes and comments are open": "Los vòtes e comentaris son doberts", + "Votes are editable": "Los vòtes son modificables", + "Votes are editable solely by their owner.": "Los vòtes son solament modificables per lo creator", + "Save the new rules": "Enregistrar las nòvas permissions", + "Cancel the rules edit": "Anullar lo cambi de permissions", + "Results are hidden.": "Las resultats son amagadas.", + "Results are visible.": "Las resultats son visiblas." + }, + "Poll results": { + "Votes of the poll": "Vòtes del sondatge", + "Edit the line:": "Modificar la linha :", + "Remove the line:": "Suprimir la linha :", + "Vote no for": "Votar « non » per", + "Vote yes for": "Votar « òc » per", + "Vote ifneedbe for": "Votar « Se cal » per", + "Save the choices": "Enregistar las causidas", + "Addition": "Soma", + "Best choice": "Milhora causida", + "Best choices": "Milhoras causidas", + "The best choice at this time is:": "Pel moment, la causida amb lo mai de vòtes es :", + "The bests choices at this time are:": "Pel moment, las causidas amb lo mai de vòtes son :", + "Scroll to the left": "Far desfilar a man esquèrra", + "Scroll to the right": "Far desfilar a man drecha", + "polled user": "votant", + "polled users": "votants", + "Display the chart of the results": "Afichar lo graphic de las resultats", + "Chart": "Graphic" + }, + "Comments": { + "Comments of polled people": "Comentaris dels opinaires", + "Remove the comment": "Suprimir lo comentari", + "Add a comment to the poll": "Apondre un commntari al sondatge", + "Your comment": "Vòstre comentari", + "Send the comment": "Mandar lo comentari", + "anonyme": "anonim", + "Comment added": "Comentari apondut" + }, + "studs": { + "If you want to vote in this poll, you have to give your name, choose the values that fit best for you and validate with the plus button at the end of the line.": "Pour participer à ce sondage, veuillez entrer votre nom, choisir toutes les valeurs qui vous conviennent et valider votre choix avec le bouton en bout de ligne.", + "POLL_LOCKED_WARNING": "L'administrator a clavat aqueste sondatge. Los vòtes e comentaris son gelats, es pus mai possible de participar", + "The poll is expired, it will be deleted soon.": "Lo sondatge a expirat, serà lèu suprimit.", + "Deletion date:": "Data de supression :", + "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:": "Vòstre vòte foguèt ben enregistrat, mas mèfi : aqueste sondatge permet l'edicion de vòstre vòte solament amb lo ligam personalizat seguent ; gardatz-lo preció ! ", + "Update vote succeeded": "Misa a jorn del vòte amb succès", + "Adding the vote succeeded": "Ajust del vòte capitat" + }, + "adminstuds": { + "As poll administrator, you can change all the lines of this poll with this button": "En tant qu'administrateur, vous pouvez modifier toutes les lignes de ce sondage avec ce bouton", + "remove a column or a line with": "effacer une colonne ou une ligne avec", + "and add a new column with": "et si vous avez oublié de saisir un choix, vous pouvez rajouter une colonne en cliquant sur", + "Finally, you can change the informations of this poll like the title, the comments or your email address.": "Vous pouvez enfin également modifier les informations relatives à ce sondage comme le titre, les commentaires ou encore votre courriel.", + "Column's adding": "Ajout de colonne", + "You can add a new scheduling date to your poll.": "Vous pouvez ajouter une date à votre sondage.", + "If you just want to add a new hour to an existant date, put the same date and choose a new hour.": "Si vous voulez juste ajouter un horaire à une date existante, mettez la même date et choisissez un autre horaire. Il sera intégré normalement au sondage existant.", + "Confirm removal of the poll": "Confirmer la suppression du sondage", + "Delete the poll": "Suprimi lo sondatge", + "Keep the poll": "Gardi lo sondatge", + "Your poll has been removed!": "Vòstre sondatge es estat suprimit !", + "Poll saved": "Sondatge salvagardat", + "Poll fully deleted": "Sondatge totalament suprimit", + "Vote added": "Vòte ajustat", + "Vote updated": "Vòte mes a jorn", + "Vote deleted": "Vòte suprimit", + "All votes deleted": "Tots los vòtes son estats suprimits", + "Back to the poll": "Tornar al sondatge", + "Add a column": "Ajustar una colomna", + "Remove the column": "Suprimir la colomna", + "Column removed": "Colomna suprimida", + "Choice added": "Causida ajustada", + "Confirm removal of all votes of the poll": "Confirmar la supression de tots los vòtes d'aqueste sondatge", + "Keep the votes": "Gardar los vòtes", + "Remove the votes": "Suprimir los vòtes", + "Confirm removal of all comments of the poll": "Confirmar la supression de tots los comentaris d'aqueste sondatge", + "Keep the comments": "Gardar los comentaris", + "Remove the comments": "Suprimir los comentaris", + "Comment deleted": "Comentari suprimit", + "All comments deleted": "Tots los comentaris son estats suprimits", + "Keep votes": "Gardar lòs vòtes", + "Keep comments": "Gardar los comentaris", + "Keep this poll": "Gardar aqueste sondatge" + }, + "Step 1": { + "Poll creation (1 on 3)": "Creacion de sondatge (1 sus 3)", + "You are in the poll creation section.": "Avètz causit de crear un nòu sondatge.", + "Required fields cannot be left blank.": "Mercés de garnir tots los formularis obligatòris, marcats amb una *.", + "Poll title": "Títol del sondatge", + "Votes cannot be modified.": "Cap vòte pòt èsser modificat", + "All voters can modify any vote": "Tot lo mond pòt modificar sos vòtes", + "Voters can modify their vote themselves": "Cadun pòt modificar son pròpi vòte", + "To receive an email for each new vote": "Recebre un messatge per cada participacion", + "To receive an email for each new comment": "Recebre un messatge per cada comentari", + "Only the poll maker can see the poll's results": "Solament lo creator del sondatge pòt veire las resultats", + "Go to step 2": "Anar a l'etapa 2" + }, + "Step 2": { + "Back to step 1": "Tornar a l'etapa 1", + "Go to step 3": "Anar a l'etapa 3" + }, + "Step 2 date": { + "Poll dates (2 on 3)": "Causida de las datas (2 sus 3)", + "Choose the dates of your poll": "Triatz las datas de vòstre sondatge", + "To schedule an event you need to propose at least two choices (two hours for one day or two days).": "Per crear un sondatge especial datas vos cal prepausar almens doas causidas (dos oraris per la meteissa jornada o dos jorns).", + "You can add or remove additionnal days and hours with the buttons": "Podètz ajustar o suprimir de jorns e oraris suplementaris amb los botons", + "For each selected day, you can choose, or not, meeting hours (e.g.: \"8h\", \"8:30\", \"8h-10h\", \"evening\", etc.)": "Per cada jorn selectionat avètz la possibilitat de causir o non d'oras de reünion (per exemple : \"8o\", \"8o30\", \"8o-10o\", \"ser\", etc.)", + "Remove an hour": "Suprimir lo darrièr orari", + "Add an hour": "Ajustar un orari", + "Copy hours of the first day": "Reportar los oraris del premièr jorn suls autres jorns", + "Remove a day": "Suprimir lo darrièr jorn", + "Add a day": "Ajustar un jorn", + "Remove all days": "Suprimir tots los jorns", + "Remove all hours": "Suprimir tots los oraris" + }, + "Step 2 classic": { + "Poll subjects (2 on 3)": "Causida dels tèmas (2 sus 3)", + "To make a generic poll you need to propose at least two choices between differents subjects.": "Per crear un sondatge classic, devètz prepausar almens doas causidas diferentas.", + "You can add or remove additional choices with the buttons": "Podètz apondre o suprimir de causidas mai amb los botons", + "It's possible to propose links or images by using": "Es possible d'inserir de ligams o d'imatge n'emplegant ", + "the Markdown syntax": "la sintaxi Markdown", + "Add a link or an image": "Apondre un ligam o un imatge", + "These fields are optional. You can add a link, an image or both.": "Aquestes camps son facultatius. Podètz apondre un ligam, un image o los dos.", + "URL of the image": "URL de l'imatge", + "Alternative text": "Tèxte alternatiu", + "Remove a choice": "Suprimir la darrièra causida", + "Add a choice": "Ajutar una causida" + }, + "Step 3": { + "Back to step 2": "Tornar a l'etapa 2", + "Removal date and confirmation (3 on 3)": "Data d'expiracion e confirmacion (3 sus 3)", + "Confirm the creation of your poll": "Confirmatz la creacion de vòstre sondatge", + "List of your choices": "Lista de vòstras causidas", + "Once you have confirmed the creation of your poll, you will be automatically redirected on the administration page of your poll.": "Un còp la creacion del sondatge confirmada, seretz mandat automaticament de vòstre sondatge.", + "Then, you will receive quickly two emails: one contening the link of your poll for sending it to the voters, the other contening the link to the administration page of your poll.": "D'aquel temps, recebretz dos corrièls : un amb lo ligam cap a vòstre sondatge per o mandar als opinaires, l'autre amb lo ligam per la pagina d'administracion del sondatge.", + "Create the poll": "Crear lo sondatge", + "Your poll will be automatically archived in %d days.": "Vòstre sondatge serà automaticament archivat dins %d jorns.", + "You can set a closer archiving date for it.": "Podètz decidir d'una data de mesa en archiva mai prèpa.", + "Archiving date:": "Data de mesa en archiva :", + "Your poll will automatically be archived": "DE_Your poll will automatically be archived", ++ "after the last date of your poll.": "DE_after the last date of your poll." + }, + "Admin": { + "Back to administration": "Tornar a l'administracion", + "Administration": "Administracion", + "Polls": "Sondatges", + "Migration": "Migracion", + "Purge": "Purga", + "Logs": "Istoric", + "Installation": "Installacion", + "Poll ID": "ID sondatge", + "Format": "Format", + "Title": "Títol", + "Author": "Autor", + "Email": "Corrièl", + "Expiration date": "Expiracion", + "Votes": "Vòtes", + "Actions": "Accions", + "See the poll": "Veire lo sondatge", + "Change the poll": "Modificar lo sondatge", + "Deleted the poll": "Suprimir lo sondatge", + "Summary": "Resumit", + "Success": "Réussite", + "Fail": "Fracàs", + "Nothing": "Res", + "Succeeded:": "Capitat:", + "Failed:": "Fracassat:", + "Skipped:": "Passat:", + "Pages:": "Paginas :", + "Purged:": "Purgats :", + "Confirm removal of the poll": "Confirmar la supression del sondatge", + "polls in the database at this time": "sondatges dins la banca de donadas actualament", + "Purge the polls": "Purgar los sondatges" + }, + "FindPolls": { + "Here are your polls": "Voici tes sondages", + "Send me my polls": "Envoyer mes sondages", + "Polls sent": "Sondages envoyés" + }, + "Mail": { + "Poll's participation: %s": "Participation au sondage : %s", + "Notification of poll: %s": "Notification d'un sondage : %s", + "filled a vote.\nYou can find your poll at the link": "vient de voter.
Vous pouvez retrouver votre sondage avec le lien suivant", + "updated a vote.\nYou can find your poll at the link": "vient de mettre à jour un vote.
Vous pouvez retrouver votre sondage avec le lien suivant", + "wrote a comment.\nYou can find your poll at the link": "vient de rédiger un commentaire.
Vous pouvez retrouver votre sondage avec le lien suivant", + "Someone just change your poll available at the following link %s.": "Quelqu'un vient de modifier votre sondage accessible au lien suivant %1$s.", + "Someone just delete your poll %s.": "Quelqu'un vient de supprimer votre sondage \"%s\".", + "Thanks for your trust.": "Merci de votre confiance.", + "FOOTER": "« La route est longue, mais la voie est libre… »
Framasoft ne vit que par vos dons (déductibles des impôts).
Merci d'avance pour votre soutien http://soutenir.framasoft.org.", + "[ADMINISTRATOR] New settings for your poll": "[ADMINISTRATEUR] Changement de configuration du sondage", + "You have changed the settings of your poll. \nYou can modify this poll with this link": "Vous avez modifié la configuration de votre sondage.
Vous pouvez modifier ce sondage avec le lien suivant", + "This is the message you have to send to the people you want to poll. \nNow, you have to send this message to everyone you want to poll.": "Ceci est le message qui doit être envoyé aux sondés.
Vous pouvez maintenant transmettre ce message à toutes les personnes susceptibles de participer au vote.", + "hast just created a poll called": " vient de créer un sondage intitulé ", + "Thanks for filling the poll at the link above": "Merci de bien vouloir participer au sondage à l'adresse suivante", + "This message should NOT be sent to the polled people. It is private for the poll's creator.\n\nYou can now modify it at the link above": "Ce message ne doit PAS être diffusé aux sondés. Il est réservé à l'auteur du sondage.

Vous pouvez modifier ce sondage à l'adresse suivante ", + "Author's message": "Réservé à l'auteur", + "For sending to the polled users": "Pour diffusion aux sondés" + }, + "Installation": { + "AppMail": "Adresse mail de l'application", + "AppName": "Nom de l'application", + "CleanUrl": "URL propres", + "Database": "Base de données", + "DbConnectionString": "Chaîne de connexion", + "DbPassword": "Mot de passe", + "DbPrefix": "Préfixe", + "DbUser": "Utilisateur", + "DefaultLanguage": "Lenga per defaut", + "General": "General", + "Install": "Installar", + "MigrationTable": "Taula de migracion", + "ResponseMail": "Adreça de responsa" + }, + "Error": { + "Error!": "Error !", + "Enter a title": "Cal picar un títol !", + "Something is going wrong...": "I a quicòm que truca...", + "Something is wrong with the format": "I a quicòm que truca amb lo format.", + "Enter an email address": "Cal picar una adreça de messatjariá !", + "The address is not correct! You should enter a valid email address (like r.stallman@outlock.com) in order to receive the link to your poll.": "L'adresse saisie n'est pas correcte ! Il faut une adresse électronique valide (par exemple r.stallman@outlock.com) pour recevoir le lien vers le sondage.", + "No polls found": "Aucun sondage n'a été trouvé", + "There is a problem with your choices": "Il y a un problème avec vos choix", + "You haven't filled the first section of the poll creation.": "Vous n'avez pas renseigné la première page du sondage", + "Javascript is disabled on your browser. Its activation is required to create a poll.": "Javascript est désactivé sur votre navigateur. Son activation est requise pour la création d'un sondage.", + "Cookies are disabled on your browser. Theirs activation is required to create a poll.": "Les cookies sont désactivés sur votre navigateur. Leur activation est requise pour la création d'un sondage.", + "This poll doesn't exist !": "Ce sondage n'existe pas !", + "Enter a name": "Vous n'avez pas saisi de nom !", + "The name is invalid.": "Le nom n'est pas valide.", + "The name you've chosen already exist in this poll!": "Le nom que vous avez choisi existe déjà !", + "Enter a name and a comment!": "Merci de remplir les deux champs !", + "Failed to insert the comment!": "Échec à l'insertion du commentaire !", + "Failed to delete the vote!": "Échec de la suppression du vote !", + "Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "Framadate n'est pas installé correctement, lisez le fichier INSTALL pour configurer la base de données avant de continuer.", + "Failed to save poll": "Echec de la sauvegarde du sondage", + "Update vote failed": "Mise à jour du vote échoué", + "Adding vote failed": "Ajout d'un vote échoué", + "You already voted": "Vous avez déjà voté", + "Poll has been updated before you vote": "Le sondage a été mis à jour avant votre vote", + "Comment failed": "Commentaire échoué", + "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'éditions suivantes : ", + "Failed to delete column": "Échec de la suppression de colonne", + "The column already exists": "La colonne existe déjà", + "MISSING_VALUES": "Il manque des valeurs", + "CANT_CONNECT_TO_DATABASE": "Impossible de se connecter à la base de données" + } +} From 070ea74fa9e893bfa54e2ebe78401f051cb13def Mon Sep 17 00:00:00 2001 From: Quentin Date: Fri, 12 Feb 2016 17:54:09 +0100 Subject: [PATCH 25/35] Update --- locale/oc.json | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/locale/oc.json b/locale/oc.json index 060460b..7d6bd45 100644 --- a/locale/oc.json +++ b/locale/oc.json @@ -164,14 +164,14 @@ "Adding the vote succeeded": "Ajust del vòte capitat" }, "adminstuds": { - "As poll administrator, you can change all the lines of this poll with this button": "En tant qu'administrateur, vous pouvez modifier toutes les lignes de ce sondage avec ce bouton", - "remove a column or a line with": "effacer une colonne ou une ligne avec", - "and add a new column with": "et si vous avez oublié de saisir un choix, vous pouvez rajouter une colonne en cliquant sur", - "Finally, you can change the informations of this poll like the title, the comments or your email address.": "Vous pouvez enfin également modifier les informations relatives à ce sondage comme le titre, les commentaires ou encore votre courriel.", - "Column's adding": "Ajout de colonne", - "You can add a new scheduling date to your poll.": "Vous pouvez ajouter une date à votre sondage.", - "If you just want to add a new hour to an existant date, put the same date and choose a new hour.": "Si vous voulez juste ajouter un horaire à une date existante, mettez la même date et choisissez un autre horaire. Il sera intégré normalement au sondage existant.", - "Confirm removal of the poll": "Confirmer la suppression du sondage", + "As poll administrator, you can change all the lines of this poll with this button": "En qualitat d'administrator podètz modificar totas las linhas d'aqueste sondatge avec aqueste boton", + "remove a column or a line with": "escafar una colomna o una linha amb", + "and add a new column with": "E se avètz doblidat de picar una causida, podètz tornar apondre una colona en clicant sus", + "Finally, you can change the informations of this poll like the title, the comments or your email address.": "Per acabar podètz tanben modificar las informacions tocant aqueste sondatge coma lo títol, los comentaris o vòstre corrièl.", + "Column's adding": "Apondi de colomna", + "You can add a new scheduling date to your poll.": "Podètz apondre una data a vòstre sondatge.", + "If you just want to add a new hour to an existant date, put the same date and choose a new hour.": "Se volètz apondre un orari a una data existenta, botatz la meteissa data e triatz un orari mai. Serà normalament integrat al sondatge existent.", + "Confirm removal of the poll": "Confirmar la supression del sondatge", "Delete the poll": "Suprimi lo sondatge", "Keep the poll": "Gardi lo sondatge", "Your poll has been removed!": "Vòstre sondatge es estat suprimit !", @@ -253,8 +253,8 @@ "Your poll will be automatically archived in %d days.": "Vòstre sondatge serà automaticament archivat dins %d jorns.", "You can set a closer archiving date for it.": "Podètz decidir d'una data de mesa en archiva mai prèpa.", "Archiving date:": "Data de mesa en archiva :", - "Your poll will automatically be archived": "DE_Your poll will automatically be archived", -+ "after the last date of your poll.": "DE_after the last date of your poll." + "Your poll will automatically be archived": "Vòstre sondatge sera automaticament mesa en archiva", ++ "after the last date of your poll.": "aprèp lo darrièr jorn del sondatge." }, "Admin": { "Back to administration": "Tornar a l'administracion", @@ -276,7 +276,7 @@ "Change the poll": "Modificar lo sondatge", "Deleted the poll": "Suprimir lo sondatge", "Summary": "Resumit", - "Success": "Réussite", + "Success": "Capidada", "Fail": "Fracàs", "Nothing": "Res", "Succeeded:": "Capitat:", @@ -289,9 +289,9 @@ "Purge the polls": "Purgar los sondatges" }, "FindPolls": { - "Here are your polls": "Voici tes sondages", - "Send me my polls": "Envoyer mes sondages", - "Polls sent": "Sondages envoyés" + "Here are your polls": "Vaquí tos sondatges", + "Send me my polls": "Mandar mos sondatges", + "Polls sent": "Sondatges mandats" }, "Mail": { "Poll's participation: %s": "Participation au sondage : %s", @@ -359,4 +359,4 @@ "MISSING_VALUES": "Il manque des valeurs", "CANT_CONNECT_TO_DATABASE": "Impossible de se connecter à la base de données" } -} +} \ No newline at end of file From 2816bd7362d3499522e7bfb808c89c26ad1f0c3a Mon Sep 17 00:00:00 2001 From: Quentin Date: Fri, 12 Feb 2016 18:06:21 +0100 Subject: [PATCH 26/35] Update --- locale/oc.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/locale/oc.json b/locale/oc.json index 7d6bd45..88e3156 100644 --- a/locale/oc.json +++ b/locale/oc.json @@ -19,16 +19,16 @@ "Back to the homepage of": "Tornar a la pagina d'acuèlh de", "days": "jors", "months": "meses", - "Day": "Jor", + "Day": "Jorn", "Time": "Ora", "with": "amb", - "vote": "vote", - "votes": "votes", + "vote": "vòte", + "votes": "vòtes", "for": "per", "Yes": "Òc", "Ifneedbe": "Se cal", "No": "Non", - "Legend:": "Légende :", + "Legend:": "Legenda :", "Date": "Data", "Classic": "Classic", "Page generated in": "Pagina generada en", @@ -94,10 +94,10 @@ "Print": "Imprimir", "Export to CSV": "Exportar en CSV", "Title": "Títol del sondatge", - "Edit the title": "Modificar l títol", + "Edit the title": "Modificar lo títol", "Save the new title": "Enregistrar lo nòu títol", "Cancel the title edit": "Anullar lo cambi de títol", - "Initiator of the poll": "Autor duel sondatge", + "Initiator of the poll": "Autor del sondatge", "Edit the name": "Modificacion de l'autor", "Save the new name": "Enregistrar l'autor", "Cancel the name edit": "Anullar lo cambi d'autor", @@ -119,7 +119,7 @@ "Votes and comments are locked": "Los vòtes e comentaris son clavats", "Votes and comments are open": "Los vòtes e comentaris son doberts", "Votes are editable": "Los vòtes son modificables", - "Votes are editable solely by their owner.": "Los vòtes son solament modificables per lo creator", + "Votes are editable solely by their owner.": "Los vòtes son solament modificables pel creator", "Save the new rules": "Enregistrar las nòvas permissions", "Cancel the rules edit": "Anullar lo cambi de permissions", "Results are hidden.": "Las resultats son amagadas.", @@ -155,7 +155,7 @@ "Comment added": "Comentari apondut" }, "studs": { - "If you want to vote in this poll, you have to give your name, choose the values that fit best for you and validate with the plus button at the end of the line.": "Pour participer à ce sondage, veuillez entrer votre nom, choisir toutes les valeurs qui vous conviennent et valider votre choix avec le bouton en bout de ligne.", + "If you want to vote in this poll, you have to give your name, choose the values that fit best for you and validate with the plus button at the end of the line.": "Per participar a aqueste sondatge, picatz vòstre nom, triatz totas las valors que vos agradan e validatz amb lo boton al cap de linha.", "POLL_LOCKED_WARNING": "L'administrator a clavat aqueste sondatge. Los vòtes e comentaris son gelats, es pus mai possible de participar", "The poll is expired, it will be deleted soon.": "Lo sondatge a expirat, serà lèu suprimit.", "Deletion date:": "Data de supression :", From c0875e6f58f0fa95d86069f3fec2d61908e5bbbe Mon Sep 17 00:00:00 2001 From: Quentin Date: Fri, 12 Feb 2016 18:06:49 +0100 Subject: [PATCH 27/35] Update --- locale/oc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/oc.json b/locale/oc.json index 88e3156..8def185 100644 --- a/locale/oc.json +++ b/locale/oc.json @@ -4,7 +4,7 @@ "Home": "Acuèlh", "Poll": "Sondage", "Save": "Enregistrar", - "Cancel": "Annllar", + "Cancel": "Anullar", "Add": "Apondre", "Remove": "Suprimir", "Validate": "Validar", From b24d59478f4a27e7e9670149f5016ec62690c933 Mon Sep 17 00:00:00 2001 From: Quentin Date: Sat, 13 Feb 2016 17:40:43 +0100 Subject: [PATCH 28/35] Update, almost finished --- locale/oc.json | 58 +++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/locale/oc.json b/locale/oc.json index 8def185..cc41660 100644 --- a/locale/oc.json +++ b/locale/oc.json @@ -294,16 +294,16 @@ "Polls sent": "Sondatges mandats" }, "Mail": { - "Poll's participation: %s": "Participation au sondage : %s", - "Notification of poll: %s": "Notification d'un sondage : %s", - "filled a vote.\nYou can find your poll at the link": "vient de voter.
Vous pouvez retrouver votre sondage avec le lien suivant", - "updated a vote.\nYou can find your poll at the link": "vient de mettre à jour un vote.
Vous pouvez retrouver votre sondage avec le lien suivant", - "wrote a comment.\nYou can find your poll at the link": "vient de rédiger un commentaire.
Vous pouvez retrouver votre sondage avec le lien suivant", - "Someone just change your poll available at the following link %s.": "Quelqu'un vient de modifier votre sondage accessible au lien suivant %1$s.", - "Someone just delete your poll %s.": "Quelqu'un vient de supprimer votre sondage \"%s\".", - "Thanks for your trust.": "Merci de votre confiance.", - "FOOTER": "« La route est longue, mais la voie est libre… »
Framasoft ne vit que par vos dons (déductibles des impôts).
Merci d'avance pour votre soutien http://soutenir.framasoft.org.", - "[ADMINISTRATOR] New settings for your poll": "[ADMINISTRATEUR] Changement de configuration du sondage", + "Poll's participation: %s": "Participacion al sondatge : %s", + "Notification of poll: %s": "Notificacion d'un sondatge : %s", + "filled a vote.\nYou can find your poll at the link": "ven de votar.
Podètz tornar a vòstre sondatge amb lo ligam seguent", + "updated a vote.\nYou can find your poll at the link": "ven de metre a jorn un vòte.
Podètz tornar a vòstre sondatge amb lo ligam seguent", + "wrote a comment.\nYou can find your poll at the link": "ven de redigir un comentari.
Podètz tornar a vòstre sondatge amb lo ligam seguent", + "Someone just change your poll available at the following link %s.": "Qualqu'un ven de modificar vòstre sondatge accessible amb lo ligam seguent %1$s.", + "Someone just delete your poll %s.": "Qualqu'un ven de suprimir vòstre sondatge \"%s\".", + "Thanks for your trust.": "Mercé per la vòstre confiança.", + "FOOTER": "« La rota es longa, mai lo camin es liure… »
Framasoft solament viu amb vòstres dons (qu'òm pòt tirar de vòstres impòstes).
Mercé d'avança pel vòstre sosten http://soutenir.framasoft.org.", + "[ADMINISTRATOR] New settings for your poll": "[ADMINISTRATOR] Cambi de configuracion del sondatge", "You have changed the settings of your poll. \nYou can modify this poll with this link": "Vous avez modifié la configuration de votre sondage.
Vous pouvez modifier ce sondage avec le lien suivant", "This is the message you have to send to the people you want to poll. \nNow, you have to send this message to everyone you want to poll.": "Ceci est le message qui doit être envoyé aux sondés.
Vous pouvez maintenant transmettre ce message à toutes les personnes susceptibles de participer au vote.", "hast just created a poll called": " vient de créer un sondage intitulé ", @@ -339,24 +339,24 @@ "You haven't filled the first section of the poll creation.": "Vous n'avez pas renseigné la première page du sondage", "Javascript is disabled on your browser. Its activation is required to create a poll.": "Javascript est désactivé sur votre navigateur. Son activation est requise pour la création d'un sondage.", "Cookies are disabled on your browser. Theirs activation is required to create a poll.": "Les cookies sont désactivés sur votre navigateur. Leur activation est requise pour la création d'un sondage.", - "This poll doesn't exist !": "Ce sondage n'existe pas !", - "Enter a name": "Vous n'avez pas saisi de nom !", - "The name is invalid.": "Le nom n'est pas valide.", - "The name you've chosen already exist in this poll!": "Le nom que vous avez choisi existe déjà !", - "Enter a name and a comment!": "Merci de remplir les deux champs !", - "Failed to insert the comment!": "Échec à l'insertion du commentaire !", - "Failed to delete the vote!": "Échec de la suppression du vote !", - "Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "Framadate n'est pas installé correctement, lisez le fichier INSTALL pour configurer la base de données avant de continuer.", - "Failed to save poll": "Echec de la sauvegarde du sondage", - "Update vote failed": "Mise à jour du vote échoué", - "Adding vote failed": "Ajout d'un vote échoué", - "You already voted": "Vous avez déjà voté", - "Poll has been updated before you vote": "Le sondage a été mis à jour avant votre vote", - "Comment failed": "Commentaire échoué", - "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'éditions suivantes : ", - "Failed to delete column": "Échec de la suppression de colonne", - "The column already exists": "La colonne existe déjà", - "MISSING_VALUES": "Il manque des valeurs", - "CANT_CONNECT_TO_DATABASE": "Impossible de se connecter à la base de données" + "This poll doesn't exist !": "Aqueste sondatge existís pas !", + "Enter a name": "Avètz pas picat de nom !", + "The name is invalid.": "Lo nom es pas valide.", + "The name you've chosen already exist in this poll!": "Lo nom qu'avètz triat existís ja !", + "Enter a name and a comment!": "Mercé de garnir los dos camps !", + "Failed to insert the comment!": "Fracàs de l'ajust del comentari !", + "Failed to delete the vote!": "Fracàs de la supression del vòte !", + "Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "Framadate es pas installat coma cal, legissètz lo fichièr per configurar la banca de donadas abans de contunhar.", + "Failed to save poll": "Fracàs del salvament del sondatge", + "Update vote failed": "Misa a jorn del vòte fracassat", + "Adding vote failed": "Ajust d'un vòte fracassat", + "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", + "Comment failed": "Comentari fracassat", + "You can't create a poll with hidden results with the following edition option:": "Podètz pas crear de sondatges amb resultats amagadas amb las opcions d'edicion seguentas : ", + "Failed to delete column": "Fracàs de la supression de colomna", + "The column already exists": "La colomna existís ja", + "MISSING_VALUES": "Mancan de valors", + "CANT_CONNECT_TO_DATABASE": "Impossible de se connectar a la banca de donadas" } } \ No newline at end of file From a6373c6e5f762418fefbb20f92e77ec87422025a Mon Sep 17 00:00:00 2001 From: Quentin Date: Sat, 13 Feb 2016 18:50:51 +0100 Subject: [PATCH 29/35] Final update for the Occitan language --- locale/oc.json | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/locale/oc.json b/locale/oc.json index cc41660..e7e302c 100644 --- a/locale/oc.json +++ b/locale/oc.json @@ -304,23 +304,23 @@ "Thanks for your trust.": "Mercé per la vòstre confiança.", "FOOTER": "« La rota es longa, mai lo camin es liure… »
Framasoft solament viu amb vòstres dons (qu'òm pòt tirar de vòstres impòstes).
Mercé d'avança pel vòstre sosten http://soutenir.framasoft.org.", "[ADMINISTRATOR] New settings for your poll": "[ADMINISTRATOR] Cambi de configuracion del sondatge", - "You have changed the settings of your poll. \nYou can modify this poll with this link": "Vous avez modifié la configuration de votre sondage.
Vous pouvez modifier ce sondage avec le lien suivant", - "This is the message you have to send to the people you want to poll. \nNow, you have to send this message to everyone you want to poll.": "Ceci est le message qui doit être envoyé aux sondés.
Vous pouvez maintenant transmettre ce message à toutes les personnes susceptibles de participer au vote.", - "hast just created a poll called": " vient de créer un sondage intitulé ", - "Thanks for filling the poll at the link above": "Merci de bien vouloir participer au sondage à l'adresse suivante", - "This message should NOT be sent to the polled people. It is private for the poll's creator.\n\nYou can now modify it at the link above": "Ce message ne doit PAS être diffusé aux sondés. Il est réservé à l'auteur du sondage.

Vous pouvez modifier ce sondage à l'adresse suivante ", - "Author's message": "Réservé à l'auteur", - "For sending to the polled users": "Pour diffusion aux sondés" + "You have changed the settings of your poll. \nYou can modify this poll with this link": "Avètz modificat la configuracion del sondatge.
Podètz modificar aqueste sondatge amb lo ligam seguent", + "This is the message you have to send to the people you want to poll. \nNow, you have to send this message to everyone you want to poll.": "Aiçò es lo messatge que serà mandat als opinaires.
Podètz ara trasmetre aqueste messatge a totas las personas susceptiblas de participar al vòte.", + "hast just created a poll called": " ven de crear un sondatge titolat ", + "Thanks for filling the poll at the link above": "Mercés de ben voler participar al sondatge a l'adreça seguenta", + "This message should NOT be sent to the polled people. It is private for the poll's creator.\n\nYou can now modify it at the link above": "Aqueste messatge cal PAS èsser difusit alx opinaires. Es reservat a l'autor del sondatge.

Podètz modificar aqueste sondatge amb lo ligam seguent ", + "Author's message": "Reservat a l'autor", + "For sending to the polled users": "Per difusion als opinaires" }, "Installation": { - "AppMail": "Adresse mail de l'application", - "AppName": "Nom de l'application", - "CleanUrl": "URL propres", - "Database": "Base de données", - "DbConnectionString": "Chaîne de connexion", - "DbPassword": "Mot de passe", - "DbPrefix": "Préfixe", - "DbUser": "Utilisateur", + "AppMail": "Adreça de corrièl de l'aplicacion", + "AppName": "Nom de l'aplicacion", + "CleanUrl": "URL clars", + "Database": "Banca de donadas", + "DbConnectionString": "Cadena de connexion", + "DbPassword": "Senhal", + "DbPrefix": "Prefixe", + "DbUser": "Utilizaire", "DefaultLanguage": "Lenga per defaut", "General": "General", "Install": "Installar", @@ -333,12 +333,12 @@ "Something is going wrong...": "I a quicòm que truca...", "Something is wrong with the format": "I a quicòm que truca amb lo format.", "Enter an email address": "Cal picar una adreça de messatjariá !", - "The address is not correct! You should enter a valid email address (like r.stallman@outlock.com) in order to receive the link to your poll.": "L'adresse saisie n'est pas correcte ! Il faut une adresse électronique valide (par exemple r.stallman@outlock.com) pour recevoir le lien vers le sondage.", - "No polls found": "Aucun sondage n'a été trouvé", - "There is a problem with your choices": "Il y a un problème avec vos choix", - "You haven't filled the first section of the poll creation.": "Vous n'avez pas renseigné la première page du sondage", - "Javascript is disabled on your browser. Its activation is required to create a poll.": "Javascript est désactivé sur votre navigateur. Son activation est requise pour la création d'un sondage.", - "Cookies are disabled on your browser. Theirs activation is required to create a poll.": "Les cookies sont désactivés sur votre navigateur. Leur activation est requise pour la création d'un sondage.", + "The address is not correct! You should enter a valid email address (like r.stallman@outlock.com) in order to receive the link to your poll.": "L'adreça picada es pas corrècta ! Cal una adreça valida (per exemple r.stallman@outlock.com) per recebre lo ligam cap al sondatge.", + "No polls found": "Cap sondatge trobat", + "There is a problem with your choices": "I a un problèma amb vòstras causidas", + "You haven't filled the first section of the poll creation.": "Avètz pas garnit la premièra pagina del sondatge", + "Javascript is disabled on your browser. Its activation is required to create a poll.": "Javascript es desactivat sus vòstre navigador. Son activacion es requesida per la creacion d'un sondatge.", + "Cookies are disabled on your browser. Theirs activation is required to create a poll.": "Los cookies son desactivats su vòstre navigador. Lor activacion es requesida per la creacion d'un sondatge.", "This poll doesn't exist !": "Aqueste sondatge existís pas !", "Enter a name": "Avètz pas picat de nom !", "The name is invalid.": "Lo nom es pas valide.", From 5decfb44884d56246f74b2853598f695c8945267 Mon Sep 17 00:00:00 2001 From: goofy-bz Date: Sat, 20 Feb 2016 17:58:39 +0100 Subject: [PATCH 30/35] minor lang fix --- locale/en.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/locale/en.json b/locale/en.json index 0d8dd59..f70d9cd 100644 --- a/locale/en.json +++ b/locale/en.json @@ -59,7 +59,7 @@ }, "Homepage": { "Schedule an event": "Schedule an event", - "Make a classic poll": "Make a classic poll", + "Make a classic poll": "Make a standard poll", "Where are my polls": "Where are my polls?" }, "1st section": { @@ -76,28 +76,28 @@ "2nd section": { "The software": "The software", "Framadate was initially based on ": "Framadate was initially based on ", - "a software developed by the University of Strasbourg. Today, it is devevoped by the association Framasoft.": "software developed by the University of Strasbourg. These days, it is developed by the Framasoft association.", - "This software needs javascript and cookies enabled. It is compatible with the following web browsers:": "This software needs JavaScript and cookies enabled. It is compatible with the following web browsers:", + "a software developed by the University of Strasbourg. Today, it is developed by Framasoft association.": "software developed by the University of Strasbourg. These days, it is developed by the Framasoft association.", + "This software needs JavaScript and cookies enabled. It is compatible with the following web browsers:": "This software needs JavaScript and cookies enabled. It is compatible with the following web browsers:", "It is governed by the": "Framadate is licensed under the", "CeCILL-B license": "CeCILL-B license" }, "3rd section": { - "Cultivate your garden": "Cultivate your garden", + "Cultivate your garden": "Grow your own", "To participate in the software development, suggest improvements or simply download it, please visit ": "To participate in the software development, suggest improvements or simply download it, please visit ", "the development site": "the development site", "If you want to install the software for your own use and thus increase your independence, we help you on:": "If you want to install the software for your own use and thus increase your independence, we can help you at:" }, "PollInfo": { "Remove the poll": "Remove the poll", - "Remove all the comments": "Remove all the comments", - "Remove all the votes": "Remove all the votes", + "Remove all the comments": "Remove all comments", + "Remove all the votes": "Remove all votes", "Print": "Print", "Export to CSV": "Export to CSV", "Title": "Title of the poll", "Edit the title": "Edit title", "Save the new title": "Save the new title", "Cancel the title edit": "Cancel the title edit", - "Initiator of the poll": "Initiator of the poll", + "Initiator of the poll": "Creator of the poll", "Edit the name": "Edit name", "Save the new name": "Save the new name", "Cancel the name edit": "Cancel the name edit", @@ -344,4 +344,4 @@ "MISSING_VALUES": "Missing values", "CANT_CONNECT_TO_DATABASE": "Unable to connect to database" } -} +} \ No newline at end of file From 31c3b9f974275523f4c2538bac10b8ead47fbf08 Mon Sep 17 00:00:00 2001 From: goofy-bz Date: Sat, 20 Feb 2016 18:12:35 +0100 Subject: [PATCH 31/35] minor lang fix --- locale/fr.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/locale/fr.json b/locale/fr.json index f1683ee..f4b5856 100644 --- a/locale/fr.json +++ b/locale/fr.json @@ -77,7 +77,7 @@ "The software": "Le logiciel", "Framadate was initially based on ": "Framadate est initialement basé sur ", "a software developed by the University of Strasbourg. Today, it is devevoped by the association Framasoft.": "un logiciel développé par l'Université de Strasbourg. Aujourd'hui, son développement est assuré par l’association Framasoft.", - "This software needs javascript and cookies enabled. It is compatible with the following web browsers:": "Ce logiciel requiert l’activation du javascript et des cookies. Il est compatible avec les navigateurs web suivants :", + "This software needs javascript and cookies enabled. It is compatible with the following web browsers:": "Ce logiciel requiert l’activation du JavaScript et des cookies. Il est compatible avec les navigateurs web suivants :", "It is governed by the": "Il est régi par la", "CeCILL-B license": "licence CeCILL-B" }, @@ -132,7 +132,7 @@ "Vote no for": "Voter « non » pour", "Vote yes for": "Voter « oui » pour", "Vote ifneedbe for": "Voter « Si nécessaire » pour", - "Save the choices": "Enregister les choix", + "Save the choices": "Enregistrer les choix", "Addition": "Somme", "Best choice": "Meilleur choix", "Best choices": "Meilleurs choix", @@ -159,7 +159,7 @@ "POLL_LOCKED_WARNING": "L'administrateur a verrouillé ce sondage. Les votes et commentaires sont gelés, il n'est plus possible de participer", "The poll is expired, it will be deleted soon.": "Le sondage a expiré, il sera bientôt supprimé.", "Deletion date:": "Date de suppression :", - "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:": "Votre vote a bien été pris en compte, mais faites attention : ce sondage n'autorise l'édition de votre vote qu'avec le lien personnalisé suivant ; conservez le précieusement ! ", + "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:": "Votre vote a bien été pris en compte, mais faites attention : ce sondage n'autorise l'édition de votre vote qu'avec le lien personnalisé suivant ; conservez-le précieusement ! ", "Update vote succeeded": "Mise à jour du vote réussi", "Adding the vote succeeded": "Ajout du vote réussi" }, @@ -279,11 +279,11 @@ "Success": "Réussite", "Fail": "Échèc", "Nothing": "Rien", - "Succeeded:": "Réussit:", - "Failed:": "Échoué:", - "Skipped:": "Passé:", - "Pages:": "Pages :", - "Purged:": "Purgés :", + "Succeeded:": "Succès :", + "Failed:": "Échec ::", + "Skipped:": "Passé :", + "Pages:": "Pages :", + "Purged:": "Purgés :", "Confirm removal of the poll": "Confirmer la suppression du sondage", "polls in the database at this time": "sondages dans la base actuellement", "Purge the polls": "Purger les sondages" @@ -337,7 +337,7 @@ "No polls found": "Aucun sondage n'a été trouvé", "There is a problem with your choices": "Il y a un problème avec vos choix", "You haven't filled the first section of the poll creation.": "Vous n'avez pas renseigné la première page du sondage", - "Javascript is disabled on your browser. Its activation is required to create a poll.": "Javascript est désactivé sur votre navigateur. Son activation est requise pour la création d'un sondage.", + "Javascript is disabled on your browser. Its activation is required to create a poll.": "JavaScript est désactivé sur votre navigateur. Son activation est requise pour la création d'un sondage.", "Cookies are disabled on your browser. Theirs activation is required to create a poll.": "Les cookies sont désactivés sur votre navigateur. Leur activation est requise pour la création d'un sondage.", "This poll doesn't exist !": "Ce sondage n'existe pas !", "Enter a name": "Vous n'avez pas saisi de nom !", @@ -347,16 +347,16 @@ "Failed to insert the comment!": "Échec à l'insertion du commentaire !", "Failed to delete the vote!": "Échec de la suppression du vote !", "Framadate is not properly installed, please check the \"INSTALL\" to setup the database before continuing.": "Framadate n'est pas installé correctement, lisez le fichier INSTALL pour configurer la base de données avant de continuer.", - "Failed to save poll": "Echec de la sauvegarde du sondage", - "Update vote failed": "Mise à jour du vote échoué", - "Adding vote failed": "Ajout d'un vote échoué", + "Failed to save poll": "Échec de la sauvegarde du sondage", + "Update vote failed": "Échec de de la mise à jour du vote", + "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", - "Comment failed": "Commentaire échoué", + "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'éditions suivantes : ", "Failed to delete column": "Échec de la suppression de colonne", "The column already exists": "La colonne existe déjà", "MISSING_VALUES": "Il manque des valeurs", "CANT_CONNECT_TO_DATABASE": "Impossible de se connecter à la base de données" } -} +} \ No newline at end of file From bde59fe9747ed9999c5b0fddb6f23e63725cfd6f Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Mon, 22 Feb 2016 23:51:33 +0100 Subject: [PATCH 32/35] Fix the position computation to insert default vote when adding column --- .../Framadate/Services/AdminPollService.php | 8 +- app/inc/XXconfig.php | 88 ------------------- 2 files changed, 7 insertions(+), 89 deletions(-) delete mode 100644 app/inc/XXconfig.php diff --git a/app/classes/Framadate/Services/AdminPollService.php b/app/classes/Framadate/Services/AdminPollService.php index 500e528..a93bf60 100644 --- a/app/classes/Framadate/Services/AdminPollService.php +++ b/app/classes/Framadate/Services/AdminPollService.php @@ -284,7 +284,13 @@ class AdminPollService { $result->slot = null; $result->insert = 0; - foreach ($slots as $slot) { + // Sort slots before searching where to insert + uasort($slots, function ($a, $b) { + return $a->title > $b->title; + }); + + // Search where to insert new column + foreach ($slots as $k=>$slot) { $rowDatetime = $slot->title; $moments = explode(',', $slot->moments); diff --git a/app/inc/XXconfig.php b/app/inc/XXconfig.php deleted file mode 100644 index 6530d13..0000000 --- a/app/inc/XXconfig.php +++ /dev/null @@ -1,88 +0,0 @@ -'; - -// Application name -const NOMAPPLICATION = 'Développement OPZ'; - -// Database administrator email -const ADRESSEMAILADMIN = 'framadate-dev@olivierperez.fr'; - -// Email for automatic responses (you should set it to "no-reply") -const ADRESSEMAILREPONSEAUTO = 'no-reply@olivierperez.fr'; - -// Database user -const DB_USER= 'dev_framadate'; - -// Database password -const DB_PASSWORD = 'dev_framadate'; - -// Database server name, leave empty to use a socket -const DB_CONNECTION_STRING = 'mysql:host=localhost;dbname=framadate_dev;port=3306'; - -// Name of the table that store migration script already executed -const MIGRATION_TABLE = 'framadate_migration'; - -// Table name prefix -const TABLENAME_PREFIX = 'fd_'; - -// Default Language using POSIX variant of BC P47 standard (choose in $ALLOWED_LANGUAGES) -const DEFAULT_LANGUAGE = 'fr'; - -// List of supported languages, fake constant as arrays can be used as constants only in PHP >=5.6 -$ALLOWED_LANGUAGES = [ - 'fr' => 'Français', - 'en' => 'English', - 'es' => 'Español', - 'de' => 'Deutsch', - 'it' => 'Italiano', -]; - -// Nom et emplacement du fichier image contenant le titre -const IMAGE_TITRE = 'images/logo-framadate.png'; - -// Clean URLs, boolean -const URL_PROPRE = false; - -// Use REMOTE_USER data provided by web server -const USE_REMOTE_USER = true; - -// Path to the log file -const LOG_FILE = 'admin/stdout.log'; - -// Days (after expiration date) before purge a poll -const PURGE_DELAY = 60; - -// Config -$config = [ - /* general config */ - 'use_smtp' => false, // use email for polls creation/modification/responses notification - /* home */ - 'show_what_is_that' => true, // display "how to use" section - 'show_the_software' => true, // display technical information about the software - 'show_cultivate_your_garden' => true, // display "developpement and administration" information - /* create_classic_poll.php / create_date_poll.php */ - 'default_poll_duration' => 180, // default values for the new poll duration (number of days). - /* create_classic_poll.php */ - 'user_can_add_img_or_link' => true, // user can add link or URL when creating his poll. -]; From 2caa5117d62f42318256b6906bd0127f27cc1514 Mon Sep 17 00:00:00 2001 From: Quentin Date: Tue, 23 Feb 2016 09:25:05 +0100 Subject: [PATCH 33/35] Update to add the Occitan language --- app/inc/config.template.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/inc/config.template.php b/app/inc/config.template.php index 9aad34e..826c67a 100644 --- a/app/inc/config.template.php +++ b/app/inc/config.template.php @@ -53,6 +53,7 @@ const DEFAULT_LANGUAGE = 'fr'; $ALLOWED_LANGUAGES = [ 'fr' => 'Français', 'en' => 'English', + 'oc' => 'Occitan', 'es' => 'Español', 'de' => 'Deutsch', 'it' => 'Italiano', @@ -85,5 +86,4 @@ $config = [ 'default_poll_duration' => 180, // default values for the new poll duration (number of days). /* create_classic_poll.php */ 'user_can_add_img_or_link' => true, // user can add link or URL when creating his poll. -]; - +]; \ No newline at end of file From 1ef4551779ee800d92010d40ab863676a0ab8f41 Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Wed, 2 Mar 2016 23:26:31 +0100 Subject: [PATCH 34/35] Fix Occitan language --- locale/oc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/oc.json b/locale/oc.json index e7e302c..f3660f1 100644 --- a/locale/oc.json +++ b/locale/oc.json @@ -254,7 +254,7 @@ "You can set a closer archiving date for it.": "Podètz decidir d'una data de mesa en archiva mai prèpa.", "Archiving date:": "Data de mesa en archiva :", "Your poll will automatically be archived": "Vòstre sondatge sera automaticament mesa en archiva", -+ "after the last date of your poll.": "aprèp lo darrièr jorn del sondatge." + "after the last date of your poll.": "aprèp lo darrièr jorn del sondatge." }, "Admin": { "Back to administration": "Tornar a l'administracion", From 276f732defd5ab01358a33f7a4e3013ae01673bd Mon Sep 17 00:00:00 2001 From: Olivier PEREZ Date: Wed, 2 Mar 2016 23:55:12 +0100 Subject: [PATCH 35/35] Fix #145 and #146 - Sort slots before check slots hash --- .../Framadate/Services/AdminPollService.php | 4 +-- .../Framadate/Services/PollService.php | 28 +++++++++++++------ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/app/classes/Framadate/Services/AdminPollService.php b/app/classes/Framadate/Services/AdminPollService.php index a93bf60..369d13d 100644 --- a/app/classes/Framadate/Services/AdminPollService.php +++ b/app/classes/Framadate/Services/AdminPollService.php @@ -285,9 +285,7 @@ class AdminPollService { $result->insert = 0; // Sort slots before searching where to insert - uasort($slots, function ($a, $b) { - return $a->title > $b->title; - }); + $this->pollService->sortSlorts($slots); // Search where to insert new column foreach ($slots as $k=>$slot) { diff --git a/app/classes/Framadate/Services/PollService.php b/app/classes/Framadate/Services/PollService.php index fa2ab46..3d2bfe3 100644 --- a/app/classes/Framadate/Services/PollService.php +++ b/app/classes/Framadate/Services/PollService.php @@ -78,16 +78,16 @@ class PollService { function allSlotsByPoll($poll) { $slots = $this->slotRepository->listByPollId($poll->id); if ($poll->format == 'D') { - uasort($slots, function ($a, $b) { - return $a->title > $b->title; - }); + $this->sortSlorts($slots); } return $slots; } public function updateVote($poll_id, $vote_id, $name, $choices, $slots_hash) { + $poll = $this->findById($poll_id); + // Check if slots are still the same - $this->checkThatSlotsDidntChanged($poll_id, $slots_hash); + $this->checkThatSlotsDidntChanged($poll, $slots_hash); // Update vote $choices = implode($choices); @@ -95,8 +95,10 @@ class PollService { } function addVote($poll_id, $name, $choices, $slots_hash) { + $poll = $this->findById($poll_id); + // Check if slots are still the same - $this->checkThatSlotsDidntChanged($poll_id, $slots_hash); + $this->checkThatSlotsDidntChanged($poll, $slots_hash); // Check if vote already exists if ($this->voteRepository->existsByPollIdAndName($poll_id, $name)) { @@ -225,15 +227,25 @@ class PollService { /** * This method checks if the hash send by the user is the same as the computed hash. * - * @param $poll_id int The id of the poll + * @param $poll /stdClass The poll * @param $slots_hash string The hash sent by the user * @throws ConcurrentEditionException Thrown when hashes are differents */ - private function checkThatSlotsDidntChanged($poll_id, $slots_hash) { - $slots = $this->slotRepository->listByPollId($poll_id); + private function checkThatSlotsDidntChanged($poll, $slots_hash) { + $slots = $this->allSlotsByPoll($poll); if ($slots_hash !== $this->hashSlots($slots)) { throw new ConcurrentEditionException(); } } + /** + * @return mixed + */ + public function sortSlorts(&$slots) { + uasort($slots, function ($a, $b) { + return $a->title > $b->title; + }); + return $slots; + } + }