diff --git a/app/classes/Framadate/Form.php b/app/classes/Framadate/Form.php index 07b7868cef97dda18f452bf6995fd15bb3666452..52437e5f84679b31ee3245d72351f1a7d270c012 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 29e8a4230a20a73f28d475f9ec1ce388c6cd8881..ff1d999b4126884fd6d734283d39412240aa8d01 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 166b21bf76a2a4514fa6e68ca4c790839d99a6ab..2430ccec4acde0df719d698e5c91c377b1c25524 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 06b41435291dc020383a608f4c3e5f1e425a054c..15f4a8055a5e45d2cbc7b43fd4bc446166561e34 100644 --- a/create_poll.php +++ b/create_poll.php @@ -18,10 +18,9 @@ */ use Framadate\Form; +use Framadate\Security\PasswordHasher; use Framadate\Services\InputService; -use Framadate\Editable; use Framadate\Utils; -use Framadate\Security\PasswordHasher; 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 ebd87448d796a4acbb0cbba8a5bcbdb14f7060a6..0ee8bdb20ab6369f8fb75e4e529f4d4b253f0e49 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 09443c68275dbe46eb17612c57f8b30e500ebb15..9b576c26a0629085570c632ecf2fd0eada750cb7 100644 --- a/tpl/create_poll.tpl +++ b/tpl/create_poll.tpl @@ -16,6 +16,7 @@ {__('Step 1', 'Required fields cannot be left blank.')} </p> </div> + <div class="form-group {$errors['title']['class']}"> <label for="poll_title" class="col-sm-4 control-label">{__('Step 1', 'Poll title')} *</label> @@ -32,6 +33,30 @@ </div> {/if} + <div class="form-group {$errors['id']['class']}"> + <label for="poll_id" class="col-sm-4 control-label">{__('Step 1', 'Poll id')} *</label> + + <div class="col-sm-8"> + <div class="input-group"> + <span class="input-group-addon"> + <input id="custom_id" type="checkbox"/> + </span> + <input id="poll_id" type="text" name="id" class="form-control" {$errors['id']['aria']} + value="{$poll_id}" aria-describedBy="pollIdDesc" disabled="disabled" maxlength="64" + pattern="[A-Za-z0-9-]+"/> + </div> + <span id="pollIdDesc" class="help-block">{__('Step 1', 'Poll id rules')}</span> + <span class="help-block text-warning">{__('Step 1', 'Poll id warning')}</span> + </div> + </div> + {if !empty($errors['id']['msg'])} + <div class="alert alert-danger"> + <p id="poll_title_error"> + {$errors['id']['msg']} + </p> + </div> + {/if} + <div class="form-group {$errors['description']['class']}"> <label for="poll_comments" class="col-sm-4 control-label">{__('Generic', 'Description')}</label>