From fae91f6f3eff85e78b6a1fdcad6ce9470c831354 Mon Sep 17 00:00:00 2001
From: Olivier PEREZ <olivier@olivierperez.fr>
Date: Fri, 5 Dec 2014 01:08:38 +0100
Subject: [PATCH] Refactor poll creation

* Rename fields in Sondage table
* Add field "editable" which tells when users can edit their votes
* PDO : Configure 2 options (FETCH_OBJ + ERRMODE_EX)
* "formatsondage" does contains "+" (or not) anymore
---
 app/classes/Framadate/Form.php    | 14 +++---
 app/classes/Framadate/FramaDB.php |  2 +
 app/classes/Framadate/Utils.php   | 10 ++---
 choix_date.php                    | 74 +++++++++++--------------------
 creation_sondage.php              | 28 ++++++++----
 infos_sondage.php                 | 28 +++++-------
 install.mysql.sql                 | 23 +++++-----
 7 files changed, 81 insertions(+), 98 deletions(-)

diff --git a/app/classes/Framadate/Form.php b/app/classes/Framadate/Form.php
index 641f0f11..79d1c68c 100644
--- a/app/classes/Framadate/Form.php
+++ b/app/classes/Framadate/Form.php
@@ -11,16 +11,16 @@ class Form
     public $formatsondage;
     public $champdatefin;
     public $choix_sondage;
-    public $studsplus;
-    public $mailsonde;
-    public $toutchoix;
-    public $totalchoixjour;
-    public $horaires;
 
     /**
-     * Step of form
+     * Tells if users can modify their choices.
      */
