Some work on vote saving

This commit is contained in:
Olivier PEREZ 2014-12-17 13:17:08 +01:00
parent e941cf1822
commit 80b06d65cd
10 changed files with 193 additions and 96 deletions

10
.gitignore vendored
View File

@ -1,6 +1,5 @@
.htaccess .htaccess
admin/.htaccess .htpasswd
admin/.htpasswd
admin/logs_studs.txt admin/logs_studs.txt
composer.lock composer.lock
composer.phar composer.phar
@ -8,7 +7,10 @@ framanav
nav nav
app/inc/constants.php app/inc/constants.php
vendor vendor
.settings/
.project
cache/ cache/
tpl_c/ tpl_c/
.settings/
.project
.idea/
*.iml

View File

@ -39,19 +39,13 @@ class FramaDB
} }
function findPollById($poll_id) { function findPollById($poll_id) {
$prepared = $this->prepare('SELECT * FROM sondage WHERE sondage.poll_id = ?');
// Open database $prepared->execute([$poll_id]);
if (preg_match(';^[\w\d]{16}$;i', $poll_id)) { $poll = $prepared->fetch();
$prepared = $this->prepare('SELECT * FROM sondage WHERE sondage.poll_id = ?'); $prepared->closeCursor();
$prepared->execute([$poll_id]); return $poll;
$poll = $prepared->fetch();
$prepared->closeCursor();
return $poll;
}
return null;
} }
function allCommentsByPollId($poll_id) { function allCommentsByPollId($poll_id) {
@ -72,15 +66,15 @@ class FramaDB
return $prepared->fetchAll(); return $prepared->fetchAll();
} }
function insertVote($name, $poll_id, $votes) { function insertVote($poll_id, $name, $choices) {
$prepared = $this->prepare('INSERT INTO user_studs (nom,id_sondage,reponses) VALUES (?,?,?)'); $prepared = $this->prepare('INSERT INTO user_studs (id_sondage,nom,reponses) VALUES (?,?,?)');
$prepared->execute([$name, $poll_id, $votes]); $prepared->execute([$poll_id, $name, $choices]);
$newVote = new \stdClass(); $newVote = new \stdClass();
$newVote->id_sondage = $poll_id; $newVote->id_sondage = $poll_id;
$newVote->id_users = $this->pdo->lastInsertId(); $newVote->id_users = $this->pdo->lastInsertId();
$newVote->nom = $name; $newVote->nom = $name;
$newVote->reponse = $votes; $newVote->reponse = $choices;
return $newVote; return $newVote;
} }

View File

@ -0,0 +1,15 @@
<?php
namespace Framadate;
class Message {
var $type;
var $message;
function __construct($type, $message) {
$this->type = $type;
$this->message = $message;
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace Framadate\Services;
/**
* This class helps to clean all inputs from the users or external services.
*/
class InputService {
function __construct() {}
/**
* This method filter an array calling "filter_var" on each items.
* Only items validated are added at their own indexes, the others are not returned.
*/
function filterArray($arr, $type, $options) {
$newArr = [];
foreach($arr as $id=>$item) {
$item = filter_var($item, $type, $options);
if ($item !== false) {
$newArr[$id] = $item;
}
}
return $newArr;
}
}

View File

@ -0,0 +1,83 @@
<?php
namespace Framadate\Services;
class PollService {
private $connect;
function __construct($connect) {
$this->connect = $connect;
}
function findById($poll_id) {
if (preg_match('/^[\w\d]{16}$/i', $poll_id)) {
return $this->connect->findPollById($poll_id);
}
return null;
}
function allCommentsByPollId($poll_id) {
return $this->connect->allCommentsByPollId($poll_id);
}
function allUserVotesByPollId($poll_id) {
return $this->connect->allUserVotesByPollId($poll_id);
}
function allSlotsByPollId($poll_id) {
return $this->connect->allSlotsByPollId($poll_id);
}
public function updateVote($poll_id, $vote_id, $choices) {
$choices = implode($choices);
return $this->connect->updateVote($poll_id, $vote_id, $choices);
}
function addVote($poll_id, $name, $choices) {
$choices = implode($choices);
return $this->connect->insertVote($poll_id, $name, $choices);
}
function computeBestMoments($votes) {
$result = [];
foreach ($votes as $vote) {
$choices = str_split($vote->reponses);
foreach ($choices as $i=>$choice) {
if (empty($result[$i])) {
$result[$i] = 0;
}
if ($choice == 2) {
$result[$i]++;
}
}
}
return $result;
}
function splitSlots($slots) {
$splitted = array();
foreach ($slots as $slot) {
$ex = explode('@', $slot->sujet);
$obj = new \stdClass();
$obj->day = $ex[0];
$obj->moments = explode(',', $ex[1]);
$splitted[] = $obj;
}
return $splitted;
}
function splitVotes($votes) {
$splitted = array();
foreach ($votes as $vote) {
$obj = new \stdClass();
$obj->id = $vote->id_users;
$obj->name = $vote->nom;
$obj->choices = str_split($vote->reponses);
$splitted[] = $obj;
}
return $splitted;
}
}

View File

@ -24,7 +24,6 @@ if (ini_get('date.timezone') == '') {
} }
include_once __DIR__ . '/constants.php'; include_once __DIR__ . '/constants.php';
include_once __DIR__ . '/i18n.php'; include_once __DIR__ . '/i18n.php';
include_once __DIR__ . '/studs.inc.php';
// Autoloading of dependencies with Composer // Autoloading of dependencies with Composer
require_once __DIR__ . '/../../vendor/autoload.php'; require_once __DIR__ . '/../../vendor/autoload.php';

View File

@ -1,10 +0,0 @@
<?php
function countStuds($subjects)
{
$nb = 0;
foreach($subjects as $subject) {
$nb += substr_count($subject->sujet, ',')+1;
}
return $nb;
}

100
studs.php
View File

@ -17,59 +17,21 @@
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
*/ */
use Framadate\Services\PollService; use Framadate\Services\PollService;
use Framadate\Services\InputService;
use Framadate\Utils; use Framadate\Utils;
use Framadate\Message;
include_once __DIR__ . '/app/inc/init.php'; include_once __DIR__ . '/app/inc/init.php';
/* Functions */ /* Variables */
/* --------- */ /* --------- */
$message = null;
function split_slots($slots) {
$splitted = array();
foreach ($slots as $slot) {
$ex = explode('@', $slot->sujet);
$obj = new \stdClass();
$obj->day = $ex[0];
$obj->moments = explode(',', $ex[1]);
$splitted[] = $obj;
}
return $splitted;
}
function split_votes($votes) {
$splitted = array();
foreach ($votes as $vote) {
$obj = new \stdClass();
$obj->id = $vote->id_users;
$obj->name = $vote->nom;
$obj->choices = str_split($vote->reponses);
$splitted[] = $obj;
}
return $splitted;
}
function computeBestMoments($votes) {
$result = [];
foreach ($votes as $vote) {
$choices = str_split($vote->reponses);
foreach ($choices as $i=>$choice) {
if (empty($result[$i])) {
$result[$i] = 0;
}
if ($choice == 2) {
$result[$i]++;
}
}
}
return $result;
}
/* Services */ /* Services */
/*----------*/ /*----------*/
$pollService = new PollService($connect); $pollService = new PollService($connect);
$inputService = new InputService();
/* PAGE */ /* PAGE */
/* ---- */ /* ---- */
@ -78,7 +40,6 @@ if(!empty($_GET['poll'])) {
$poll_id = filter_input(INPUT_GET, 'poll', FILTER_VALIDATE_REGEXP, ['options'=>['regexp'=>'/^[a-z0-9]+$/']]); $poll_id = filter_input(INPUT_GET, 'poll', FILTER_VALIDATE_REGEXP, ['options'=>['regexp'=>'/^[a-z0-9]+$/']]);
} }
$poll = $pollService->findById($poll_id); $poll = $pollService->findById($poll_id);
if (!$poll) { if (!$poll) {
@ -96,27 +57,47 @@ if (!empty($_POST['edit_vote'])) {
} }
// Something to save (edit or add)
if (!empty($_POST['save'])) { // Save edition of an old vote if (!empty($_POST['save'])) { // Save edition of an old vote
$editedVote = filter_input(INPUT_POST, 'save', FILTER_VALIDATE_INT); $editedVote = filter_input(INPUT_POST, 'save', FILTER_VALIDATE_INT);
$newChoices = []; $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options'=>['regexp'=>'/^[012]$/']]);
// TODO Do this verification into a Service (maybe called 'InputService') if (empty($name)) {
foreach($_POST['choices'] as $id=>$choice) { $message = new Message('danger', _('Name is incorrect.'));
$choice = filter_var($choice, FILTER_VALIDATE_REGEXP, ['options'=>['regexp'=>'/^[012]$/']]); }
if ($choice !== false) { if (count($choices) != count($_POST['choices'])) {
$newChoices[$id] = $choice; $message = new Message('danger', _('There is a problem with your choices.'));
}
} }
if (count($newChoices) == count($_POST['choices'])) { if ($message == null) {
$result = $pollService->updatePoll($poll_id, $editedVote, $newChoices); // Update vote
$result = $pollService->updateVote($poll_id, $editedVote, $choices);
if ($result) { if ($result) {
$message = ['type'=>'success', 'message'=>_('Update vote successfully!')]; $message = new Message('success', _('Update vote successfully!'));
} else { } else {
$message = ['type'=>'success', 'message'=>_('Update vote successfully!')]; $message = new Message('danger', _('Update vote failed!'));
}
}
} elseif (isset($_POST['save'])) { // Add a new vote
$name = filter_input(INPUT_POST, 'name', FILTER_VALIDATE_REGEXP, ['options'=>['regexp'=>'/^[a-z0-9_ -]+$/i']]);
$choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options'=>['regexp'=>'/^[012]$/']]);
if (empty($name)) {
$message = new Message('danger', _('Name is incorrect.'));
}
if (count($choices) != count($_POST['choices'])) {
$message = new Message('danger', _('There is a problem with your choices.'));
}
if ($message == null) {
// Add vote
$result = $pollService->addVote($poll_id, $name, $choices);
if ($result) {
$message = new Message('success', _('Update vote successfully!'));
} else {
$message = new Message('danger', _('Update vote failed!'));
} }
} }
} elseif (isset($_POST[''])) { // Add a new vote
} }
// Retrieve data // Retrieve data
@ -129,11 +110,12 @@ $comments = $pollService->allCommentsByPollId($poll_id);
$smarty->assign('poll_id', $poll_id); $smarty->assign('poll_id', $poll_id);
$smarty->assign('poll', $poll); $smarty->assign('poll', $poll);
$smarty->assign('title', _('Poll') . ' - ' . $poll->title); $smarty->assign('title', _('Poll') . ' - ' . $poll->title);
$smarty->assign('slots', split_slots($slots)); $smarty->assign('slots', $pollService->splitSlots($slots));
$smarty->assign('votes', split_votes($votes)); $smarty->assign('votes', $pollService->splitVotes($votes));
$smarty->assign('best_moments', computeBestMoments($votes)); $smarty->assign('best_moments', $pollService->computeBestMoments($votes));
$smarty->assign('comments', $comments); $smarty->assign('comments', $comments);
$smarty->assign('editingVoteId', $editingVoteId); $smarty->assign('editingVoteId', $editingVoteId);
$smarty->assign('message', $message);
//Utils::debug(computeBestMoments($votes));exit; //Utils::debug(computeBestMoments($votes));exit;