-    public $step = 0;
+    public $editable;
+    
+    /**
+     * If true, notify poll administrator when new vote is made.
+     */
+    public $receiveNewVotes;
 
     /**
      * List of available choices
diff --git a/app/classes/Framadate/FramaDB.php b/app/classes/Framadate/FramaDB.php
index a10884ef..60f5b62b 100644
--- a/app/classes/Framadate/FramaDB.php
+++ b/app/classes/Framadate/FramaDB.php
@@ -11,6 +11,8 @@ class FramaDB
     function __construct($connection_string, $user, $password)
     {
         $this->pdo = new \PDO($connection_string, $user, $password);
+        $this->pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ);
+        $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
     }
 
     function areTablesCreated()
diff --git a/app/classes/Framadate/Utils.php b/app/classes/Framadate/Utils.php
index c48aff2b..ae431c01 100644
--- a/app/classes/Framadate/Utils.php
+++ b/app/classes/Framadate/Utils.php
@@ -239,7 +239,7 @@ class Utils
         $prepared = $connect->prepare('DELETE FROM comments WHERE id_sondage = ?');
         $prepared->execute(array($poll_id));
 
-        $prepared = $connect->prepare('DELETE FROM sondage WHERE id_sondage = ?');
+        $prepared = $connect->prepare('DELETE FROM sondage WHERE poll_id = ?');
         $prepared->execute(array($poll_id));
         
     }
@@ -247,15 +247,13 @@ class Utils
     public static function cleaningOldPolls($log_txt) {
         global $connect;
         
-        $resultSet = $connect->query('SELECT id_sondage, format, nom_admin, mail_admin FROM sondage WHERE date_fin < NOW() LIMIT 20');
+        $resultSet = $connect->query('SELECT poll_id, format, admin_name FROM sondage WHERE end_date < NOW() LIMIT 20');
         $toClean = $resultSet->fetchAll(\PDO::FETCH_CLASS);
-        
-        echo '<pre>toClean:'.print_r($toClean, true).'</pre>';
 
         $connect->beginTransaction();
         foreach ($toClean as $row) {
-            if (self::removeSondage($row->id_sondage)) {
-                error_log(date('H:i:s d/m/Y:') . ' EXPIRATION: '. $row->id_sondage."\t".$row->format."\t".$row->nom_admin."\t".$row->mail_admin."\n", 3, $log_txt);
+            if (self::removeSondage($row->poll_id)) {
+                error_log(date('H:i:s d/m/Y:') . ' EXPIRATION: '. $row->poll_id."\t".$row->format."\t".$row->admin_name."\n", 3, $log_txt);
             }
         }
         $connect->commit();
diff --git a/choix_date.php b/choix_date.php
index df0ac983..200b8a91 100644
--- a/choix_date.php
+++ b/choix_date.php
@@ -45,58 +45,37 @@ if (!isset($_SESSION['form']->titre) || !isset($_SESSION['form']->nom) || (($con
 } else {
     // Step 4 : Data prepare before insert in DB
     if (Utils::issetAndNoEmpty('confirmation')) {
-        $temp_results = array();
-        $choixdate='';
-        if (Utils::issetAndNoEmpty('totalchoixjour', $_SESSION) === true) {
-            for ($i = 0; $i < count($_SESSION["totalchoixjour"]); $i++) {
-                if(count($_SESSION['horaires'.$i])!=0) {
-                    for ($j=0;$j< min(count($_SESSION['horaires'.$i]),12);$j++) {
-                        if ($_SESSION['horaires'.$i][$j]!="") {
-                            array_push($temp_results, $_SESSION["totalchoixjour"][$i].'@'.$_SESSION['horaires'.$i][$j]);
-                        } else {
-                            array_push($temp_results, $_SESSION["totalchoixjour"][$i]);
-                        }
-                    }
-                } else {
-                    array_push($temp_results, $_SESSION["totalchoixjour"][$i]);
-                }
-            }
-
-        }
-
-        // Sort and remove doublons
-        $temp_results = array_unique($temp_results);
-        sort($temp_results);
-        for ($i=0;$i<count($temp_results);$i++) {
-            if (isset($temp_results[$i])) {
-                $choixdate.=','.$temp_results[$i];
-            }
-        }
-
-        $_SESSION['form']->toutchoix=substr($choixdate,1);
-
-        // Expiration date → 6 months after last day if not filled or in bad format
-        $_SESSION['form']->champdatefin=end($temp_results)+(86400 * $config['default_poll_duration']);
 
-        if (Utils::issetAndNoEmpty('champdatefin')) {
-            $registredate = explode("/",$_POST["champdatefin"]);
-            if (is_array($registredate) == true && count($registredate) == 3) {
-                $time = mktime(0,0,0,$registredate[1],$registredate[0],$registredate[2]);
-                if ($time > time() + (24*60*60)) {
+        // Define expiration date
+        if (!empty($_POST['champdatefin']))
+        {
+            $registredate = explode('/', $_POST['champdatefin']);
+            if (is_array($registredate) && count($registredate) == 3)
+            {
+                $time = mktime(0,0,0, $registredate[1], $registredate[0], $registredate[2]);
+                if ($time > time() + (24*60*60))
+                {
                     $_SESSION['form']->champdatefin=$time;
                 }
             }
+        } 
+        
+        if(empty($_SESSION['form']->champdatefin))
+        {
+            // By default, expiration date is 6 months after last day
+            $_SESSION['form']->champdatefin=end($temp_results)+(86400 * $config['default_poll_duration']);
         }
-
+        
         $admin_poll_id = ajouter_sondage(
             $_SESSION['form']->titre,
             $_SESSION['form']->commentaires,
             $_SESSION['form']->nom,
             $_SESSION['form']->adresse,
             $_SESSION['form']->formatsondage,
+            $_SESSION['form']->editable,
             $_SESSION['form']->champdatefin,
-            $_SESSION['form']->mailsonde,
-            $_SESSION['form']->toutchoix
+            $_SESSION['form']->receiveNewVotes,
+            $_SESSION['form']->getChoices()
         );
         
         // Clean Form data in $_SESSION
@@ -137,9 +116,9 @@ if (!isset($_SESSION['form']->titre) || !isset($_SESSION['form']->nom) || (($con
     }
 
     //le format du sondage est DATE
-    $_SESSION['form']->formatsondage = "D".$_SESSION['form']->studsplus;
+    $_SESSION['form']->formatsondage = 'D';
 
-    // Step 3/3 : Confirm poll creation
+    // Step 3/4 : Confirm poll creation
     if (Utils::issetAndNoEmpty('choixheures') && !isset($_SESSION['form']->totalchoixjour)) {
 
         Utils::print_header ( _("Removal date and confirmation (3 on 3)") );
@@ -147,7 +126,7 @@ if (!isset($_SESSION['form']->titre) || !isset($_SESSION['form']->nom) || (($con
 
         $_SESSION['form']->sortChoices();
         $last_date = $_SESSION['form']->lastChoice()->getName();
-        $removal_date = utf8_encode(strftime($date_format['txt_full'], $last_date + (86400 * $config['default_poll_duration'])));
+        $removal_date = $last_date + (86400 * $config['default_poll_duration']);
 
         // Summary
         $summary = '<ul>';
@@ -173,13 +152,13 @@ if (!isset($_SESSION['form']->titre) || !isset($_SESSION['form']->nom) || (($con
                 '. $summary .'
             </div>
             <div class="alert alert-info clearfix">
-                <p>' . _("Your poll will be automatically removed "). $config['default_poll_duration'] . ' ' . _("days") ._(" after the last date of your poll:") . ' <strong>'.$removal_date.'</strong>.<br />' . _("You can fix another removal date for it.") .'</p>
+                <p>' . _("Your poll will be automatically removed "). $config['default_poll_duration'] . ' ' . _("days") . ' ' ._("after the last date of your poll") . '.<br />' . _("You can fix another removal date for it.") .'</p>
                 <div class="form-group">
-                    <label for="champdatefin" class="col-sm-5 control-label">'. _("Removal date (optional)") .'</label>
+                    <label for="champdatefin" class="col-sm-5 control-label">'. _("Removal date") .'</label>
                     <div class="col-sm-6">
                         <div class="input-group date">
                             <span class="input-group-addon"><i class="glyphicon glyphicon-calendar text-info"></i></span>
-                            <input type="text" class="form-control" id="champdatefin" data-date-format="'. _("dd/mm/yyyy") .'" aria-describedby="dateformat" name="champdatefin" value="" size="10" maxlength="10" placeholder="'. _("dd/mm/yyyy") .'" />
+                            <input type="text" class="form-control" id="champdatefin" data-date-format="'. _("dd/mm/yyyy") .'" aria-describedby="dateformat" name="champdatefin" value="'.strftime('%d/%m/%Y', $removal_date).'" size="10" maxlength="10" placeholder="'. _("dd/mm/yyyy") .'" />
                         </div>
                     </div>
                     <span id="dateformat" class="sr-only">'. _("(dd/mm/yyyy)") .'</span>
@@ -200,11 +179,10 @@ if (!isset($_SESSION['form']->titre) || !isset($_SESSION['form']->nom) || (($con
         </div>
     </div>
     </form>'."\n";
-//exit('<pre>POST<br/>'.print_r($_POST, true).'<hr/>SESSION<br/>'.print_r($_SESSION, true).'</pre>');
 
         bandeau_pied();
 
-    // Step 2/3 : Select dates of the poll
+    // Step 2/4 : Select dates of the poll
     } else {
         Utils::print_header ( _("Poll dates (2 on 3)") );
         bandeau_titre(_("Poll dates (2 on 3)"));
diff --git a/creation_sondage.php b/creation_sondage.php
index 1226637d..77ab9e0d 100644
--- a/creation_sondage.php
+++ b/creation_sondage.php
@@ -38,24 +38,34 @@ function random($car)
     return $string;
 }
 
-function ajouter_sondage($title, $comment, $adminName, $adminMail, $format, $endDate, $mailsonde, $slots)
+function ajouter_sondage($title, $comment, $adminName, $adminMail, $format, $editable, $endDate, $receiveNewVotes, $choices)
 {
     global $connect;
     global $config; 
+    
+    // Generate poll ids
     $poll_id = random(16);
     $admin_poll_id = $poll_id.random(8);
+    
+    // Insert poll + slots
+    $connect->beginTransaction();
 
-    $date_fin = $_SESSION['champdatefin']; // provided by choix_autre.php or choix_date.php
-    $_SESSION['champdatefin'] = ''; //clean param cause 2 polls created by the same user in the same session can be affected by this param during the 2nd creation.
     $sql = 'INSERT INTO sondage
-          (id_sondage, commentaires, mail_admin, nom_admin, titre, id_sondage_admin, date_fin, format, mailsonde)
-          VALUES (?,?,?,?,?,?,?,?)';
+          (poll_id, admin_poll_id, title, comment, admin_name, admin_mail, end_date, format, editable, receiveNewVotes)
+          VALUES (?,?,?,?,?,?,FROM_UNIXTIME(?),?,?,?)';
     $prepared = $connect->prepare($sql);
-    $res = $prepared->execute(array($poll_id, $comment, $adminMail, $adminName, $title, $admin_poll_id, $format, $mailsonde));
+    $prepared->execute(array($poll_id, $admin_poll_id, $title, $comment, $adminName, $adminMail, $endDate, $format, $editable, $receiveNewVotes));
+
+    $prepared = $connect->prepare('INSERT INTO sujet_studs (id_sondage, sujet) VALUES (?, ?)');
+    foreach ($choices as $choice) {
+        foreach ($choice->getSlots() as $slot) {
+            $prepared->execute(array($poll_id, $choice->getName().'@'.$slot));
+        }
+    }
 
-    $prepared = $connect->prepare('INSERT INTO sujet_studs values (?, ?)');
-    $prepared->execute(array($poll_id, $slots));
+    $connect->commit();
 
+    // Send confirmation by mail if enabled
     if($config['use_smtp'] === true){
         $message = _("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.");
         $message .= "\n\n";
@@ -74,7 +84,7 @@ function ajouter_sondage($title, $comment, $adminName, $adminMail, $format, $end
         }
     }
     
-    error_log(date('H:i:s d/m/Y:') . ' CREATION: '.$poll_id."\t".$format."\t".$adminName."\t".$adminMail."\t \t".$slots."\n", 3, 'admin/logs_studs.txt');
+    error_log(date('H:i:s d/m/Y:') . ' CREATION: '.$poll_id."\t".$format."\t".$adminName."\t".$adminMail."\n", 3, 'admin/logs_studs.txt');
 
     return $admin_poll_id;
 }
diff --git a/infos_sondage.php b/infos_sondage.php
index 99f27c3c..dc773bf2 100644
--- a/infos_sondage.php
+++ b/infos_sondage.php
@@ -41,7 +41,7 @@ if ((isset($_GET['choix_sondage']) && $_GET['choix_sondage'] == 'date') ||
 
 // On teste toutes les variables pour supprimer l'ensemble des warnings PHP
 // On transforme en entites html les données afin éviter les failles XSS
-$post_var = array('poursuivre', 'titre', 'nom', 'adresse', 'commentaires', 'studsplus', 'mailsonde', 'creation_sondage_date', 'creation_sondage_autre');
+$post_var = array('poursuivre', 'titre', 'nom', 'adresse', 'commentaires', 'editable', 'receiveNewVotes', 'creation_sondage_date', 'creation_sondage_autre');
 foreach ($post_var as $var) {
     if (isset($_POST[$var]) === true) {
         $$var = htmlentities($_POST[$var], ENT_QUOTES, 'UTF-8');
@@ -55,8 +55,6 @@ $erreur_adresse = false;
 $erreur_injection_titre = false;
 $erreur_injection_nom = false;
 $erreur_injection_commentaires = false;
-$cocheplus = '';
-$cochemail = '';
 
 #tests
 if (Utils::issetAndNoEmpty("poursuivre")){
@@ -64,8 +62,8 @@ if (Utils::issetAndNoEmpty("poursuivre")){
     $_SESSION['form']->nom = $nom;
     $_SESSION['form']->adresse = $adresse;
     $_SESSION['form']->commentaires = $commentaires;
-    $_SESSION['form']->studsplus = ($studsplus !== null) ? '+' : $_SESSION['form']->studsplus = '';
-    $_SESSION['form']->mailsonde = ($mailsonde !== null) ? true : false;
+    $_SESSION['form']->editable = ($editable !== null) ? true : false;
+    $_SESSION['form']->receiveNewVotes = ($receiveNewVotes !== null) ? true : false;
 
     if ($config['use_smtp']==true){
         if (Utils::isValidEmail($adresse) === false) {
@@ -86,7 +84,7 @@ if (Utils::issetAndNoEmpty("poursuivre")){
     }
 
     // Si pas d'erreur dans l'adresse alors on change de page vers date ou autre
-    if($config['use_smtp']==true){
+    if($config['use_smtp'] == true){
         $email_OK = $adresse && !$erreur_adresse;
     } else{
         $email_OK = true;
@@ -189,19 +187,15 @@ if (USE_REMOTE_USER && isset($_SERVER['REMOTE_USER'])) {
 }
 
 // Checkbox checked ?
-if (!$_SESSION['form']->studsplus && !Utils::issetAndNoEmpty('creation_sondage_date') && !Utils::issetAndNoEmpty('creation_sondage_autre')) {
-    $_SESSION['form']->studsplus="+";
+if ($_SESSION['form']->editable) {
+    $editable = 'checked';
 }
 
-if ($_SESSION['form']->studsplus=="+") {
-    $cocheplus="checked";
+if ($_SESSION['form']->receiveNewVotes) {
+    $receiveNewVotes = 'checked';
 }
 
-if ($_SESSION['form']->mailsonde) {
-    $cochemail="checked";
-}
-
-// Affichage du formulaire
+// Display form
 echo '
 <div class="row">
     <div class="col-md-8 col-md-offset-2" >
@@ -247,7 +241,7 @@ echo '
             <div class="col-sm-offset-1 col-sm-11">
               <div class="checkbox">
                 <label>
-                    <input type=checkbox name=studsplus '.$cocheplus.' id="studsplus">'. _("Voters can modify their vote themselves.") .'
+                    <input type=checkbox name="editable" '.$editable.' id="editable">'. _("Voters can modify their vote themselves.") .'
                 </label>
               </div>
             </div>
@@ -257,7 +251,7 @@ if($config['use_smtp']==true){
         <div class="col-sm-offset-1 col-sm-11">
           <div class="checkbox">
             <label>
-                <input type=checkbox name=mailsonde '.$cochemail.' id="mailsonde">'. _("To receive an email for each new vote.") .'
+                <input type=checkbox name="receiveNewVotes" '.$receiveNewVotes.' id="receiveNewVotes">'. _("To receive an email for each new vote.") .'
             </label>
           </div>
         </div>
diff --git a/install.mysql.sql b/install.mysql.sql
index c873a75d..3980fd7b 100644
--- a/install.mysql.sql
+++ b/install.mysql.sql
@@ -23,18 +23,19 @@ CREATE TABLE IF NOT EXISTS `comments` (
 --
 
 CREATE TABLE IF NOT EXISTS `sondage` (
-  `id_sondage` char(16) NOT NULL,
-  `commentaires` text,
-  `mail_admin` varchar(128) DEFAULT NULL,
-  `nom_admin` varchar(64) DEFAULT NULL,
-  `titre` text,
-  `id_sondage_admin` char(24) DEFAULT NULL,
-  `date_creation` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  `date_fin` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
-  `format` varchar(2) DEFAULT NULL,
-  `mailsonde` tinyint(1) DEFAULT '0',
+  `poll_id` char(16) NOT NULL,
+  `admin_poll_id` char(24) DEFAULT NULL,
+  `title` text NOT NULL,
+  `comment` text,
+  `admin_name` varchar(64) DEFAULT NULL,
+  `admin_mail` varchar(128) DEFAULT NULL,
+  `creation_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `end_date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
+  `format` varchar(1) DEFAULT NULL,
+  `editable` tinyint(1) DEFAULT '0',
+  `receiveNewVotes` tinyint(1) DEFAULT '0',
   `statut` int(11) NOT NULL DEFAULT '1' COMMENT '1 = actif ; 0 = inactif ; ',
-  UNIQUE KEY `id_sondage` (`id_sondage`)
+  UNIQUE KEY `poll_id` (`poll_id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
 -- --------------------------------------------------------
-- 
GitLab