View File

@ -1,4 +1,4 @@
</main> </main>
</div> <!-- .container --> </div> <!-- .container -->
</body> </body>
</html> </html>

View File

@ -5,6 +5,10 @@
{* Global informations about the current poll *} {* Global informations about the current poll *}
{if !empty($message)}
<div class="alert alert-{$message->type}" role="alert">{$message->message}</div>
{/if}
<div class="jumbotron"> <div class="jumbotron">
<div class="row"> <div class="row">
<div class="col-md-7"> <div class="col-md-7">
@ -12,7 +16,7 @@
</div> </div>
<div class="col-md-5"> <div class="col-md-5">
<div class="btn-group pull-right"> <div class="btn-group pull-right">
<button onclick="javascript:print(); return false;" class="btn btn-default"><span class="glyphicon glyphicon-print"></span>{_('Print')}</button> <button onclick="print(); return false;" class="btn btn-default"><span class="glyphicon glyphicon-print"></span>{_('Print')}</button>
<a href="{$SERVER_URL}export.php?poll={$poll_id}&mode=csv" class="btn btn-default"><span class="glyphicon glyphicon-download-alt"></span>{_('Export to CSV')}</a> <a href="{$SERVER_URL}export.php?poll={$poll_id}&mode=csv" class="btn btn-default"><span class="glyphicon glyphicon-download-alt"></span>{_('Export to CSV')}</a>
</div> </div>
</div> </div>
@ -172,7 +176,7 @@
<td class="bg-info" style="padding:5px"> <td class="bg-info" style="padding:5px">
<div class="input-group input-group-sm"> <div class="input-group input-group-sm">
<span class="input-group-addon"><span class="glyphicon glyphicon-user"></span></span> <span class="input-group-addon"><span class="glyphicon glyphicon-user"></span></span>
<input type="text" id="nom" name="nom" class="form-control" title="{_('Your name')}" placeholder="{_('Your name')}" /> <input type="text" id="name" name="name" class="form-control" title="{_('Your name')}" placeholder="{_('Your name')}" />
</div> </div>
</td> </td>
{$i = 0} {$i = 0}
@ -181,19 +185,19 @@
<td class="bg-info" headers="M{$headersM[$i]} D{$headersD[$i]} H{$i}"> <td class="bg-info" headers="M{$headersM[$i]} D{$headersD[$i]} H{$i}">
<ul class="list-unstyled choice"> <ul class="list-unstyled choice">
<li class="yes"> <li class="yes">
<input type="radio" id="y-choice-{$i}" name="choice{$i}" value="2" /> <input type="radio" id="y-choice-{$i}" name="choices[{$i}]" value="2" />
<label class="btn btn-default btn-xs" for="y-choice-{$i}" title="{_('Vote yes for')} {$slot->day|date_format:$date_format.txt_short} - {$moment}"> <label class="btn btn-default btn-xs" for="y-choice-{$i}" title="{_('Vote yes for')} {$slot->day|date_format:$date_format.txt_short} - {$moment}">
<span class="glyphicon glyphicon-ok"></span><span class="sr-only">{_('Yes')}</span> <span class="glyphicon glyphicon-ok"></span><span class="sr-only">{_('Yes')}</span>
</label> </label>
</li> </li>
<li class="ifneedbe"> <li class="ifneedbe">
<input type="radio" id="i-choice-{$i}" name="choice{$i}" value="1" /> <input type="radio" id="i-choice-{$i}" name="choices[{$i}]" value="1" />
<label class="btn btn-default btn-xs" for="i-choice-{$i}" title="{_('Vote ifneedbe for')} {$slot->day|date_format:$date_format.txt_short} - {$moment}"> <label class="btn btn-default btn-xs" for="i-choice-{$i}" title="{_('Vote ifneedbe for')} {$slot->day|date_format:$date_format.txt_short} - {$moment}">
(<span class="glyphicon glyphicon-ok"></span>)<span class="sr-only">{_('Ifneedbe')}</span> (<span class="glyphicon glyphicon-ok"></span>)<span class="sr-only">{_('Ifneedbe')}</span>
</label> </label>
</li> </li>
<li class="no"> <li class="no">
<input type="radio" id="n-choice{$i}" name="choice{$i}" value="0" checked/> <input type="radio" id="n-choice{$i}" name="choices[{$i}]" value="0" checked/>
<label class="btn btn-default btn-xs" for="n-choice-{$i}" title="{_('Vote no for')} {$slot->day|date_format:$date_format.txt_short} - {$moment}"> <label class="btn btn-default btn-xs" for="n-choice-{$i}" title="{_('Vote no for')} {$slot->day|date_format:$date_format.txt_short} - {$moment}">
<span class="glyphicon glyphicon-ban-circle"></span><span class="sr-only">{_('No')}</span> <span class="glyphicon glyphicon-ban-circle"></span><span class="sr-only">{_('No')}</span>
</label> </label>
@ -203,7 +207,7 @@
{$i = $i+1} {$i = $i+1}
{/foreach} {/foreach}
{/foreach} {/foreach}
<td><button type="submit" class="btn btn-success btn-sm" name="add_vote" title="{_('Save the choices')}">{_('Save')}</button></td> <td><button type="submit" class="btn btn-success btn-sm" name="save" title="{_('Save the choices')}">{_('Save')}</button></td>
</tr> </tr>
{/if} {/if}