diff --git a/.gitignore b/.gitignore index 004467b..580102f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,13 @@ .htaccess -admin/.htaccess -admin/.htpasswd +.htpasswd admin/logs_studs.txt composer.phar framanav nav -app/inc/constants.php +app/inc/config.php vendor +cache/ +tpl_c/ # Temp files *~ @@ -15,3 +16,8 @@ vendor # Cache Thumbs.db +# IDE +.settings/ +.project +.idea/ +*.iml diff --git a/README.md b/README.md index e57038b..798b3de 100644 --- a/README.md +++ b/README.md @@ -7,112 +7,179 @@ If you want to work with us, **fork us on [git.framasoft.org](https://git.framas Si vous souhaitez travailler avec nous, **forkez-nous sur [git.framasoft.org](https://git.framasoft.org)**. (l'inscription n'est pas nécessaire, vous pouvez vous connecter avec votre compte Github) * * * -![English:](http://upload.wikimedia.org/wikipedia/commons/thumb/a/ae/Flag_of_the_United_Kingdom.svg/20px-Flag_of_the_United_Kingdom.svg.png) -This software is governed by the CeCILL-B license. If a copy of this license -is not distributed with this file, you can obtain one at -[http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt](http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt) +Framadate est un fork du projet STUdS : https://sourcesup.cru.fr/projects/studs/ -Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ -Authors of Framadate/OpenSondate: [Framasoft](https://git.framasoft.org/framasoft/framadate) +Framadate est le projet qui motorise framadate.org pour framasoft.org -![Français :](http://upload.wikimedia.org/wikipedia/commons/thumb/c/c3/Flag_of_France.svg/20px-Flag_of_France.svg.png) -Ce logiciel est régi par la licence CeCILL-B. Si une copie de cette licence -ne se trouve pas avec ce fichier vous pouvez l'obtenir sur -[http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.txt](http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.txt) +Les auteurs principaux de Framadate sont : +- Simon LEBLANC +- Pierre-Yves GOSSET -Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ -Auteurs de Framadate/OpenSondage : [Framasoft](https://git.framasoft.org/framasoft/framadate) +Les auteurs principaux du projet STUdS sont : +- Guilhem BORGHESI +- Raphaël DROZ -* * * -#Framadate -[Framadate](https://framadate.org) est un fork du projet [STUdS](https://sourcesup.cru.fr/projects/studs/). -Il est développé par l'association [Framasoft](http://framasoft.org). +========================================================================== -##Fichiers de l'application +Université de Strasbourg - Direction Informatique +Auteur : Guilhem BORGHESI +Création : Février 2008 -### Administration -* `/admin` - Le répertoire réservé à l'administrateur de l'application -* `admin/index.php` - La page présentant tous les sondages actuellement dans la base à l'administrateur -* `admin/log_studs.txt` - Le fichier contenant un historique de toutes les creations/suppressions de sondage dans la base +borghesi@unistra.fr -* `install/` (pas utilisé - en développement) - Le répertoire qui contient les scripts chargés de simplifier la procédure d'installation -* `scripts/` (pas utilisé) - Le répertoire qui contient quelques vieux scripts pour la maintenance de l'application +Ce logiciel est régi par la licence CeCILL-B soumise au droit français et +respectant les principes de diffusion des logiciels libres. Vous pouvez +utiliser, modifier et/ou redistribuer ce programme sous les conditions +de la licence CeCILL-B telle que diffusée par le CEA, le CNRS et l'INRIA +sur le site "http://www.cecill.info". -### Application -* `app/inc/constants.php.template` - Le fichier contenant les constantes à changer en fonction de la machine locale -* `app/classes/Framadate/Utils.php` - Le fichier contenant quelques fonctions récurrentes de l'application -* `app/inc/i18n.php` - Le fichier contenant quelques fonctions récurrentes de l'application relatives à l'internationalisation -* `app/inc/init.php` - Le fichier qui charge les dépendances et ouvre la connexion à la base de données +Le fait que vous puissiez accéder à cet en-tête signifie que vous avez +pris connaissance de la licence CeCILL-B, et que vous en avez accepté les +termes. Vous pouvez trouver une copie de la licence dans le fichier LICENCE. -* `css/` - Les fichiers CSS de l'application (dont ceux de Bootstrap) -* `fonts/` - Les fichiers des icônes de Bootstrap -* `images/` - Logo et images de la page d'accueil -* `js/` - Les fichiers javascript de l'application (dont ceux de Bootstrap et de jQuery) +========================================================================== -* `locale/` +Université de Strasbourg - Direction Informatique +Author : Guilhem BORGHESI +Creation : Feb 2008 + +borghesi@unistra.fr + +This software is governed by the CeCILL-B license under French law and +abiding by the rules of distribution of free software. You can use, +modify and/ or redistribute the software under the terms of the CeCILL-B +license as circulated by CEA, CNRS and INRIA at the following URL +"http://www.cecill.info". + +The fact that you are presently reading this means that you have had +knowledge of the CeCILL-B license and that you accept its terms. You can +find a copy of this license in the file LICENSE. + +========================================================================== + +============================================================================= +Fichiers de l'application +============================================================================= + +index.php + La page d'accueil de STUdS +studs.php + La page de présentation de sondage +adminstuds.php + La page d'administration réservée à l'auteur du sondage +infos_sondage.php + La page (1/2) de création de sondage récupérant les informations générales +choix_date.php + La page de création (2/2) pour un sondage pour déterminer une date +choix_autre.php + La page de création (2/2) pour un sondage sur un sujet quelconque +creation_sondage.php + Le fichier qui récupérent les informations des pages précédentes pour procéder à l'insertion du nouveau sondage dans la base PostgreSQL +style.css + Le fichier CSS de style pour toute l'application +app/inc/constants.php + Le fichier contenant les constantes à changer en fonction de la machine locale +app/inc/functions.php + Le fichier contenant quelques fonctions récurrentes de l'application +app/inc/i18n.php + Le fichier contenant quelques fonctions récurrentes de l'application relatives à l'internationalisation +README + Ce fichier +INSTALL + Le fichier contenant les informations d'installation sur l'application +CHANGELOG + Le fichier contenant toutes les modifications de l'application entre les différentes versions +contacts.php + La page permettant aux usagers de poser une question à l'administrateur de l'application +apropos.php + La page expliquant les détails techniques relatifs à l'application et les dernieres modifications et celles à venir sur l'application +bandeaux.php + Le fichier contenant tous les bandeaux des pages PHP de l'application +favicon.ico + L'icone de favoris de l'application +sources.php + La page qui propose les sources de l'application +exportics.php + Le fichier d'export de la meilleure date au format iCAL (fichier .ICS) +exportcsv.php + Le fichier d'export de tous le tableau des participants avec leurs réponses dans un tableur (format .CSV) +exportpdf.php + Le fichier d'export de la lettre de convocation que le créateur du sondage pourra envoyer aux participants (format .PDF) + +admin/ + Le répertoire réservé à l'administrateur de l'application +admin/.htaccess + Le fichier gérant les droits restreints du répertoire ADMIN +admin/.htpasswd + Le fichier contenant les passwd des logins ayant accès au répertoire ADMIN +admin/index.php + La page présentant tous les sondages actuellement dans la base à l'administrateur +admin/log_studs.txt + Le fichier contenant un historique de toutes les creations/suppressions de sondage dans la base + +errors/ + Le répertoire contenant toutes les pages d'erreurs +errors/error-forbidden.php + La page qui indique dans la charte graphique de l'application l'erreur "501 forbidden" +errors/maintenance.php + La page qui indique que l'application est en maintenance temporaire + +export/ + Le répertoire qui contient tous les exports ICS + +iCalcreator/ + Le répertoire qui contient les librairies d'export en iCal + +php2pdf/ + Le répertoire qui contient les librairies d'export en PDF + +scripts/ + Le répertoire qui contient tous les scripts de l'application + +sources/ + Le répertoire qui contient les sources de l'application disponible sur la page sources.php + +locale/ Le répertoire qui contient les fichiers de traduction modifiables (.po) et compilés (.mo) au format gettext -* `index.php` - La page d'accueil de STUdS -* `studs.php` - La page de présentation de sondage -* `adminstuds.php` - La page d'administration réservée à l'auteur du sondage -* `infos_sondage.php` - La page (1/2) de création de sondage récupérant les informations générales -* `choix_date.php` - La page de création (2/2) pour un sondage pour déterminer une date -* `choix_autre.php` - La page de création (2/2) pour un sondage sur un sujet quelconque -* `creation_sondage.php` - Le fichier qui récupérent les informations des pages précédentes pour procéder à l'insertion du nouveau sondage dans la base PostgreSQL +============================================================================= + Validations des pages +============================================================================= -* `bandeaux.php` - Le fichier contenant les éléments de l'entête et du pied de page de l'application -* `exportcsv.php` - Le fichier d'export de tous le tableau des participants avec leurs réponses dans un tableur (format .CSV) -* `favicon.ico` - L'icone de favoris de l'application +Toutes les pages de STUdS sont validées HTML 4.01 Strict. +La CSS de STUdS est validée CSS 2.1. -### Infos -* `AUTHORS.md` - Liste des principaux développeurs du logiciel -* `README.md` - Ce fichier -* `INSTALL.md` - Le fichier contenant les informations d'installation sur l'application -* `CHANGELOG.md` - Le fichier contenant la liste des principale modifications de l'application entre les différentes versions - -##Technologies utilisées +============================================================================= +Technologies utilisées +============================================================================= -- PHP 5.4.4, php-adodb, php-gettext, composer -- Bootstrap, jQuery, Bootstrap Datepicker -- MySQL -- Nginx, Apache +- PHP 5.4.4, php-fpdf, php-adodb, php-gettext +- PostgreSQL, mysql +- Apache +- iCalcreator - POedit +- Icônes : Deleket (http://deleket.deviantart.com/) et DryIcons (http://dryicons.com) -##Compatibilités des navigateurs -(Dernière mise à jour le 21 avril 2014) +============================================================================= +Compatibilités des navigateurs +Dernière mise à jour le 21 avril 2014 +============================================================================= - Firefox : Ubuntu 13.10/FF28 - Chrome : Ubuntu 13.10/Chromium33 - Opera (non testé) - Konqueror +- Links (non testé, inutile) - Safari (non testé) - IE : Win7/IE9 + +----------------- +Janvier 2008 +Guilhem BORGHESI +Université de Strasbourg + +Mai 2010 +Raphaël DROZ, raphael.droz@gmail.com + diff --git a/admin/index.php b/admin/index.php index 61335d5..28014ef 100644 --- a/admin/index.php +++ b/admin/index.php @@ -16,100 +16,9 @@ * Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) */ -namespace Framadate; -session_start(); -include_once __DIR__ . '/../app/inc/init.php'; -include_once __DIR__ . '/../bandeaux.php'; +require_once '../app/inc/init.php'; -// Ce fichier index.php se trouve dans le sous-repertoire ADMIN de Studs. Il sert à afficher l'intranet de studs -// pour modifier les sondages directement sans avoir reçu les mails. C'est l'interface d'aministration -// de l'application. - -// Affichage des balises standards -Utils::print_header( _("Polls administrator") ); -bandeau_titre(_("Polls administrator")); - -$sondage=$connect->Execute("select * from sondage"); - -echo' -
'."\n"; -// Test et affichage du bouton de confirmation en cas de suppression de sondage -while($dsondage = $sondage->FetchNextObject(false)) { - if (Utils::issetAndNoEmpty('supprimersondage'.$dsondage->id_sondage) === true) { - echo ' -
-

'. _("Confirm removal of the poll ") .'"'.$dsondage->id_sondage.'

-

-

-
'; - } - - // Traitement de la confirmation de suppression - if (Utils::issetAndNoEmpty('confirmesuppression'.$dsondage->id_sondage) === true) { - // On inclut la routine de suppression - $date=date('H:i:s d/m/Y'); - - if (Utils::remove_sondage($connect, $dsondage->id_sondage)) { - // ecriture des traces dans le fichier de logs - error_log($date . " SUPPRESSION: $dsondage->id_sondage\t$dsondage->format\t$dsondage->nom_admin\t$dsondage->mail_admin\n", 3, 'logs_studs.txt'); - } - } -} - -$sondage=$connect->Execute("select * from sondage WHERE date_fin > DATE_SUB(now(), INTERVAL 3 MONTH) ORDER BY date_fin ASC"); -$nbsondages=$sondage->RecordCount(); - -$btn_logs = (is_readable('logs_studs.txt')) ? ''. _("Logs") .'' : ''; - -echo '

' . $nbsondages. ' ' . _("polls in the database at this time") . $btn_logs .'

'."\n"; - -// tableau qui affiche tous les sondages de la base -echo ' - - - - - - - - - - '."\n"; - -$i = 0; -while($dsondage = $sondage->FetchNextObject(false)) { - /* possible en 1 bonne requête dans $sondage */ - $sujets=$connect->Execute( "select * from sujet_studs where id_sondage='$dsondage->id_sondage'"); - $dsujets=$sujets->FetchObject(false); - - $user_studs=$connect->Execute( "select * from user_studs where id_sondage='$dsondage->id_sondage'"); - $nbuser=$user_studs->RecordCount(); - - echo ' - - - - - - '; - - if (strtotime($dsondage->date_fin) > time()) { - echo ' - '; - } else { - echo ' - '; - } - echo ' - - - - - '."\n"; - $i++; -} - -echo '
'. _("Poll ID") .''. _("Format") .''. _("Title") .''. _("Author") .''. _("Email") .''. _("Expiration's date") .''. _("Users") .''. _("Actions") .'
'.$dsondage->id_sondage.''.$dsondage->format.''. stripslashes($dsondage->titre).''.stripslashes($dsondage->nom_admin).''.stripslashes($dsondage->mail_admin).''.date("d/m/y",strtotime($dsondage->date_fin)).''.date("d/m/y",strtotime($dsondage->date_fin)).''.$nbuser.'' . _("See the poll") . '' . _("Change the poll") . '
'."\n"; - -bandeau_pied(true); +$smarty->assign('title', _('Administration')); +$smarty->assign('logsAreReadable', is_readable('../' . LOG_FILE)); +$smarty->display('admin/index.tpl'); \ No newline at end of file diff --git a/admin/logs.php b/admin/logs.php new file mode 100644 index 0000000..e4be44d --- /dev/null +++ b/admin/logs.php @@ -0,0 +1,28 @@ +assign('title', _('Administration')); +$smarty->assign('logs', $content); +$smarty->display('admin/logs.tpl'); \ No newline at end of file diff --git a/admin/migration.php b/admin/migration.php new file mode 100644 index 0000000..9c34f97 --- /dev/null +++ b/admin/migration.php @@ -0,0 +1,107 @@ +allTables(); +$pdo = $connect->getPDO(); +$prefixedMigrationTable = Utils::table(MIGRATION_TABLE); + +if (!in_array($prefixedMigrationTable, $tables)) { + $pdo->exec(' +CREATE TABLE IF NOT EXISTS `' . $prefixedMigrationTable . '` ( + `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `name` TEXT NOT NULL, + `execute_date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) +) + ENGINE = MyISAM + DEFAULT CHARSET = utf8;'); +} + +$selectStmt = $pdo->prepare('SELECT id FROM ' . $prefixedMigrationTable . ' WHERE name=?'); +$insertStmt = $pdo->prepare('INSERT INTO ' . $prefixedMigrationTable . ' (name) VALUES (?)'); +$countSucceeded = 0; +$countFailed = 0; +$countSkipped = 0; + +// Loop on every Migration sub classes +$success = []; +$fail = []; +foreach ($migrations as $migration) { + $className = get_class($migration); + + // Check if $className is a Migration sub class + if (!$migration instanceof Migration) { + $smarty->assign('error', 'The class ' . $className . ' is not a sub class of Framadate\\Migration\\Migration.'); + $smarty->display('error.tpl'); + exit; + } + + // Check if the Migration is already executed + $selectStmt->execute([$className]); + $executed = $selectStmt->rowCount(); + $selectStmt->closeCursor(); + + if (!$executed && $migration->preCondition($pdo)) { + $migration->execute($pdo); + if ($insertStmt->execute([$className])) { + $countSucceeded++; + $success[] = $migration->description(); + } else { + $countFailed++; + $fail[] = $migration->description(); + } + } else { + $countSkipped++; + } + +} + +$countTotal = $countSucceeded + $countFailed + $countSkipped; + +$smarty->assign('success', $success); +$smarty->assign('fail', $fail); + +$smarty->assign('countSucceeded', $countSucceeded); +$smarty->assign('countFailed', $countFailed); +$smarty->assign('countSkipped', $countSkipped); +$smarty->assign('countTotal', $countTotal); +$smarty->assign('time', $total_time = round((microtime(true)-$_SERVER['REQUEST_TIME_FLOAT']), 4)); + +$smarty->assign('title', _('Migration')); + +$smarty->display('admin/migration.tpl'); diff --git a/admin/polls.php b/admin/polls.php new file mode 100644 index 0000000..d2a617b --- /dev/null +++ b/admin/polls.php @@ -0,0 +1,78 @@ += 1) ? $page : 1; + +/* PAGE */ +/* ---- */ + +if (!empty($_POST['delete_poll']) && $securityService->checkCsrf('admin', $_POST['csrf'])) { + $delete_id = filter_input(INPUT_POST, 'delete_poll', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); + $poll_to_delete = $pollService->findById($delete_id); +} + +// Traitement de la confirmation de suppression +if (!empty($_POST['delete_confirm']) && $securityService->checkCsrf('admin', $_POST['csrf'])) { + $poll_id = filter_input(INPUT_POST, 'delete_confirm', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); + $adminPollService->deleteEntirePoll($poll_id); +} + +$found = $superAdminService->findAllPolls($page-1, POLLS_PER_PAGE); +$polls = $found['polls']; +$count = $found['count']; + +// Assign data to template +$smarty->assign('polls', $polls); +$smarty->assign('count', $count); +$smarty->assign('page', $page); +$smarty->assign('pages', ceil($count / POLLS_PER_PAGE)); +$smarty->assign('poll_to_delete', $poll_to_delete); +$smarty->assign('crsf', $securityService->getToken('admin')); + +$smarty->display('admin/polls.tpl'); diff --git a/admin/purge.php b/admin/purge.php new file mode 100644 index 0000000..b97dcb2 --- /dev/null +++ b/admin/purge.php @@ -0,0 +1,56 @@ + ['regexp' => NAME_REGEX]]); + +/* PAGE */ +/* ---- */ + +if ($action === 'purge' && $securityService->checkCsrf('admin', $_POST['csrf'])) { + $count = $purgeService->purgeOldPolls(); + $message = _('Purged:') . ' ' . $count; +} + +// Assign data to template +$smarty->assign('message', $message); +$smarty->assign('crsf', $securityService->getToken('admin')); + +$smarty->display('admin/purge.tpl'); \ No newline at end of file diff --git a/adminstuds.php b/adminstuds.php index 1f2210f..f8501dd 100644 --- a/adminstuds.php +++ b/adminstuds.php @@ -16,1214 +16,362 @@ * Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) */ -namespace Framadate; +use Framadate\Services\PollService; +use Framadate\Services\AdminPollService; +use Framadate\Services\InputService; +use Framadate\Services\LogService; +use Framadate\Message; +use Framadate\Utils; -session_start(); - -//setlocale(LC_TIME, "fr_FR"); include_once __DIR__ . '/app/inc/init.php'; -if (file_exists('bandeaux_local.php')) { - include_once('bandeaux_local.php'); -} else { - include_once('bandeaux.php'); +/* Variables */ +/* --------- */ + +$admin_poll_id = null; +$poll_id = null; +$poll = null; +$message = null; +$editingVoteId = 0; + +/* Services */ +/*----------*/ + +$logService = new LogService(); +$pollService = new PollService($connect, $logService); +$adminPollService = new AdminPollService($connect, $pollService, $logService); +$inputService = new InputService(); + +/* PAGE */ +/* ---- */ + +if (!empty($_GET['poll']) && strlen($_GET['poll']) === 24) { + $admin_poll_id = filter_input(INPUT_GET, 'poll', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); + $poll_id = substr($admin_poll_id, 0, 16); + $poll = $pollService->findById($poll_id); } -// Initialisation des variables -$numsondageadmin = false; -$sondage = false; - -// recuperation du numero de sondage admin (24 car.) dans l'URL -if (Utils::issetAndNoEmpty('sondage', $_GET) && is_string($_GET['sondage']) && strlen($_GET['sondage']) === 24) { - $numsondageadmin=$_GET["sondage"]; - //on découpe le résultat pour avoir le numéro de sondage (16 car.) - $numsondage=substr($numsondageadmin, 0, 16); +if (!$poll) { + $smarty->assign('error', _('This poll doesn\'t exist !')); + $smarty->display('error.tpl'); + exit; } -if (preg_match(";[\w\d]{24};i", $numsondageadmin)) { - $sql = 'SELECT * FROM sondage WHERE id_sondage_admin = '.$connect->Param('numsondageadmin'); - $sql = $connect->Prepare($sql); - $sondage = $connect->Execute($sql, array($numsondageadmin)); +// ------------------------------- +// Update poll info +// ------------------------------- - if ($sondage !== false) { - $sql = 'SELECT * FROM sujet_studs WHERE id_sondage = '.$connect->Param('numsondage'); - $sql = $connect->Prepare($sql); - $sujets = $connect->Execute($sql, array($numsondage)); +if (isset($_POST['update_poll_info'])) { + $updated = false; + $field = $inputService->filterAllowedValues($_POST['update_poll_info'], ['title', 'admin_mail', 'comment', 'rules', 'expiration_date', 'name']); - $sql = 'SELECT * FROM user_studs WHERE id_sondage = '.$connect->Param('numsondage').' order by id_users'; - $sql = $connect->Prepare($sql); - $user_studs = $connect->Execute($sql, array($numsondage)); - } -} - -//verification de l'existence du sondage, s'il n'existe pas on met une page d'erreur -if (!$sondage || $sondage->RecordCount() != 1){ - Utils::print_header( _("Error!")); - - bandeau_titre(_("Error!")); - - echo ' -
-

' . _("This poll doesn't exist !") . '

-

' . _('Back to the homepage of ') . ' ' . NOMAPPLICATION . '

-
'."\n"; - - bandeau_pied(); - - die(); -} - -$dsujet=$sujets->FetchObject(false); -$dsondage=$sondage->FetchObject(false); - -// Send email (only once during the session) to alert admin of the change he made. ==> two modifications (comment, title, description, ...) on differents polls in the same session will generate only one mail. -$email_admin = $dsondage->mail_admin; -$poll_title = $dsondage->titre; -$smtp_allowed = $config['use_smtp']; -function send_mail_admin() { - global $email_admin; - global $poll_title; - global $numsondageadmin; - global $smtp_allowed; - if($smtp_allowed==true){ - if(!isset($_SESSION["mail_admin_sent"])) { - Utils::sendEmail( $email_admin, - _("[ADMINISTRATOR] New settings for your poll") . ' ' . stripslashes( $poll_title ), - _("You have changed the settings of your poll. \nYou can modify this poll with this link") . - " :\n\n" . Utils::getUrlSondage($numsondageadmin, true) . "\n\n" . - _("Thanks for your confidence.") . "\n" . NOMAPPLICATION - ); - $_SESSION["mail_admin_sent"]=true; - } + // Update the right poll field + if ($field == 'title') { + $title = strip_tags($_POST['title']); + if ($title) { + $poll->title = $title; + $updated = true; } + } elseif ($field == 'admin_mail') { + $admin_mail = filter_input(INPUT_POST, 'admin_mail', FILTER_VALIDATE_EMAIL); + if ($admin_mail) { + $poll->admin_mail = $admin_mail; + $updated = true; + } + } elseif ($field == 'comment') { + $comment = strip_tags($_POST['comment']); + if ($comment) { + $poll->comment = $comment; + $updated = true; + } + } elseif ($field == 'rules') { + $rules = strip_tags($_POST['rules']); + switch ($rules) { + case 0: + $poll->active = false; + $poll->editable = false; + $updated = true; + break; + case 1: + $poll->active = true; + $poll->editable = false; + $updated = true; + break; + case 2: + $poll->active = true; + $poll->editable = true; + $updated = true; + break; + } + } elseif ($field == 'expiration_date') { + $expiration_date = filter_input(INPUT_POST, 'expiration_date', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '#^[0-9]+[-/][0-9]+[-/][0-9]+#']]); + $expiration_date = strtotime($expiration_date); + if ($expiration_date) { + $poll->end_date = $expiration_date; + $updated = true; + } + } elseif ($field == 'name') { + $admin_name = filter_input(INPUT_POST, 'name', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => NAME_REGEX]]); + if ($admin_name) { + $poll->admin_name = $admin_name; + $updated = true; + } + } -} - -//si la valeur du nouveau titre est valide et que le bouton est activé -if (isset($_POST["boutonnouveautitre"])) { - if (Utils::issetAndNoEmpty('nouveautitre') === false) { - $err |= TITLE_EMPTY; + // Update poll in database + if ($updated && $adminPollService->updatePoll($poll)) { + $message = new Message('success', _('Poll saved.')); } else { - //Update SQL database with new title - $nouveautitre = htmlentities(html_entity_decode($_POST['nouveautitre'], ENT_QUOTES, 'UTF-8'), ENT_QUOTES, 'UTF-8'); - $sql = 'UPDATE sondage SET titre = '.$connect->Param('nouveautitre').' WHERE id_sondage = '.$connect->Param('numsondage'); - $sql = $connect->Prepare($sql); - - //Email sent to the admin - if ($connect->Execute($sql, array($nouveautitre, $numsondage))) { - send_mail_admin(); - } + $message = new Message('danger', _('Failed to save poll.')); + $poll = $pollService->findById($poll_id); } } -// si le bouton est activé, quelque soit la valeur du champ textarea -if (isset($_POST["boutonnouveauxcommentaires"])) { - if (Utils::issetAndNoEmpty('nouveautitre') === false) { - $err |= COMMENT_EMPTY; - } else { - $commentaires = htmlentities(html_entity_decode($_POST['nouveauxcommentaires'], ENT_QUOTES, 'UTF-8'), ENT_QUOTES, 'UTF-8'); +// ------------------------------- +// A vote is going to be edited +// ------------------------------- - //Update SQL database with new description - $sql = 'UPDATE sondage SET commentaires = '.$connect->Param('commentaires').' WHERE id_sondage = '.$connect->Param('numsondage'); - $sql = $connect->Prepare($sql); - - //Email sent to the admin - if ($connect->Execute($sql, array($commentaires, $numsondage))) { - send_mail_admin(); - } - } +if (!empty($_POST['edit_vote'])) { + $editingVoteId = filter_input(INPUT_POST, 'edit_vote', FILTER_VALIDATE_INT); } -//si la valeur de la nouvelle adresse est valide et que le bouton est activé -if (isset($_POST["boutonnouvelleadresse"])) { - if (Utils::issetAndNoEmpty('nouvelleadresse') === false || Utils::isValidEmail($_POST["nouvelleadresse"]) === false) { - $err |= INVALID_EMAIL; - } else { - $nouvelleadresse = htmlentities(html_entity_decode($_POST['nouvelleadresse'], ENT_QUOTES, 'UTF-8'), ENT_QUOTES, 'UTF-8'); +// ------------------------------- +// Something to save (edit or add) +// ------------------------------- - //Update SQL database with new email - $sql = 'UPDATE sondage SET mail_admin = '.$connect->Param('nouvelleadresse').' WHERE id_sondage = '.$connect->Param('numsondage'); - $sql = $connect->Prepare($sql); +if (!empty($_POST['save'])) { // Save edition of an old vote + $name = filter_input(INPUT_POST, 'name', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => NAME_REGEX]]); + $editedVote = filter_input(INPUT_POST, 'save', FILTER_VALIDATE_INT); + $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]); - //Email sent to the admin - if ($connect->Execute($sql, array($nouvelleadresse, $numsondage))) { - send_mail_admin(); - } + if (empty($editedVote)) { + $message = new Message('danger', _('Something is going wrong...')); } -} - -//New poll rules -if (isset($_POST["btn_poll_rules"])) { - echo ''; - if($_POST['poll_rules'] == '+') { - $new_poll_rules = substr($dsondage->format, 0, 1).'+'; - } elseif($_POST['poll_rules'] == '-') { - $new_poll_rules = substr($dsondage->format, 0, 1).'-'; - } else { - $new_poll_rules = substr($dsondage->format, 0, 1); + if (count($choices) != count($_POST['choices'])) { + $message = new Message('danger', _('There is a problem with your choices.')); } - //Update SQL database with new rules - $sql = 'UPDATE sondage SET format = '.$connect->Param('new_poll_rules').' WHERE id_sondage = '.$connect->Param('numsondage'); - $sql = $connect->Prepare($sql); - - //Email sent to the admin - if ($connect->Execute($sql, array($new_poll_rules, $numsondage))) { - send_mail_admin(); - } -} - -// reload -$dsujet=$sujets->FetchObject(false); -$dsondage=$sondage->FetchObject(false); - -if (isset($_POST["ajoutsujet"])) { - Utils::print_header( _("Add a column") .' - ' . stripslashes( $dsondage->titre )); - - bandeau_titre(_("Make your polls")); - - //on recupere les données et les sujets du sondage - - echo ' -
-
-
-

' . _("Column's adding") . '

'."\n"; - - if (substr($dsondage->format, 0, 1)=="A"){ - echo ' -
- -
- -
-
'."\n"; - } else { - //ajout d'une date avec creneau horaire - echo ' -

'. _("You can add a new scheduling date to your poll.").'
'._("If you just want to add a new hour to an existant date, put the same date and choose a new hour.") .'

- -
- -
-
- - -
- '. _("(dd/mm/yyyy)") .' -
-
-
- -
- -
-
'; - } - echo ' -

- - -

-
-
-
'; - - bandeau_pied(); - - die(); -} - -if (isset($_POST["suppressionsondage"])) { - Utils::print_header( _("Confirm removal of your poll") .' - ' . stripslashes( $dsondage->titre )); - - bandeau_titre(_("Confirm removal of your poll")); - - echo ' -
-
-

' . _("Confirm removal of your poll") . '

-

-

-
-
'; - - bandeau_pied(); - - die(); -} - -// Remove all the comments -if (isset($_POST["removecomments"])) { - $sql = 'DELETE FROM comments WHERE id_sondage='.$connect->Param('numsondage'); - $sql = $connect->Prepare($sql); - $cleaning = $connect->Execute($sql, array($numsondage)); -} - -// Remove all the votes -if (isset($_POST["removevotes"])) { - $sql = 'DELETE FROM user_studs WHERE id_sondage='.$connect->Param('numsondage'); - $sql = $connect->Prepare($sql); - $cleaning = $connect->Execute($sql, array($numsondage)); -} - -//action si bouton confirmation de suppression est activé -if (isset($_POST["confirmesuppression"])) { - $nbuser=$user_studs->RecordCount(); - $date=date('H:i:s d/m/Y:'); - - if (Utils::remove_sondage($connect, $numsondage)) { - // on ecrit dans le fichier de logs la suppression du sondage - error_log($date . " SUPPRESSION: $dsondage->id_sondage\t$dsondage->format\t$dsondage->nom_admin\t$dsondage->mail_admin\n", 3, 'admin/logs_studs.txt'); - - // Email sent - send_mail_admin(); - //affichage de l'ecran de confirmation de suppression de sondage - Utils::print_header(_("Your poll has been removed!")); - - bandeau_titre(_("Make your polls")); - - echo ' -
-

' . _("Your poll has been removed!") . '

-

' . _('Back to the homepage of ') . ' ' . NOMAPPLICATION . '

-
- '."\n"; - - bandeau_pied(); - - die(); - } -} - -// quand on ajoute un commentaire utilisateur -if (isset($_POST['ajoutcomment'])) { - if (Utils::issetAndNoEmpty('commentuser') === false) { - $err |= COMMENT_USER_EMPTY; - } else { - $comment_user = htmlentities(html_entity_decode($_POST["commentuser"], ENT_QUOTES, 'UTF-8'), ENT_QUOTES, 'UTF-8'); - } - - if(Utils::issetAndNoEmpty('comment') === false) { - $err |= COMMENT_EMPTY; - } - - if (Utils::issetAndNoEmpty('comment') && !Utils::is_error(COMMENT_EMPTY) && !Utils::is_error(NO_POLL) && !Utils::is_error(COMMENT_USER_EMPTY)) { - $comment = htmlentities(html_entity_decode($_POST["comment"], ENT_QUOTES, 'UTF-8'), ENT_QUOTES, 'UTF-8'); - - // Check for doublons - $comment_doublon = false; - $req = 'SELECT * FROM comments WHERE id_sondage='.$connect->Param('numsondage').' ORDER BY id_comment'; - $sql = $connect->Prepare($req); - $comment_user_doublon = $connect->Execute($sql, array($numsondage)); - if ($comment_user_doublon->RecordCount() != 0) { - while ( $dcomment_user_doublon=$comment_user_doublon->FetchNextObject(false)) { - if($dcomment_user_doublon->comment == $comment && $dcomment_user_doublon->usercomment == $comment_user) { - $comment_doublon = true; - }; - } - } - - if(!$comment_doublon) { - $req = 'INSERT INTO comments (id_sondage, comment, usercomment) VALUES ('. - $connect->Param('id_sondage').','. - $connect->Param('comment').','. - $connect->Param('comment_user').')'; - $sql = $connect->Prepare($req); - - $comments = $connect->Execute($sql, array($numsondage, $comment, $comment_user)); - if ($comments === false) { - $err |= COMMENT_INSERT_FAILED; - } - } - } -} - -$nbcolonnes = substr_count($dsujet->sujet, ',') + 1; -$nblignes = $user_studs->RecordCount(); - -//si il n'y a pas suppression alors on peut afficher normalement le tableau - -//action si le bouton participer est cliqué -if (isset($_POST["boutonp"])) { - //si on a un nom dans la case texte - if (Utils::issetAndNoEmpty('nom')){ - $nouveauchoix = ''; - $erreur_prenom = false; - - for ($i=0;$i<$nbcolonnes;$i++){ - // radio checked 1 = Yes, 2 = Ifneedbe, 0 = No - if (isset($_POST["choix$i"])) { - switch ($_POST["choix$i"]) { - case 1: $nouveauchoix .= "1";break; - case 2: $nouveauchoix .= "2";break; - default: $nouveauchoix .= "0";break; - } - } - } - - $nom = htmlentities(html_entity_decode($_POST["nom"], ENT_QUOTES, 'UTF-8'), ENT_QUOTES, 'UTF-8'); - - while($user = $user_studs->FetchNextObject(false)) { - if ($nom == $user->nom){ - $erreur_prenom="yes"; - } - } - - // Ecriture des choix de l'utilisateur dans la base - if (!$erreur_prenom) { - $sql = 'INSERT INTO user_studs (nom, id_sondage, reponses) VALUES ('. - $connect->Param('nom').','. - $connect->Param('numsondage').','. - $connect->Param('nouveauchoix').')'; - - $sql = $connect->Prepare($sql); - $connect->Execute($sql, array($nom, $numsondage, $nouveauchoix)); - } - } -} - - -//action quand on ajoute une colonne au format AUTRE -if (isset($_POST["ajoutercolonne"]) && Utils::issetAndNoEmpty('nouvellecolonne') && (substr($dsondage->format, 0, 1) == "A" )) { - $nouveauxsujets=$dsujet->sujet; - - //on rajoute la valeur a la fin de tous les sujets deja entrés - $nouveauxsujets.=","; - $nouveauxsujets.=str_replace(","," ",$_POST["nouvellecolonne"]); - $nouveauxsujets = htmlentities(html_entity_decode($nouveauxsujets, ENT_QUOTES, 'UTF-8'), ENT_QUOTES, 'UTF-8'); - - //mise a jour avec les nouveaux sujets dans la base - $sql = 'UPDATE sujet_studs SET sujet = '.$connect->Param('nouveauxsujets').' WHERE id_sondage = '.$connect->Param('numsondage'); - $sql = $connect->Prepare($sql); - if ($connect->Execute($sql, array($nouveauxsujets, $numsondage))) { - send_mail_admin(); - } -} - -$erreur_ajout_date = false; -//action quand on ajoute une colonne au format DATE -if (isset($_POST["ajoutercolonne"]) && (substr($dsondage->format, 0, 1) == "D")) { - $nouveauxsujets=$dsujet->sujet; - - if (isset($_POST["newdate"]) && $_POST["newdate"] != "") { - $nouvelledate=mktime(0, 0, 0, substr($_POST["newdate"],3,2), substr($_POST["newdate"],0,2), substr($_POST["newdate"],6,4)); - - if (isset($_POST["newhour"]) && $_POST["newhour"]!=""){ - $nouvelledate.="@"; - $nouvelledate.=$_POST["newhour"]; - } - - //on rajoute la valeur dans les valeurs - $datesbase = explode(",",$dsujet->sujet); - $taillebase = sizeof($datesbase); - - //recherche de l'endroit de l'insertion de la nouvelle date dans les dates deja entrées dans le tableau - if ($nouvelledate < $datesbase[0]) { - $cleinsertion = 0; - } elseif ($nouvelledate > $datesbase[$taillebase-1]) { - $cleinsertion = count($datesbase); + if ($message == null) { + // Update vote + $result = $pollService->updateVote($poll_id, $editedVote, $name, $choices); + if ($result) { + $message = new Message('success', _('Update vote successfully.')); } else { - for ($i = 0; $i < count($datesbase); $i++) { - $j = $i + 1; - if ($nouvelledate > $datesbase[$i] && $nouvelledate < $datesbase[$j]) { - $cleinsertion = $j; - } - } + $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' => NAME_REGEX]]); + $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]); - array_splice($datesbase, $cleinsertion, 0, $nouvelledate); - $cle = array_search($nouvelledate, $datesbase); - $dateinsertion = ''; - for ($i = 0; $i < count($datesbase); $i++) { - $dateinsertion.=","; - $dateinsertion.=$datesbase[$i]; + if (empty($name)) { + $message = new Message('danger', _('The name is invalid.')); + } + 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.')); } + } +} - $dateinsertion = substr("$dateinsertion", 1); - - //mise a jour avec les nouveaux sujets dans la base - - $sql = 'UPDATE sujet_studs SET sujet = '.$connect->Param('dateinsertion').' WHERE id_sondage = '.$connect->Param('numsondage'); - $sql = $connect->Prepare($sql); - $connect->Execute($sql, array($dateinsertion, $numsondage)); - - /* Doesn't work → 30/11/-0001 - if ($nouvelledate > strtotime($dsondage->date_fin)) { - $date_fin=$nouvelledate+200000; - $sql = 'UPDATE sondage SET date_fin = '.$connect->Param('date_fin').' WHERE id_sondage = '.$connect->Param('numsondage'); - $sql = $connect->Prepare($sql); - $connect->Execute($sql, array($date_fin, $numsondage)); - }*/ - - //mise a jour des reponses actuelles correspondant au sujet ajouté - $sql = 'UPDATE user_studs SET reponses = '.$connect->Param('reponses').' WHERE nom = '.$connect->Param('nom').' AND id_users='.$connect->Param('id_users'); - $sql = $connect->Prepare($sql); - while ($data = $user_studs->FetchNextObject(false)) { - $ensemblereponses=$data->reponses; - $newcar = ''; - - //parcours de toutes les réponses actuelles - for ($j = 0; $j < $nbcolonnes; $j++) { - $car=substr($ensemblereponses,$j,1); - - //si les reponses ne concerne pas la colonne ajoutée, on concatene - if ($j==$cle) { - $newcar.="0"; - } - - $newcar.=$car; - } - - //mise a jour des reponses utilisateurs dans la base - if (isset($erreur_ajout_date) && !$erreur_ajout_date){ - $connect->Execute($sql, array($newcar, $data->nom, $data->id_users)); - } - } - - //Email sent to the admin - send_mail_admin(); +// ------------------------------- +// Delete a votes +// ------------------------------- +if (!empty($_POST['delete_vote'])) { + $vote_id = filter_input(INPUT_POST, 'delete_vote', FILTER_VALIDATE_INT); + if ($adminPollService->deleteVote($poll_id, $vote_id)) { + $message = new Message('success', _('Vote delete.')); } else { - $erreur_ajout_date = true; + $message = new Message('danger', _('Failed to delete the vote.')); } } +// ------------------------------- +// Remove all votes +// ------------------------------- -//suppression de ligne dans la base -for ($i = 0; $i < $nblignes; $i++) { - if (isset($_POST["effaceligne$i"])) { - $compteur=0; - $sql = 'DELETE FROM user_studs WHERE nom = '.$connect->Param('nom').' AND id_users = '.$connect->Param('id_users'); - $sql = $connect->Prepare($sql); - - while ($data=$user_studs->FetchNextObject(false)) { - if ($compteur==$i){ - $connect->Execute($sql, array($data->nom, $data->id_users)); - } - - $compteur++; - } - } +if (isset($_POST['remove_all_votes'])) { + $smarty->assign('poll_id', $poll_id); + $smarty->assign('admin_poll_id', $admin_poll_id); + $smarty->assign('title', _('Poll') . ' - ' . $poll->title); + $smarty->display('confirm/delete_votes.tpl'); + exit; } - - -//suppression d'un commentaire utilisateur -$sql = 'SELECT * FROM comments WHERE id_sondage='.$connect->Param('numsondage').' ORDER BY id_comment'; -$sql = $connect->Prepare($sql); -$comment_user = $connect->Execute($sql, array($numsondage)); -$i = 0; -while ($dcomment = $comment_user->FetchNextObject(false)) { - if (isset($_POST['suppressioncomment'.$i])) { - $sql = 'DELETE FROM comments WHERE id_comment = '.$connect->Param('id_comment'); - $sql = $connect->Prepare($sql); - $connect->Execute($sql, array($dcomment->id_comment)); - } - - $i++; -} - - -//on teste pour voir si une ligne doit etre modifiée -$testmodifier = false; -$testligneamodifier = false; - -for ($i = 0; $i < $nblignes; $i++) { - if (isset($_POST["modifierligne$i"])) { - $ligneamodifier=$i; - $testligneamodifier="true"; - } - - //test pour voir si une ligne est a modifier - if (isset($_POST["validermodifier$i"])) { - $modifier=$i; - $testmodifier="true"; - } -} - - -//si le test est valide alors on affiche des checkbox pour entrer de nouvelles valeurs -if ($testmodifier) { - $nouveauchoix = ''; - for ($i = 0; $i < $nbcolonnes; $i++) { - // radio checked 1 = Yes, 2 = Ifneedbe, 0 = No - if (isset($_POST["choix$i"])) { - switch ($_POST["choix$i"]) { - case 1: $nouveauchoix .= "1";break; - case 2: $nouveauchoix .= "2";break; - default: $nouveauchoix .= "0";break; - } - } - } - - $compteur=0; - - while ($data=$user_studs->FetchNextObject(false)) { - //mise a jour des données de l'utilisateur dans la base SQL - if ($compteur==$modifier) { - $sql = 'UPDATE user_studs SET reponses = '.$connect->Param('reponses').' WHERE nom = '.$connect->Param('nom').' AND id_users = '.$connect->Param('id_users'); - $sql = $connect->Prepare($sql); - $connect->Execute($sql, array($nouveauchoix, $data->nom, $data->id_users)); - } - - $compteur++; - } -} - - -//suppression de colonnes dans la base -for ($i = 0; $i < $nbcolonnes; $i++) { - if ((isset($_POST["effacecolonne$i"])) && $nbcolonnes > 1){ - $toutsujet = explode(",",$dsujet->sujet); - //sort($toutsujet, SORT_NUMERIC); - $j = 0; - $nouveauxsujets = ''; - - //parcours de tous les sujets actuels - while (isset($toutsujet[$j])) { - //si le sujet n'est pas celui qui a été effacé alors on concatene - if ($i != $j) { - $nouveauxsujets .= ','; - $nouveauxsujets .= $toutsujet[$j]; - } - - $j++; - } - - //on enleve la virgule au début - $nouveauxsujets = substr("$nouveauxsujets", 1); - - //nettoyage des reponses actuelles correspondant au sujet effacé - $compteur = 0; - $sql = 'UPDATE user_studs SET reponses = '.$connect->Param('reponses').' WHERE nom = '.$connect->Param('nom').' AND id_users = '.$connect->Param('id_users'); - $sql = $connect->Prepare($sql); - - while ($data = $user_studs->FetchNextObject(false)) { - $newcar = ''; - $ensemblereponses = $data->reponses; - - //parcours de toutes les réponses actuelles - for ($j = 0; $j < $nbcolonnes; $j++) { - $car=substr($ensemblereponses, $j, 1); - //si les reponses ne concerne pas la colonne effacée, on concatene - if ($i != $j) { - $newcar .= $car; - } - } - - $compteur++; - - //mise a jour des reponses utilisateurs dans la base - $connect->Execute($sql, array($newcar, $data->nom, $data->id_users)); - } - - //mise a jour des sujets dans la base - $sql = 'UPDATE sujet_studs SET sujet = '.$connect->Param('nouveauxsujets').' WHERE id_sondage = '.$connect->Param('numsondage'); - $sql = $connect->Prepare($sql); - $connect->Execute($sql, array($nouveauxsujets, $numsondage)); - } -} - - -//recuperation des donnes de la base -$sql = 'SELECT * FROM sondage WHERE id_sondage_admin = '.$connect->Param('numsondageadmin'); -$sql = $connect->Prepare($sql); -$sondage = $connect->Execute($sql, array($numsondageadmin)); - -if ($sondage !== false) { - $sql = 'SELECT * FROM sujet_studs WHERE id_sondage = '.$connect->Param('numsondage'); - $sql = $connect->Prepare($sql); - $sujets = $connect->Execute($sql, array($numsondage)); - - $sql = 'SELECT * FROM user_studs WHERE id_sondage = '.$connect->Param('numsondage').' order by id_users'; - $sql = $connect->Prepare($sql); - $user_studs = $connect->Execute($sql, array($numsondage)); -} else { - - Utils::print_header(_("Error!")); - bandeau_titre(_("Error!")); - - echo ' -
-

' . _("This poll doesn't exist !") . '

-

' . _('Back to the homepage of ') . ' ' . NOMAPPLICATION . '

-
'."\n"; - - bandeau_pied(); - - die(); -} - -// Errors -$errors = ''; -if ((isset($_POST["boutonp"])) && $_POST["nom"] == "") { - $errors .= '
  • ' . _("Enter a name") . '
  • '; -} -if (isset($erreur_prenom) && $erreur_prenom) { - $errors .= '
  • ' . _("The name you've chosen already exist in this poll!") . '
  • '; -} -if (isset($erreur_injection) && $erreur_injection) { - $errors .= '
  • ' . _("Characters \" ' < et > are not permitted") . '
  • '; -} -if (isset($erreur_ajout_date) && $erreur_ajout_date) { - $errors .= '
  • ' . _("The date is not correct !") . '
  • '; -} - -//Poll title, description and email values -$title = (isset($_POST["boutonnouveautitre"]) && Utils::issetAndNoEmpty('nouveautitre')) ? htmlentities(html_entity_decode($_POST['nouveautitre'], ENT_QUOTES, 'UTF-8'), ENT_QUOTES, 'UTF-8') : stripslashes( $dsondage->titre ); -$description = (isset($_POST["nouveauxcommentaires"])) ? stripslashes(htmlentities(html_entity_decode($_POST['nouveauxcommentaires'], ENT_QUOTES, 'UTF-8'), ENT_QUOTES, 'UTF-8')) : stripslashes( $dsondage->commentaires ); -$email_admin = (isset($_POST["boutonnouvelleadresse"]) && Utils::issetAndNoEmpty('nouvelleadresse')) ? htmlentities(html_entity_decode($_POST['nouvelleadresse'], ENT_QUOTES, 'UTF-8'), ENT_QUOTES, 'UTF-8') : stripslashes( $dsondage->mail_admin ); - -//Poll format (locked A-/D-, open A/D, editable A+/D+) -$poll_rules = (isset($_POST["poll_rules"]) && Utils::issetAndNoEmpty('btn_poll_rules')) ? $_POST["poll_rules"] : substr($dsondage->format, 1, 1); -$poll_rules_opt1 = '';$poll_rules_opt2 = '';$poll_rules_opt3 = ''; -if($poll_rules == '+') { - $poll_rules_text = ' '. _("Votes are editable"); - $poll_rules_opt3 = 'selected'; -} elseif($poll_rules == '-') { - $poll_rules_text = ' '. _("Votes and comments are locked"); - $poll_rules_opt1 = 'selected'; -} else { - $poll_rules_text = ' '. _("Votes and comments are open"); - $poll_rules_opt2 = 'selected'; -} - -if ($errors!='') { - Utils::print_header(_("Error!")); - bandeau_titre(_("Error!")); - - echo '
    '."\n"; - -} else { - Utils::print_header(_('Poll administration').' - '.$title); - bandeau_titre(_('Poll administration').' - '.$title); - - // session_unset(); -} - -echo ' -
    -
    -
    -
    -

    '.$title.'

    - -
    -
    -
    - - - - -
    -
    -
    -
    -
    -
    -
    -

    '. _("Initiator of the poll") .'

    -

    '.stripslashes($dsondage->nom_admin).'

    -
    -
    -

    '.$email_admin.'

    - -
    -
    -
    -
    -

    '._("Description") .'


    -

    '.$description.'

    - -
    -
    -
    - - -
    -

    '. _("Expiration's date") .'

    -

    '.date("d/m/Y",strtotime($dsondage->date_fin)).'

    -
    -
    -
    -
    -
    -

    '.$poll_rules_text.'

    - -
    -
    -
    -
    -
    '."\n"; // .jumbotron - -//on recupere les données et les sujets du sondage -$dsujet=$sujets->FetchObject(false); -$dsondage=$sondage->FetchObject(false); - -//reformatage des données des sujets du sondage -$toutsujet=explode(",",$dsujet->sujet); -$toutsujet=str_replace("°","'",$toutsujet); -$nbcolonnes=substr_count($dsujet->sujet,',')+1; - -// Table headers -$thead = ''; - -// Button in the first td to avoid remove col on "Return" keypress) -$tr_add_remove_col = ''; - -$border = array(); // bordure pour distinguer les mois -$td_headers = array(); // for a11y, headers="M1 D4 H5" on each td -$radio_title = array(); // date for - -// Dates poll -if (substr($dsondage->format, 0, 1)=="D") { - - $tr_months = ''; - $tr_days = ''; - $tr_hours = ''; - - // Headers - $colspan_month = 1; - $colspan_day = 1; - - for ($i = 0; $i < count($toutsujet); $i++) { - - // Current date - $current = $toutsujet[$i];//format date@hour. ex : 2020292820@10:00 - $horoCur = explode("@",$current); //horoCur[0] = date, horoCur[1] = hour - if (isset($toutsujet[$i+1])){ - $next = $toutsujet[$i+1]; - $horoNext = explode("@",$next); - } - $border[$i] = false; - $radio_title[$i] = strftime($date_format['txt_short'],$horoCur[0]); - - // Months - $td_headers[$i] = 'M'.($i+1-$colspan_month); - - if (isset($toutsujet[$i+1]) && strftime("%B", $horoCur[0]) == strftime("%B", $horoNext[0]) && strftime("%Y", $horoCur[0]) == strftime("%Y", $horoNext[0])){ - $colspan_month++; - } else { - $border[$i] = true; - $tr_months .= ''.strftime("%B",$horoCur[0]).' '.strftime("%Y", $horoCur[0]).''; - $colspan_month=1; - } - - // Days - $td_headers[$i] .= ' D'.($i+1-$colspan_day); - - if (isset($toutsujet[$i+1]) && strftime($date_format['txt_day'],$horoCur[0])==strftime($date_format['txt_day'],$horoNext[0]) && strftime("%B",$horoCur[0])==strftime("%B",$horoNext[0])){ - $colspan_day++; - } else { - $rbd = ($border[$i]) ? ' rbd' : ''; - $tr_days .= ''.strftime($date_format['txt_day'],$horoCur[0]).''; - $colspan_day=1; - } - - // Hours - $rbd = ($border[$i]) ? ' rbd' : ''; - if (isset($horoCur[1]) && $horoCur[1] !== '') { - $tr_hours .= ''.$horoCur[1].''; - $radio_title[$i] .= ' - '.$horoCur[1]; - $td_headers[$i] .= ' H'.$i; - } else { - $tr_hours .= ''; - } - - // Remove col - $tr_add_remove_col .= (count($toutsujet) > 1 ) ? '' : ''; - - } - - $border[count($border)-1] = false; // suppression de la bordure droite du dernier mois - - $tr_months .= ''; - $tr_days .= ''; - $tr_hours .= ''; - - // Add col - $tr_add_remove_col .= ''; - - $thead = "\n".$tr_add_remove_col."\n".$tr_months."\n".$tr_days."\n".$tr_hours."\n"; - -// Subjects poll -} else { - $toutsujet=str_replace("@","
    ",$toutsujet); - - $tr_subjects = ''; - - for ($i = 0; isset($toutsujet[$i]); $i++) { - - $td_headers[$i]='';$radio_title[$i]=''; // init before concatenate - - // Subjects - preg_match_all('/\[!\[(.*?)\]\((.*?)\)\]\((.*?)\)/',$toutsujet[$i],$md_a_img); // Markdown [![alt](src)](href) - preg_match_all('/!\[(.*?)\]\((.*?)\)/',$toutsujet[$i],$md_img); // Markdown ![alt](src) - preg_match_all('/\[(.*?)\]\((.*?)\)/',$toutsujet[$i],$md_a); // Markdown [text](href) - if (isset($md_a_img[2][0]) && $md_a_img[2][0]!='' && isset($md_a_img[3][0]) && $md_a_img[3][0]!='') { // [![alt](src)](href) - - $th_subject_text = (isset($md_a_img[1][0]) && $md_a_img[1][0]!='') ? stripslashes($md_a_img[1][0]) : _("Choice") .' '.($i+1); - $th_subject_html = ''.$th_subject_text.''; - - } elseif (isset($md_img[2][0]) && $md_img[2][0]!='') { // ![alt](src) - - $th_subject_text = (isset($md_img[1][0]) && $md_img[1][0]!='') ? stripslashes($md_img[1][0]) : _("Choice") .' '.($i+1); - $th_subject_html = ''.$th_subject_text.''; - - } elseif (isset($md_a[2][0]) && $md_a[2][0]!='') { // [text](href) - - $th_subject_text = (isset($md_a[1][0]) && $md_a[1][0]!='') ? stripslashes($md_a[1][0]) : _("Choice") .' '.($i+1); - $th_subject_html = ''.$th_subject_text.''; - - } else { // text only - - $th_subject_text = stripslashes($toutsujet[$i]); - $th_subject_html = $th_subject_text; - - } - $tr_subjects .= ''.$th_subject_html.''; - - $border[$i] = false; - $td_headers[$i] .= 'S'.$i; - $radio_title[$i] .= $th_subject_text; - - // Remove col - $tr_add_remove_col .= ''; - } - - // Add col - $tr_add_remove_col .= ''; - - $thead = $tr_add_remove_col.$tr_subjects.''; -} - -// Print headers -echo ' -
    - -
    -

    ' . _('As poll administrator, you can change all the lines of this poll with this button ').'' . _('Edit') . ', - ' . _(' remove a column or a line with ') . '' . _('Remove') . ' - ' . _('and add a new column with '). ''. _('Add a column') . '

    -

    ' . _('Finally, you can change the informations of this poll like the title, the comments or your email address.') . '

    - -
    - - - -

    '._('Votes of the poll ').'

    -
    - - - '. $thead . ' - '; - -// Print poll results -$somme[] = 0; -$compteur = 0; - -while ($data = $user_studs->FetchNextObject(false)) { - - $ensemblereponses = $data->reponses; - - // Print name - $nombase=str_replace("°","'",$data->nom); - echo ' -'."\n"; - - // si la ligne n'est pas a changer, on affiche les données - if (!$testligneamodifier) { - for ($k = 0; $k < $nbcolonnes; $k++) { - $rbd = ($border[$k]) ? ' rbd' : ''; - $car = substr($ensemblereponses, $k, 1); - switch ($car) { - case "1": echo ''."\n"; - if (isset($somme[$k]) === false) { - $somme[$k] = 0; - } - $somme[$k]++; break; - case "2": echo ''."\n"; break; - default: echo ''."\n";break; - } - } - } else { // sinon on remplace les choix de l'utilisateur par une ligne de radio pour recuperer de nouvelles valeurs - // si c'est bien la ligne a modifier on met les radios - if ($compteur == "$ligneamodifier") { - for ($j = 0; $j < $nbcolonnes; $j++) { - - $car = substr($ensemblereponses, $j, 1); - - // variable pour afficher la valeur cochée - $car_html[0]='value="0"';$car_html[1]='value="1"';$car_html[2]='value="2"'; - switch ($car) { - case "1": $car_html[1]='value="1" checked';break; - case "2": $car_html[2]='value="2" checked';break; - default: $car_html[0]='value="0" checked';break; - } - - echo ' - '."\n"; - - } - } else { //sinon on affiche les lignes normales - for ($k = 0; $k < $nbcolonnes; $k++) { - $rbd = ($border[$k]) ? ' rbd' : ''; - $car = substr($ensemblereponses, $k, 1); - switch ($car) { - case "1": echo ''."\n"; - if (isset($somme[$k]) === false) { - $somme[$k] = 0; - } - $somme[$k]++; break; - case "2": echo ''."\n"; break; - default: echo ''."\n";break; - } - } - } - } - - //a la fin de chaque ligne se trouve les boutons modifier - if (!$testligneamodifier=="true") { - echo ' - '."\n"; - } - - //demande de confirmation pour modification de ligne - for ($i = 0; $i < $nblignes; $i++) { - if (isset($_POST["modifierligne$i"])) { - if ($compteur == $i) { - echo ''."\n"; - } - } - } - - $compteur++; - echo ''."\n"; -} - -if (!$testligneamodifier=="true") { - //affichage de la case vide de texte pour un nouvel utilisateur - echo ' -'."\n"; - - //une ligne de checkbox pour le choix du nouvel utilisateur - for ($i = 0; $i < $nbcolonnes; $i++) { - echo ' - '."\n"; - } - - // Affichage du bouton de formulaire pour inscrire un nouvel utilisateur dans la base - echo ' -'."\n"; - -} - -// Addition and Best choice -//affichage de la ligne contenant les sommes de chaque colonne -$tr_addition = ''; -$meilleurecolonne = max($somme); -$compteursujet = 0; -$meilleursujet = ''; - - $meilleursujet.= '
  • '.$radio_title[$i].'
  • '; - $compteursujet++; - - } else { - $tr_addition .= ''; - } +if (isset($_POST['confirm_remove_all_votes'])) { + if ($adminPollService->cleanVotes($poll_id)) { + $message = new Message('success', _('All votes deleted.')); } else { - $tr_addition .= ''; + $message = new Message('danger', _('Failed to delete all votes.')); } } -$tr_addition .= ''; -//recuperation des valeurs des sujets et adaptation pour affichage -$toutsujet = explode(",", $dsujet->sujet); +// ------------------------------- +// Add a comment +// ------------------------------- -$meilleursujet = str_replace("°", "'", $meilleursujet).''; -$vote_str = ($meilleurecolonne > 1) ? $vote_str = _('votes') : _('vote'); +if (isset($_POST['add_comment'])) { + $name = filter_input(INPUT_POST, 'name', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => NAME_REGEX]]); + $comment = strip_tags($_POST['comment']); -// Print Addition and Best choice -echo $tr_addition.' - -
    '._('Votes of the poll ').$title.'
    '.stripslashes($nombase).' ' . _('Yes') . '() ' . _('Yes') . _(', ifneedbe') . '' . _('No') . ' -
      -
    • - - -
    • -
    • - - -
    • -
    • - - -
    • -
    -
    ' . _('Yes') . '() ' . _('Yes') . _(', ifneedbe') . '' . _('No') . ' - - -
    -
    - - -
    -
    -
      -
    • - - -
    • -
    • - - -
    • -
    • - - -
    • -
    -
    '. _("Addition") .''.$somme[$i].''.$somme[$i].'
    -
    -
    '."\n"; - -if ($compteursujet == 1) { - echo ' -

    ' . _("Best choice") . '

    -
    -

    ' . _("The best choice at this time is:") . '

    - ' . $meilleursujet . ' -

    ' . _("with") . ' ' . $meilleurecolonne . ' ' . $vote_str . '.

    -
    '."\n"; -} elseif ($compteursujet > 1) { - echo ' -

    ' . _("Best choices") . '

    -
    -

    ' . _("The bests choices at this time are:") . '

    - ' . $meilleursujet . ' -

    ' . _("with") . ' ' . $meilleurecolonne . ' ' . $vote_str . '.

    -
    '."\n"; -} - -echo ' -
    -
    '."\n"; -// Commments -$sql = 'SELECT * FROM comments WHERE id_sondage='.$connect->Param('numsondage').' ORDER BY id_comment'; -$sql = $connect->Prepare($sql); -$comment_user = $connect->Execute($sql, array($numsondage)); - -if ($comment_user->RecordCount() != 0) { - echo '

    ' . _("Comments of polled people") . '

    '."\n"; - - $i = 0; - while ( $dcomment=$comment_user->FetchNextObject(false)) { - echo ' -
    - - '.stripslashes($dcomment->usercomment). ' : - ' . stripslashes(nl2br($dcomment->comment)) . ' -
    '; - $i++; + if (empty($name)) { + $message = new Message('danger', _('The name is invalid.')); } - echo '
    '; -} -echo ' -
    -
    -
    ' . _("Add a comment in the poll") . ' -
    -

    -
    -
    -


    -

    -
    -

    -
    -
    -
    -
    -
    '; -bandeau_pied(); + if ($message == null) { + // Add comment + $result = $pollService->addComment($poll_id, $name, $comment); + if ($result) { + $message = new Message('success', _('Comment added.')); + } else { + $message = new Message('danger', _('Comment failed.')); + } + } + +} + +// ------------------------------- +// Delete a comment +// ------------------------------- + +if (!empty($_POST['delete_comment'])) { + $comment_id = filter_input(INPUT_POST, 'delete_comment', FILTER_VALIDATE_INT); + + if ($adminPollService->deleteComment($poll_id, $comment_id)) { + $message = new Message('success', _('Comment deleted.')); + } else { + $message = new Message('danger', _('Failed to delete the comment.')); + } +} + +// ------------------------------- +// Remove all comments +// ------------------------------- + +if (isset($_POST['remove_all_comments'])) { + $smarty->assign('poll_id', $poll_id); + $smarty->assign('admin_poll_id', $admin_poll_id); + $smarty->assign('title', _('Poll') . ' - ' . $poll->title); + $smarty->display('confirm/delete_comments.tpl'); + exit; +} +if (isset($_POST['confirm_remove_all_comments'])) { + if ($adminPollService->cleanComments($poll_id)) { + $message = new Message('success', _('All comments deleted.')); + } else { + $message = new Message('danger', _('Failed to delete all comments.')); + } +} + +// ------------------------------- +// Delete the entire poll +// ------------------------------- + +if (isset($_POST['delete_poll'])) { + $smarty->assign('poll_id', $poll_id); + $smarty->assign('admin_poll_id', $admin_poll_id); + $smarty->assign('title', _('Poll') . ' - ' . $poll->title); + $smarty->display('confirm/delete_poll.tpl'); + exit; +} +if (isset($_POST['confirm_delete_poll'])) { + if ($adminPollService->deleteEntirePoll($poll_id)) { + $message = new Message('success', _('Poll fully deleted.')); + } else { + $message = new Message('danger', _('Failed to delete the poll.')); + } + $smarty->assign('poll_id', $poll_id); + $smarty->assign('admin_poll_id', $admin_poll_id); + $smarty->assign('title', _('Poll') . ' - ' . $poll->title); + $smarty->assign('message', $message); + $smarty->display('poll_deleted.tpl'); + exit; +} + +// ------------------------------- +// Delete a slot +// ------------------------------- + +if (!empty($_POST['delete_column'])) { + $column = filter_input(INPUT_POST, 'delete_column', FILTER_DEFAULT); + + if ($poll->format === 'D') { + $ex = explode('@', $column); + + $slot = new stdClass(); + $slot->title = $ex[0]; + $slot->moment = $ex[1]; + + $result = $adminPollService->deleteDateSlot($poll_id, $slot); + } else { + $result = $adminPollService->deleteClassicSlot($poll_id, $column); + } + + if ($result) { + $message = new Message('success', _('Column deleted.')); + } else { + $message = new Message('danger', _('Failed to delete the column.')); + } +} + +// ------------------------------- +// Add a slot +// ------------------------------- + +if (isset($_POST['add_slot'])) { + $smarty->assign('poll_id', $poll_id); + $smarty->assign('admin_poll_id', $admin_poll_id); + $smarty->assign('format', $poll->format); + $smarty->assign('title', _('Poll') . ' - ' . $poll->title); + $smarty->display('add_slot.tpl'); + exit; +} +if (isset($_POST['confirm_add_slot'])) { + if ($poll->format === 'D') { + $newdate = strip_tags($_POST['newdate']); + $newmoment = strip_tags($_POST['newmoment']); + + $ex = explode('/', $newdate); + $result = $adminPollService->addSlot($poll_id, mktime(0, 0, 0, $ex[1], $ex[0], $ex[2]), $newmoment); + } else { + $newslot = strip_tags($_POST['choice']); + $result = $adminPollService->addSlot($poll_id, $newslot, null); + } + + if ($result) { + $message = new Message('success', _('Column added.')); + } else { + $message = new Message('danger', _('Failed to add the column.')); + } +} + +// Retrieve data +$slots = $pollService->allSlotsByPollId($poll_id); +$votes = $pollService->allVotesByPollId($poll_id); +$comments = $pollService->allCommentsByPollId($poll_id); + + +// Assign data to template +$smarty->assign('poll_id', $poll_id); +$smarty->assign('admin_poll_id', $admin_poll_id); +$smarty->assign('poll', $poll); +$smarty->assign('title', _('Poll') . ' - ' . $poll->title); +$smarty->assign('expired', strtotime($poll->end_date) < time()); +$smarty->assign('deletion_date', $poll->end_date + PURGE_DELAY * 86400); +$smarty->assign('slots', $poll->format === 'D' ? $pollService->splitSlots($slots) : $slots); +$smarty->assign('votes', $pollService->splitVotes($votes)); +$smarty->assign('best_choices', $pollService->computeBestChoices($votes)); +$smarty->assign('comments', $comments); +$smarty->assign('editingVoteId', $editingVoteId); +$smarty->assign('message', $message); +$smarty->assign('admin', true); + +$smarty->display('studs.tpl'); \ No newline at end of file diff --git a/app/classes/Framadate/Choice.php b/app/classes/Framadate/Choice.php new file mode 100644 index 0000000..aab438c --- /dev/null +++ b/app/classes/Framadate/Choice.php @@ -0,0 +1,59 @@ +name = $name; + $this->slots = array(); + } + + public function addSlot($slot) + { + $this->slots[] = $slot; + } + + public function getName() + { + return $this->name; + } + + public function getSlots() + { + return $this->slots; + } + + static function compare(Choice $a, Choice $b) + { + return strcmp($a->name, $b->name); + } + +} diff --git a/app/classes/Framadate/Form.php b/app/classes/Framadate/Form.php new file mode 100644 index 0000000..76a4a4d --- /dev/null +++ b/app/classes/Framadate/Form.php @@ -0,0 +1,81 @@ +editable = true; + $this->clearChoices(); + } + + public function clearChoices() { + $this->choices = array(); + } + + public function addChoice(Choice $choice) + { + $this->choices[] = $choice; + } + + public function getChoices() + { + return $this->choices; + } + + public function sortChoices() + { + usort($this->choices, array('Framadate\Choice', 'compare')); + } + + public function lastChoice() + { + return end($this->choices); + } + +} \ No newline at end of file diff --git a/app/classes/Framadate/FramaDB.php b/app/classes/Framadate/FramaDB.php new file mode 100644 index 0000000..6b7c4c3 --- /dev/null +++ b/app/classes/Framadate/FramaDB.php @@ -0,0 +1,314 @@ +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); + } + + /** + * @return \PDO Connection to database + */ + function getPDO() { + return $this->pdo; + } + + /** + * Find all tables in database. + * + * @return array The array of table names + */ + function allTables() { + $result = $this->pdo->query('SHOW TABLES'); + $schemas = $result->fetchAll(\PDO::FETCH_COLUMN); + + return $schemas; + } + + function prepare($sql) { + return $this->pdo->prepare($sql); + } + + function beginTransaction() { + $this->pdo->beginTransaction(); + } + + function commit() { + $this->pdo->commit(); + } + + function rollback() { + $this->pdo->rollback(); + } + + function errorCode() { + return $this->pdo->errorCode(); + } + + function errorInfo() { + return $this->pdo->errorInfo(); + } + + function query($sql) { + return $this->pdo->query($sql); + } + + function findPollById($poll_id) { + $prepared = $this->prepare('SELECT * FROM `' . Utils::table('poll') . '` WHERE id = ?'); + + $prepared->execute([$poll_id]); + $poll = $prepared->fetch(); + $prepared->closeCursor(); + + return $poll; + } + + function updatePoll($poll) { + $prepared = $this->prepare('UPDATE `' . Utils::table('poll') . '` SET title=?, admin_name=?, admin_mail=?, description=?, end_date=FROM_UNIXTIME(?), active=?, editable=? WHERE id = ?'); + + return $prepared->execute([$poll->title, $poll->admin_name, $poll->admin_mail, $poll->description, $poll->end_date, $poll->active, $poll->editable, $poll->id]); + } + + function allCommentsByPollId($poll_id) { + $prepared = $this->prepare('SELECT * FROM `' . Utils::table('comment') . '` WHERE poll_id = ? ORDER BY id'); + $prepared->execute(array($poll_id)); + + return $prepared->fetchAll(); + } + + function allUserVotesByPollId($poll_id) { + $prepared = $this->prepare('SELECT * FROM `' . Utils::table('vote') . '` WHERE poll_id = ? ORDER BY id'); + $prepared->execute(array($poll_id)); + + return $prepared->fetchAll(); + } + + function allSlotsByPollId($poll_id) { + $prepared = $this->prepare('SELECT * FROM `' . Utils::table('slot') . '` WHERE poll_id = ? ORDER BY title'); + $prepared->execute(array($poll_id)); + + return $prepared->fetchAll(); + } + + function insertDefaultVote($poll_id, $insert_position) { + $prepared = $this->prepare('UPDATE `' . Utils::table('vote') . '` SET choices = CONCAT(SUBSTRING(choices, 1, ?), "0", SUBSTRING(choices, ?)) WHERE poll_id = ?'); + + return $prepared->execute([$insert_position, $insert_position + 1, $poll_id]); + } + + function insertVote($poll_id, $name, $choices) { + $prepared = $this->prepare('INSERT INTO `' . Utils::table('vote') . '` (poll_id, name, choices) VALUES (?,?,?)'); + $prepared->execute([$poll_id, $name, $choices]); + + $newVote = new \stdClass(); + $newVote->poll_id = $poll_id; + $newVote->id = $this->pdo->lastInsertId(); + $newVote->name = $name; + $newVote->choices = $choices; + + return $newVote; + } + + function deleteVote($poll_id, $vote_id) { + $prepared = $this->prepare('DELETE FROM `' . Utils::table('vote') . '` WHERE poll_id = ? AND id = ?'); + + return $prepared->execute([$poll_id, $vote_id]); + } + + /** + * Delete all votes of a given poll. + * + * @param $poll_id int The ID of the given poll. + * @return bool|null true if action succeeded. + */ + function deleteVotesByPollId($poll_id) { + $prepared = $this->prepare('DELETE FROM `' . Utils::table('vote') . '` WHERE poll_id = ?'); + + return $prepared->execute([$poll_id]); + } + + /** + * Delete all votes made on given moment index. + * + * @param $poll_id int The ID of the poll + * @param $index int The index of the vote into the poll + * @return bool|null true if action succeeded. + */ + function deleteVotesByIndex($poll_id, $index) { + $prepared = $this->prepare('UPDATE `' . Utils::table('vote') . '` SET choices = CONCAT(SUBSTR(choices, 1, ?), SUBSTR(choices, ?)) WHERE poll_id = ?'); + + return $prepared->execute([$index, $index + 2, $poll_id]); + } + + /** + * Find the slot into poll for a given datetime. + * + * @param $poll_id int The ID of the poll + * @param $datetime int The datetime of the slot + * @return mixed Object The slot found, or null + */ + function findSlotByPollIdAndDatetime($poll_id, $datetime) { + $prepared = $this->prepare('SELECT * FROM `' . Utils::table('slot') . '` WHERE poll_id = ? AND SUBSTRING_INDEX(title, \'@\', 1) = ?'); + + $prepared->execute([$poll_id, $datetime]); + $slot = $prepared->fetch(); + $prepared->closeCursor(); + + return $slot; + } + + /** + * Insert a new slot into a given poll. + * + * @param $poll_id int The ID of the poll + * @param $title mixed The title of the slot + * @param $moments mixed|null The moments joined with "," + * @return bool true if action succeeded + */ + function insertSlot($poll_id, $title, $moments) { + $prepared = $this->prepare('INSERT INTO `' . Utils::table('slot') . '` (poll_id, title, moments) VALUES (?,?,?)'); + + return $prepared->execute([$poll_id, $title, $moments]); + } + + /** + * Update a slot into a poll. + * + * @param $poll_id int The ID of the poll + * @param $datetime int The datetime of the slot to update + * @param $newMoments mixed The new moments + * @return bool|null true if action succeeded. + */ + function updateSlot($poll_id, $datetime, $newMoments) { + $prepared = $this->prepare('UPDATE `' . Utils::table('slot') . '` SET moments = ? WHERE poll_id = ? AND title = ?'); + + return $prepared->execute([$newMoments, $poll_id, $datetime]); + } + + /** + * Delete a entire slot from a poll. + * + * @param $poll_id int The ID of the poll + * @param $datetime mixed The datetime of the slot + */ + function deleteSlot($poll_id, $datetime) { + $prepared = $this->prepare('DELETE FROM `' . Utils::table('slot') . '` WHERE poll_id = ? AND title = ?'); + $prepared->execute([$poll_id, $datetime]); + } + + function deleteSlotsByPollId($poll_id) { + $prepared = $this->prepare('DELETE FROM `' . Utils::table('slot') . '` WHERE poll_id = ?'); + + return $prepared->execute([$poll_id]); + } + + /** + * Delete all comments of a given poll. + * + * @param $poll_id int The ID of the given poll. + * @return bool|null true if action succeeded. + */ + function deleteCommentsByPollId($poll_id) { + $prepared = $this->prepare('DELETE FROM `' . Utils::table('comment') . '` WHERE poll_id = ?'); + + return $prepared->execute([$poll_id]); + } + + function updateVote($poll_id, $vote_id, $name, $choices) { + $prepared = $this->prepare('UPDATE `' . Utils::table('vote') . '` SET choices = ?, name = ? WHERE poll_id = ? AND id = ?'); + + return $prepared->execute([$choices, $name, $poll_id, $vote_id]); + } + + function insertComment($poll_id, $name, $comment) { + $prepared = $this->prepare('INSERT INTO `' . Utils::table('comment') . '` (poll_id, name, comment) VALUES (?,?,?)'); + + return $prepared->execute([$poll_id, $name, $comment]); + } + + function deleteComment($poll_id, $comment_id) { + $prepared = $this->prepare('DELETE FROM `' . Utils::table('comment') . '` WHERE poll_id = ? AND id = ?'); + + return $prepared->execute([$poll_id, $comment_id]); + } + + function deletePollById($poll_id) { + $prepared = $this->prepare('DELETE FROM `' . Utils::table('poll') . '` WHERE id = ?'); + + return $prepared->execute([$poll_id]); + } + + /** + * Find old polls. Limit: 20. + * + * @return array Array of old polls + */ + public function findOldPolls() { + $prepared = $this->prepare('SELECT * FROM `' . Utils::table('poll') . '` WHERE DATE_ADD(`end_date`, INTERVAL ' . PURGE_DELAY . ' DAY) < NOW() AND `end_date` != 0 LIMIT 20'); + $prepared->execute([]); + + return $prepared->fetchAll(); + } + + /** + * @param $start int The index of the first poll to return + * @param $limit int The limit size + * @return array + */ + public function findAllPolls($start, $limit) { + // Polls + $prepared = $this->prepare(' +SELECT p.*, + (SELECT count(1) FROM `' . Utils::table('vote') . '` v WHERE p.id=v.poll_id) votes + FROM ' . Utils::table('poll') . ' p + ORDER BY p.title ASC + LIMIT :start, :limit'); + $prepared->bindParam(':start', $start, PDO::PARAM_INT); + $prepared->bindParam(':limit', $limit, PDO::PARAM_INT); + $prepared->execute(); + $polls = $prepared->fetchAll(); + + // Total count + $stmt = $this->query('SELECT count(1) nb FROM `' . Utils::table('poll') . '`'); + $count = $stmt->fetch(); + $stmt->closeCursor(); + + return ['polls' => $polls, 'count' => $count->nb]; + } + + public function countVotesByPollId($poll_id) { + $prepared = $this->prepare('SELECT count(1) nb FROM `' . Utils::table('vote') . '` WHERE poll_id = ?'); + + $prepared->execute([$poll_id]); + $result = $prepared->fetch(); + $prepared->closeCursor(); + + return $result->nb; + } +} diff --git a/app/classes/Framadate/Message.php b/app/classes/Framadate/Message.php new file mode 100644 index 0000000..9819e00 --- /dev/null +++ b/app/classes/Framadate/Message.php @@ -0,0 +1,32 @@ +type = $type; + $this->message = $message; + } + +} + \ No newline at end of file diff --git a/app/classes/Framadate/Migration/From_0_0_to_0_8_Migration.php b/app/classes/Framadate/Migration/From_0_0_to_0_8_Migration.php new file mode 100644 index 0000000..c85ec1a --- /dev/null +++ b/app/classes/Framadate/Migration/From_0_0_to_0_8_Migration.php @@ -0,0 +1,86 @@ +query('SHOW TABLES'); + $tables = $stmt->fetchAll(\PDO::FETCH_COLUMN); + + // Check if there is no tables but the MIGRATION_TABLE one + $diff = array_diff($tables, [Utils::table(MIGRATION_TABLE)]); + return count($diff) === 0; + } + + /** + * This methode is called only one time in the migration page. + * + * @param \PDO $pdo The connection to database + * @return bool true is the execution succeeded + */ + function execute(\PDO $pdo) { + $pdo->exec(' +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\', + `statut` int(11) NOT NULL DEFAULT \'1\' COMMENT \'1 = actif ; 0 = inactif ; \', + UNIQUE KEY `id_sondage` (`id_sondage`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8;'); + + $pdo->exec(' +CREATE TABLE IF NOT EXISTS `sujet_studs` ( + `id_sondage` char(16) NOT NULL, + `sujet` text, + KEY `id_sondage` (`id_sondage`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8;'); + + $pdo->exec(' +CREATE TABLE IF NOT EXISTS `comments` ( + `id_comment` int(11) unsigned NOT NULL AUTO_INCREMENT, + `id_sondage` char(16) NOT NULL, + `comment` text NOT NULL, + `usercomment` text, + PRIMARY KEY (`id_comment`), + KEY `id_sondage` (`id_sondage`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;'); + + $pdo->exec(' +CREATE TABLE IF NOT EXISTS `user_studs` ( + `id_users` int(11) unsigned NOT NULL AUTO_INCREMENT, + `nom` varchar(64) NOT NULL, + `id_sondage` char(16) NOT NULL, + `reponses` text NOT NULL, + PRIMARY KEY (`id_users`), + KEY `id_sondage` (`id_sondage`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;'); + } +} diff --git a/app/classes/Framadate/Migration/From_0_8_to_0_9_Migration.php b/app/classes/Framadate/Migration/From_0_8_to_0_9_Migration.php new file mode 100644 index 0000000..e570b5f --- /dev/null +++ b/app/classes/Framadate/Migration/From_0_8_to_0_9_Migration.php @@ -0,0 +1,273 @@ +query('SHOW TABLES'); + $tables = $stmt->fetchAll(\PDO::FETCH_COLUMN); + + // Check if tables of v0.8 are presents + $diff = array_diff(['sondage', 'sujet_studs', 'comments', 'user_studs'], $tables); + return count($diff) === 0; + } + + /** + * This methode is called only one time in the migration page. + * + * @param \PDO $pdo The connection to database + * @return bool true is the execution succeeded + */ + function execute(\PDO $pdo) { + $this->createPollTable($pdo); + $this->createCommentTable($pdo); + $this->createSlotTable($pdo); + $this->createVoteTable($pdo); + + $pdo->beginTransaction(); + $this->migrateFromSondageToPoll($pdo); + $this->migrateFromCommentsToComment($pdo); + $this->migrateFromSujetStudsToSlot($pdo); + $this->migrateFromUserStudsToVote($pdo); + $pdo->commit(); + + $this->dropOldTables($pdo); + + return true; + } + + private function createPollTable(\PDO $pdo) { + $pdo->exec(' +CREATE TABLE IF NOT EXISTS `' . Utils::table('poll') . '` ( + `id` CHAR(16) NOT NULL, + `admin_id` CHAR(24) NOT NULL, + `title` TEXT NOT NULL, + `description` 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\', + `active` TINYINT(1) DEFAULT \'1\', + PRIMARY KEY (`id`) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8'); + } + + private function migrateFromSondageToPoll(\PDO $pdo) { + $select = $pdo->query(' +SELECT + `id_sondage`, + `id_sondage_admin`, + `titre`, + `commentaires`, + `nom_admin`, + `mail_admin`, + `date_creation`, + `date_fin`, + SUBSTR(`format`, 1, 1) AS `format`, + CASE SUBSTR(`format`, 2, 1) + WHEN \'+\' THEN 1 + ELSE 0 END AS `editable`, + `mailsonde`, + CASE SUBSTR(`format`, 2, 1) + WHEN \'-\' THEN 0 + ELSE 1 END AS `active` + FROM sondage'); + + $insert = $pdo->prepare(' +INSERT INTO `' . Utils::table('poll') . '` +(`id`, `admin_id`, `title`, `description`, `admin_name`, `admin_mail`, `creation_date`, `end_date`, `format`, `editable`, `receiveNewVotes`, `active`) +VALUE (?,?,?,?,?,?,?,?,?,?,?,?)'); + + while ($row = $select->fetch(\PDO::FETCH_OBJ)) { + $insert->execute([ + $row->id_sondage, + $row->id_sondage_admin, + $this->unescape($row->titre), + $this->unescape($row->commentaires), + $this->unescape($row->nom_admin), + $this->unescape($row->mail_admin), + $row->date_creation, + $row->date_fin, + $row->format, + $row->editable, + $row->mailsonde, + $row->active + ]); + } + } + + private function createSlotTable(\PDO $pdo) { + $pdo->exec(' +CREATE TABLE IF NOT EXISTS `' . Utils::table('slot') . '` ( + `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `poll_id` CHAR(16) NOT NULL, + `title` TEXT, + `moments` TEXT, + PRIMARY KEY (`id`), + KEY `poll_id` (`poll_id`) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8'); + } + + private function migrateFromSujetStudsToSlot(\PDO $pdo) { + $stmt = $pdo->query('SELECT * FROM sujet_studs'); + $sujets = $stmt->fetchAll(); + $slots = []; + + foreach ($sujets as $sujet) { + $newSlots = $this->transformSujetToSlot($sujet); + $slots = array_merge($slots, $newSlots); + } + + $prepared = $pdo->prepare('INSERT INTO ' . Utils::table('slot') . ' (`poll_id`, `title`, `moments`) VALUE (?,?,?)'); + foreach ($slots as $slot) { + $prepared->execute([ + $slot->poll_id, + $this->unescape($slot->title), + !empty($slot->moments) ? $this->unescape($slot->moments) : null + ]); + } + } + + private function createCommentTable(\PDO $pdo) { + $pdo->exec(' +CREATE TABLE IF NOT EXISTS `' . Utils::table('comment') . '` ( + `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `poll_id` CHAR(16) NOT NULL, + `name` TEXT, + `comment` TEXT NOT NULL, + PRIMARY KEY (`id`), + KEY `poll_id` (`poll_id`) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8'); + } + + private function migrateFromCommentsToComment(\PDO $pdo) { + $select = $pdo->query(' +SELECT + `id_sondage`, + `usercomment`, + `comment` + FROM `comments`'); + + $insert = $pdo->prepare(' +INSERT INTO `' . Utils::table('comment') . '` (`poll_id`, `name`, `comment`) +VALUE (?,?,?)'); + + while ($row = $select->fetch(\PDO::FETCH_OBJ)) { + $insert->execute([ + $row->id_sondage, + $this->unescape($row->usercomment), + $this->unescape($row->comment) + ]); + } + } + + private function createVoteTable(\PDO $pdo) { + $pdo->exec(' +CREATE TABLE IF NOT EXISTS `' . Utils::table('vote') . '` ( + `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `poll_id` CHAR(16) NOT NULL, + `name` VARCHAR(64) NOT NULL, + `choices` TEXT NOT NULL, + PRIMARY KEY (`id`), + KEY `poll_id` (`poll_id`) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8'); + } + + private function migrateFromUserStudsToVote(\PDO $pdo) { + $select = $pdo->query(' +SELECT + `id_sondage`, + `nom`, + REPLACE(REPLACE(REPLACE(`reponses`, 1, \'X\'), 2, 1), \'X\', 2) reponses + FROM `user_studs`'); + + $insert = $pdo->prepare(' +INSERT INTO `' . Utils::table('vote') . '` (`poll_id`, `name`, `choices`) +VALUE (?,?,?)'); + + while ($row = $select->fetch(\PDO::FETCH_OBJ)) { + $insert->execute([ + $row->id_sondage, + $this->unescape($row->nom), + $row->reponses + ]); + } + } + + private function transformSujetToSlot($sujet) { + $slots = []; + $ex = explode(',', $sujet->sujet); + $isDatePoll = strpos($sujet->sujet, '@'); + $lastSlot = null; + + foreach ($ex as $atomicSlot) { + if ($isDatePoll === false) { // Classic poll + $slot = new \stdClass(); + $slot->poll_id = $sujet->id_sondage; + $slot->title = $atomicSlot; + $slots[] = $slot; + } else { // Date poll + $values = explode('@', $atomicSlot); + if ($lastSlot == null || $lastSlot->title !== $values[0]) { + $lastSlot = new \stdClass(); + $lastSlot->poll_id = $sujet->id_sondage; + $lastSlot->title = $values[0]; + $lastSlot->moments = count($values) == 2 ? $values[1] : '-'; + $slots[] = $lastSlot; + } else { + $lastSlot->moments .= ',' . (count($values) == 2 ? $values[1] : '-'); + } + } + } + + return $slots; + } + + private function dropOldTables(\PDO $pdo) { + $pdo->exec('DROP TABLE `comments`'); + $pdo->exec('DROP TABLE `sujet_studs`'); + $pdo->exec('DROP TABLE `user_studs`'); + $pdo->exec('DROP TABLE `sondage`'); + } + + private function unescape($value) { + return stripslashes(html_entity_decode($value, ENT_QUOTES)); + } +} diff --git a/app/classes/Framadate/Migration/From_0_9_to_0_9_1_Migration.php b/app/classes/Framadate/Migration/From_0_9_to_0_9_1_Migration.php new file mode 100644 index 0000000..49896ba --- /dev/null +++ b/app/classes/Framadate/Migration/From_0_9_to_0_9_1_Migration.php @@ -0,0 +1,60 @@ +query('SHOW TABLES'); + $tables = $stmt->fetchAll(\PDO::FETCH_COLUMN); + + // Check if tables of v0.9 are presents + $diff = array_diff([Utils::table('poll'), Utils::table('slot'), Utils::table('vote'), Utils::table('comment')], $tables); + return count($diff) === 0; + } + + /** + * This methode is called only one time in the migration page. + * + * @param \PDO $pdo The connection to database + * @return bool true is the execution succeeded + */ + function execute(\PDO $pdo) { + $this->alterPollTable($pdo); + + return true; + } + + private function alterPollTable(\PDO $pdo) { + $pdo->exec(' +ALTER TABLE `' . Utils::table('poll') . '` + ADD `receiveNewComments` TINYINT(1) DEFAULT \'0\' + AFTER `receiveNewVotes`'); + } + +} diff --git a/app/classes/Framadate/Migration/Migration.php b/app/classes/Framadate/Migration/Migration.php new file mode 100644 index 0000000..0cd22f8 --- /dev/null +++ b/app/classes/Framadate/Migration/Migration.php @@ -0,0 +1,31 @@ +time = time() + TOKEN_TIME; + $this->value = $this->generate(); + } + + private function generate() { + return sha1(uniqid(mt_rand(), true)); + } + + public function getTime() { + return $this->time; + } + + public function getValue() { + return $this->value; + } + + public function isGone() { + return $this->time < time(); + } + + public function check($value) { + return $value === $this->value; + } + +} + \ No newline at end of file diff --git a/app/classes/Framadate/Services/AdminPollService.php b/app/classes/Framadate/Services/AdminPollService.php new file mode 100644 index 0000000..70699bb --- /dev/null +++ b/app/classes/Framadate/Services/AdminPollService.php @@ -0,0 +1,270 @@ +connect = $connect; + $this->pollService = $pollService; + $this->logService = $logService; + } + + function updatePoll($poll) { + global $config; + if ($poll->end_date > $poll->creation_date && $poll->end_date <= strtotime($poll->creation_date) + (86400 * $config['default_poll_duration'])) { + return $this->connect->updatePoll($poll); + } else { + return false; + } + } + + /** + * Delete a comment from a poll. + * + * @param $poll_id int The ID of the poll + * @param $comment_id int The ID of the comment + * @return mixed true is action succeeded + */ + function deleteComment($poll_id, $comment_id) { + return $this->connect->deleteComment($poll_id, $comment_id); + } + + /** + * Remove all comments of a poll. + * + * @param $poll_id int The ID a the poll + * @return bool|null true is action succeeded + */ + function cleanComments($poll_id) { + $this->logService->log("CLEAN_COMMENTS", "id:$poll_id"); + return $this->connect->deleteCommentsByPollId($poll_id); + } + + /** + * Delete a vote from a poll. + * + * @param $poll_id int The ID of the poll + * @param $vote_id int The ID of the vote + * @return mixed true is action succeeded + */ + function deleteVote($poll_id, $vote_id) { + return $this->connect->deleteVote($poll_id, $vote_id); + } + + /** + * Remove all votes of a poll. + * + * @param $poll_id int The ID of the poll + * @return bool|null true is action succeeded + */ + function cleanVotes($poll_id) { + $this->logService->log('CLEAN_VOTES', 'id:' . $poll_id); + return $this->connect->deleteVotesByPollId($poll_id); + } + + /** + * Delete the entire given poll. + * + * @param $poll_id int The ID of the poll + * @return bool true is action succeeded + */ + function deleteEntirePoll($poll_id) { + $poll = $this->connect->findPollById($poll_id); + $this->logService->log('DELETE_POLL', "id:$poll->id, format:$poll->format, admin:$poll->admin_name, mail:$poll->admin_mail"); + + // Delete the entire poll + $this->connect->deleteVotesByPollId($poll_id); + $this->connect->deleteCommentsByPollId($poll_id); + $this->connect->deleteSlotsByPollId($poll_id); + $this->connect->deletePollById($poll_id); + + return true; + } + + /** + * Delete a slot from a poll. + * + * @param $poll_id int The ID of the poll + * @param $slot object The slot informations (datetime + moment) + * @return bool true if action succeeded + */ + public function deleteDateSlot($poll_id, $slot) { + $this->logService->log('DELETE_SLOT', 'id:' . $poll_id . ', slot:' . json_encode($slot)); + + $datetime = $slot->title; + $moment = $slot->moment; + + $slots = $this->pollService->allSlotsByPollId($poll_id); + + $index = 0; + $indexToDelete = -1; + $newMoments = []; + + // Search the index of the slot to delete + foreach ($slots as $aSlot) { + $moments = explode(',', $aSlot->moments); + + foreach ($moments as $rowMoment) { + if ($datetime == $aSlot->title) { + if ($moment == $rowMoment) { + $indexToDelete = $index; + } else { + $newMoments[] = $rowMoment; + } + } + $index++; + } + } + + // Remove votes + $this->connect->beginTransaction(); + $this->connect->deleteVotesByIndex($poll_id, $indexToDelete); + if (count($newMoments) > 0) { + $this->connect->updateSlot($poll_id, $datetime, implode(',', $newMoments)); + } else { + $this->connect->deleteSlot($poll_id, $datetime); + } + $this->connect->commit(); + + return true; + } + + public function deleteClassicSlot($poll_id, $slot_title) { + $this->logService->log('DELETE_SLOT', 'id:' . $poll_id . ', slot:' . $slot_title); + + $slots = $this->pollService->allSlotsByPollId($poll_id); + + $index = 0; + $indexToDelete = -1; + + // Search the index of the slot to delete + foreach ($slots as $aSlot) { + if ($slot_title == $aSlot->title) { + $indexToDelete = $index; + } + $index++; + } + + // Remove votes + $this->connect->beginTransaction(); + $this->connect->deleteVotesByIndex($poll_id, $indexToDelete); + $this->connect->deleteSlot($poll_id, $slot_title); + $this->connect->commit(); + + return true; + } + + /** + * Add a new slot to the poll. And insert default values for user's votes. + * + * + * @param $poll_id int The ID of the poll + * @param $datetime int The datetime + * @param $new_moment string The moment's name + * @return bool true if added + */ + public function addSlot($poll_id, $datetime, $new_moment) { + $slots = $this->connect->allSlotsByPollId($poll_id); + $result = $this->findInsertPosition($slots, $datetime, $new_moment); + + // Begin transaction + $this->connect->beginTransaction(); + + if ($result == null) { + // The moment already exists + return false; + } elseif ($result->slot != null) { + $slot = $result->slot; + $moments = explode(',', $slot->moments); + + // Check if moment already exists (maybe not necessary) + if (in_array($new_moment, $moments)) { + return false; + } + + // Update found slot + $moments[] = $new_moment; + sort($moments); + $this->connect->updateSlot($poll_id, $datetime, implode(',', $moments)); + + } else { + $this->connect->insertSlot($poll_id, $datetime, $new_moment); + } + + $this->connect->insertDefaultVote($poll_id, $result->insert); + + // Commit transaction + $this->connect->commit(); + + return true; + + } + + /** + * This method find where to insert a datatime+moment into a list of slots.
    + * Return the {insert:X}, where X is the index of the moment into the whole poll (ex: X=0 => Insert to the first column). + * Return {slot:Y}, where Y is not null if there is a slot existing for the given datetime. + * + * @param $slots array All the slots of the poll + * @param $datetime int The datetime of the new slot + * @param $moment string The moment's name + * @return null|\stdClass An object like this one: {insert:X, slot:Y} where Y can be null. + */ + private function findInsertPosition($slots, $datetime, $moment) { + $result = new \stdClass(); + $result->slot = null; + $result->insert = -1; + + $i = 0; + + foreach ($slots as $slot) { + $rowDatetime = $slot->title; + $moments = explode(',', $slot->moments); + + if ($datetime == $rowDatetime) { + $result->slot = $slot; + + foreach ($moments as $rowMoment) { + $strcmp = strcmp($moment, $rowMoment); + if ($strcmp < 0) { + // Here we have to insert at First place or middle of the slot + break(2); + } elseif ($strcmp == 0) { + // Here we dont have to insert at all + return null; + } + $i++; + } + + // Here we have to insert at the end of a slot + $result->insert = $i; + break; + } elseif ($datetime < $rowDatetime) { + // Here we have to insert a new slot + break; + } else { + $i += count($moments); + } + } + $result->insert = $i; + + return $result; + } + +} + \ No newline at end of file diff --git a/app/classes/Framadate/Services/InputService.php b/app/classes/Framadate/Services/InputService.php new file mode 100644 index 0000000..aafed00 --- /dev/null +++ b/app/classes/Framadate/Services/InputService.php @@ -0,0 +1,49 @@ +$item) { + $item = filter_var($item, $type, $options); + if ($item !== false) { + $newArr[$id] = $item; + } + } + + return $newArr; + } + + function filterAllowedValues($value, array $allowedValues) { + return in_array($value, $allowedValues, true) ? $value : null; + } + +} \ No newline at end of file diff --git a/app/classes/Framadate/Services/LogService.php b/app/classes/Framadate/Services/LogService.php new file mode 100644 index 0000000..4f68463 --- /dev/null +++ b/app/classes/Framadate/Services/LogService.php @@ -0,0 +1,25 @@ +smtp_allowed = $smtp_allowed; + } + + public function isValidEmail($email) { + return filter_var($email, FILTER_VALIDATE_EMAIL); + } + + function send($to, $subject, $body, $param = '') { + if($this->smtp_allowed == true) { + mb_internal_encoding('UTF-8'); + + $subject = mb_encode_mimeheader(html_entity_decode($subject, ENT_QUOTES, 'UTF-8'), 'UTF-8', 'B', "\n", 9); + + $encoded_app = mb_encode_mimeheader(NOMAPPLICATION, 'UTF-8', 'B', "\n", 6); + $size_encoded_app = (6 + strlen($encoded_app)) % 75; + $size_admin_email = strlen(ADRESSEMAILADMIN); + + if (($size_encoded_app + $size_admin_email + 9) > 74) { + $folding = "\n"; + } else { + $folding = ''; + }; + + $from = sprintf("From: %s%s <%s>\n", $encoded_app, $folding, ADRESSEMAILADMIN); + + $headers = $from; + $headers .= 'Reply-To: ' . ADRESSEMAILREPONSEAUTO . "\n"; + $headers .= "MIME-Version: 1.0\n"; + $headers .= "Content-Type: text/plain; charset=UTF-8\n"; + $headers .= "Content-Transfer-Encoding: 8bit\n"; + $headers .= "Auto-Submitted:auto-generated\n"; + $headers .= 'Return-Path: <>'; + + $body = html_entity_decode($body, ENT_QUOTES, 'UTF-8') . _("\n--\n\n« La route est longue, mais la voie est libre… »\nFramasoft ne vit que par vos dons (déductibles des impôts).\nMerci d'avance pour votre soutien http://soutenir.framasoft.org."); + + mail($to, $subject, $body, $headers, $param); + } + } + +} + \ No newline at end of file diff --git a/app/classes/Framadate/Services/PollService.php b/app/classes/Framadate/Services/PollService.php new file mode 100644 index 0000000..cf32713 --- /dev/null +++ b/app/classes/Framadate/Services/PollService.php @@ -0,0 +1,190 @@ +connect = $connect; + $this->logService = $logService; + } + + /** + * Find a poll from its ID. + * + * @param $poll_id int The ID of the poll + * @return \stdClass|null The found poll, or null + */ + 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 allVotesByPollId($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, $name, $choices) { + $choices = implode($choices); + + return $this->connect->updateVote($poll_id, $vote_id, $name, $choices); + } + + function addVote($poll_id, $name, $choices) { + $choices = implode($choices); + + return $this->connect->insertVote($poll_id, $name, $choices); + } + + function addComment($poll_id, $name, $comment) { + // TODO Check if there is no duplicate before to add a new comment + return $this->connect->insertComment($poll_id, $name, $comment); + } + + public function countVotesByPollId($poll_id) { + return $this->connect->countVotesByPollId($poll_id); + } + + function computeBestChoices($votes) { + $result = []; + foreach ($votes as $vote) { + $choices = str_split($vote->choices); + 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) { + $obj = new \stdClass(); + $obj->day = $slot->title; + $obj->moments = explode(',', $slot->moments); + + $splitted[] = $obj; + } + + return $splitted; + } + + function splitVotes($votes) { + $splitted = array(); + foreach ($votes as $vote) { + $obj = new \stdClass(); + $obj->id = $vote->id; + $obj->name = $vote->name; + $obj->choices = str_split($vote->choices); + + $splitted[] = $obj; + } + + return $splitted; + } + + /** + * @param Form $form + * @return string + */ + function createPoll(Form $form) { + + // Generate poll IDs + $poll_id = $this->random(16); + $admin_poll_id = $poll_id . $this->random(8); + + // Insert poll + slots + $this->connect->beginTransaction(); + + // TODO Extract this to FramaDB (or repository layer) + $sql = 'INSERT INTO ' . Utils::table('poll') . ' + (id, admin_id, title, description, admin_name, admin_mail, end_date, format, editable, receiveNewVotes, receiveNewComments) + VALUES (?,?,?,?,?,?,FROM_UNIXTIME(?),?,?,?,?)'; + $prepared = $this->connect->prepare($sql); + $prepared->execute(array($poll_id, $admin_poll_id, $form->title, $form->description, $form->admin_name, $form->admin_mail, $form->end_date, $form->format, $form->editable, $form->receiveNewVotes, $form->receiveNewComments)); + + $prepared = $this->connect->prepare('INSERT INTO ' . Utils::table('slot') . ' (poll_id, title, moments) VALUES (?, ?, ?)'); + + foreach ($form->getChoices() as $choice) { + + // We prepared the slots (joined by comas) + $joinedSlots = ''; + $first = true; + foreach ($choice->getSlots() as $slot) { + if ($first) { + $joinedSlots = $slot; + $first = false; + } else { + $joinedSlots .= ',' . $slot; + } + } + + // We execute the insertion + if (empty($joinedSlots)) { + $prepared->execute(array($poll_id, $choice->getName(), null)); + } else { + $prepared->execute(array($poll_id, $choice->getName(), $joinedSlots)); + } + + } + + $this->connect->commit(); + + $this->logService->log('CREATE_POLL', 'id:' . $poll_id . ', title: ' . $form->title . ', format:' . $form->format . ', admin:' . $form->admin_name . ', mail:' . $form->admin_mail); + + + return [$poll_id, $admin_poll_id]; + } + + private function random($car) { + // TODO Better random ? + $string = ''; + $chaine = 'abcdefghijklmnopqrstuvwxyz123456789'; + mt_srand(); + for ($i = 0; $i < $car; $i++) { + $string .= $chaine[mt_rand() % strlen($chaine)]; + } + + return $string; + } +} diff --git a/app/classes/Framadate/Services/PurgeService.php b/app/classes/Framadate/Services/PurgeService.php new file mode 100644 index 0000000..fc05365 --- /dev/null +++ b/app/classes/Framadate/Services/PurgeService.php @@ -0,0 +1,69 @@ +connect = $connect; + $this->logService = $logService; + } + + /** + * This methode purges all old polls (the ones with end_date in past). + * + * @return bool true is action succeeded + */ + function purgeOldPolls() { + $oldPolls = $this->connect->findOldPolls(); + $count = count($oldPolls); + + if ($count > 0) { + $this->logService->log('EXPIRATION', 'Going to purge ' . $count . ' poll(s)...'); + + foreach ($oldPolls as $poll) { + if ($this->purgePollById($poll->id)) { + $this->logService->log('EXPIRATION_SUCCESS', 'id: ' . $poll->id . ', title:' . $poll->title . ', format: '.$poll->format . ', admin: ' . $poll->admin_name); + } else { + $this->logService->log('EXPIRATION_FAILED', 'id: ' . $poll->id . ', title:' . $poll->title . ', format: '.$poll->format . ', admin: ' . $poll->admin_name); + } + } + } + + return $count; + } + + /** + * This methode delete all data about a poll. + * + * @param $poll_id int The ID of the poll + * @return bool true is action succeeded + */ + function purgePollById($poll_id) { + $done = true; + + $this->connect->beginTransaction(); + $done &= $this->connect->deleteCommentsByPollId($poll_id); + $done &= $this->connect->deleteVotesByPollId($poll_id); + $done &= $this->connect->deleteSlotsByPollId($poll_id); + $done &= $this->connect->deletePollById($poll_id); + + if ($done) { + $this->connect->commit(); + } else { + $this->connect->rollback(); + } + + return $done; + } + +} + \ No newline at end of file diff --git a/app/classes/Framadate/Services/SecurityService.php b/app/classes/Framadate/Services/SecurityService.php new file mode 100644 index 0000000..fc67a72 --- /dev/null +++ b/app/classes/Framadate/Services/SecurityService.php @@ -0,0 +1,52 @@ + + *
  • There no token with the given name in session
  • + *
  • The token time is in past
  • + * + * + * @param $tokan_name string The name of the CSRF token + * @return Token The token + */ + function getToken($tokan_name) { + if (!isset($_SESSION['tokens'])) { + $_SESSION['tokens'] = []; + } + if (!isset($_SESSION['tokens'][$tokan_name]) || $_SESSION['tokens'][$tokan_name]->isGone()) { + $_SESSION['tokens'][$tokan_name] = new Token(); + } + + return $_SESSION['tokens'][$tokan_name]->getValue(); + } + + /** + * Check if a given value is corresponding to the token in session. + * + * @param $tokan_name string Name of the token + * @param $csrf string Value to check + * @return bool true if the token is well checked + */ + public function checkCsrf($tokan_name, $csrf) { + $checked = $_SESSION['tokens'][$tokan_name]->getValue() === $csrf; + + if($checked) { + unset($_SESSION['tokens'][$tokan_name]); + } + + return $checked; + } + +} + \ No newline at end of file diff --git a/app/classes/Framadate/Services/SuperAdminService.php b/app/classes/Framadate/Services/SuperAdminService.php new file mode 100644 index 0000000..af8a305 --- /dev/null +++ b/app/classes/Framadate/Services/SuperAdminService.php @@ -0,0 +1,32 @@ +connect = $connect; + } + + /** + * Return the list of all polls. + * + * @param $page int The page index (O = first page) + * @param $limit int The limit size + * @return array ['polls' => The {$limit} polls, 'count' => Total count] + * polls, 'count' => Total count] + */ + public function findAllPolls($page, $limit) { + return $this->connect->findAllPolls($page * $limit, $limit); + } + +} + \ No newline at end of file diff --git a/app/classes/Framadate/Utils.php b/app/classes/Framadate/Utils.php index 3333c75..dc14eca 100644 --- a/app/classes/Framadate/Utils.php +++ b/app/classes/Framadate/Utils.php @@ -18,45 +18,21 @@ */ namespace Framadate; -class Utils -{ - public static function get_server_name() - { - $scheme = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') ? 'https' : 'http'; - $port = in_array($_SERVER['SERVER_PORT'], [80, 443]) ? '/' : ':' . $_SERVER['SERVER_PORT'] . '/'; - $server_name = $_SERVER['SERVER_NAME'] . $port . dirname($_SERVER['SCRIPT_NAME']) . '/'; +class Utils { + /** + * @return string Server name + */ + public static function get_server_name() { + $scheme = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http'; + $port = in_array($_SERVER['SERVER_PORT'], [80, 443]) ? '' : ':' . $_SERVER['SERVER_PORT']; + $dirname = dirname($_SERVER['SCRIPT_NAME']); + $dirname = $dirname === '\\' ? '/' : $dirname . '/'; + $server_name = $_SERVER['SERVER_NAME'] . $port . $dirname; - return $scheme . '://' . str_replace('/admin','',str_replace('//','/',str_replace('///','/',$server_name))); + return $scheme . '://' . str_replace('/admin', '', str_replace('//', '/', str_replace('///', '/', $server_name))); } - public static function get_sondage_from_id($id) - { - global $connect; - - // Open database - if (preg_match(';^[\w\d]{16}$;i', $id)) { - $sql = 'SELECT sondage.*,sujet_studs.sujet FROM sondage - LEFT OUTER JOIN sujet_studs ON sondage.id_sondage = sujet_studs.id_sondage - WHERE sondage.id_sondage = ' . $connect->Param('id_sondage'); - - $sql = $connect->Prepare($sql); - $sondage = $connect->Execute($sql, [$id]); - - if ($sondage === false) { - return false; - } - - $psondage = $sondage->FetchObject(false); - $psondage->date_fin = strtotime($psondage->date_fin); - - return $psondage; - } - - return false; - } - - public static function is_error($cerr) - { + public static function is_error($cerr) { global $err; if ($err == 0) { return false; @@ -65,38 +41,40 @@ class Utils return ($err & $cerr) != 0; } - public static function is_user() - { + public static function is_user() { return (USE_REMOTE_USER && isset($_SERVER['REMOTE_USER'])) || isset($_SESSION['nom']); } - public static function print_header($title = '') - { - global $lang; + /** + * @param string $title + * @deprecated + */ + public static function print_header($title = '') { + global $html_lang; echo ' - + - '; + '; - if (! empty($title)) { + if (!empty($title)) { echo '' . stripslashes($title) . ' - ' . NOMAPPLICATION . ''; } else { echo '' . NOMAPPLICATION . ''; } echo ' - - - - - + + + + + - + '; - if (file_exists($_SERVER['DOCUMENT_ROOT']."/nav/nav.js")) { + if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/nav/nav.js")) { echo ''; } @@ -104,107 +82,26 @@ class Utils
    '; - - } - - public static function check_table_sondage() - { - global $connect; - - if (in_array('sondage', $connect->MetaTables('TABLES'))) { - return true; - } - - return false; } /** * Check if an email address is valid using PHP filters * - * @param string $email Email address to check + * @param string $email Email address to check * @return bool True if valid. False if not valid. + * @deprecated */ - public static function isValidEmail($email) - { + public static function isValidEmail($email) { return filter_var($email, FILTER_VALIDATE_EMAIL); } - /** - * Envoi un courrier avec un codage correct de To et Subject - * Les en-têtes complémentaires ne sont pas gérés - * - */ - public static function sendEmail( $to, $subject, $body, $headers='', $param='') - { - - mb_internal_encoding('UTF-8'); - - $subject = mb_encode_mimeheader(html_entity_decode($subject, ENT_QUOTES, 'UTF-8'), 'UTF-8', 'B', "\n", 9); - - $encoded_app = mb_encode_mimeheader(NOMAPPLICATION, 'UTF-8', 'B', "\n", 6); - $size_encoded_app = (6 + strlen($encoded_app)) % 75; - $size_admin_email = strlen(ADRESSEMAILADMIN); - - if (($size_encoded_app + $size_admin_email + 9) > 74 ) { - $folding = "\n"; - } else { - $folding = ''; - }; - - /* - Si $headers ne contient qu'une adresse email, on la considère comme - adresse de reply-to, sinon on met l'adresse de no-reply definie - dans constants.php - */ - if (self::isValidEmail($headers)) { - $replyTo = $headers; - $headers = ''; // on reinitialise $headers - } else { - $replyTo = ADRESSEMAILREPONSEAUTO; - } - - $from = sprintf( "From: %s%s <%s>\n", $encoded_app, $folding, ADRESSEMAILADMIN); - - if ($headers) { - $headers .= "\n" ; - } - - $headers .= $from; - $headers .= "Reply-To: $replyTo\n"; - $headers .= "MIME-Version: 1.0\n"; - $headers .= "Content-Type: text/plain; charset=UTF-8\n"; - $headers .= "Content-Transfer-Encoding: 8bit\n"; - $headers .= "Auto-Submitted:auto-generated\n"; - $headers .= "Return-Path: <>"; - - $body = html_entity_decode($body, ENT_QUOTES, 'UTF-8')._("\n--\n\n« La route est longue, mais la voie est libre… »\nFramasoft ne vit que par vos dons (déductibles des impôts).\nMerci d'avance pour votre soutien http://soutenir.framasoft.org."); - - mail($to, $subject, $body, $headers, $param); - } - - /** - * Fonction vérifiant l'existance et la valeur non vide d'une clé d'un tableau - * @param string $name La clé à tester - * @param array $tableau Le tableau où rechercher la clé ($_POST par défaut) - * @return bool Vrai si la clé existe et renvoie une valeur non vide - */ - public static function issetAndNoEmpty($name, $tableau = null) - { - if (is_null($tableau)) { - $tableau = $_POST; - } - - return isset($tableau[$name]) && ! empty($tableau[$name]); - } - /** * Fonction permettant de générer les URL pour les sondage - * @param string $id L'identifiant du sondage - * @param bool $admin True pour générer une URL pour l'administration d'un sondage, False pour un URL publique + * @param string $id L'identifiant du sondage + * @param bool $admin True pour générer une URL pour l'administration d'un sondage, False pour un URL publique * @return string L'url pour le sondage */ - public static function getUrlSondage($id, $admin = false) - { + public static function getUrlSondage($id, $admin = false) { if (URL_PROPRE) { if ($admin === true) { $url = str_replace('/admin', '', self::get_server_name()) . $id . '/admin'; @@ -213,52 +110,75 @@ class Utils } } else { if ($admin === true) { - $url = str_replace('/admin', '', self::get_server_name()) . 'adminstuds.php?sondage=' . $id; + $url = str_replace('/admin', '', self::get_server_name()) . 'adminstuds.php?poll=' . $id; } else { - $url = str_replace('/admin', '', self::get_server_name()) . 'studs.php?sondage=' . $id; + $url = str_replace('/admin', '', self::get_server_name()) . 'studs.php?poll=' . $id; } } return $url; } - public static function remove_sondage($connect, $numsondage) - { - $connect->StartTrans(); - - $req = 'DELETE FROM sondage WHERE id_sondage = ' . $connect->Param('numsondage') ; - $sql = $connect->Prepare($req); - $connect->Execute($sql, [$numsondage]); - - $req = 'DELETE FROM sujet_studs WHERE id_sondage = ' . $connect->Param('numsondage') ; - $sql = $connect->Prepare($req); - $connect->Execute($sql, [$numsondage]); - - $req = 'DELETE FROM user_studs WHERE id_sondage = ' . $connect->Param('numsondage') ; - $sql = $connect->Prepare($req); - $connect->Execute($sql, [$numsondage]); - - $req = 'DELETE FROM comments WHERE id_sondage = ' . $connect->Param('numsondage') ; - $sql = $connect->Prepare($req); - $connect->Execute($sql, [$numsondage]); - - $suppression_OK = ! $connect->HasFailedTrans(); - $connect->CompleteTrans(); - - return $suppression_OK ; + /** + * This method pretty prints an object to the page framed by pre tags. + * + * @param mixed $object The object to print. + */ + public static function debug($object) { + echo '
    ';
    +        print_r($object);
    +        echo '
    '; } - public static function cleaning_polls($connect, $log_txt) { - $connect->StartTrans(); - $req = 'SELECT * FROM sondage WHERE date_fin < NOW() AND date_fin != 0 LIMIT 20'; - $sql = $connect->Prepare($req); - $cleaning = $connect->Execute($sql); + public static function table($tableName) { + return TABLENAME_PREFIX . $tableName; + } + + public static function markdown($md, $clear) { + preg_match_all('/\[!\[(.*?)\]\((.*?)\)\]\((.*?)\)/', $md, $md_a_img); // Markdown [![alt](src)](href) + preg_match_all('/!\[(.*?)\]\((.*?)\)/', $md, $md_img); // Markdown ![alt](src) + preg_match_all('/\[(.*?)\]\((.*?)\)/', $md, $md_a); // Markdown [text](href) + if (isset($md_a_img[2][0]) && $md_a_img[2][0] != '' && isset($md_a_img[3][0]) && $md_a_img[3][0] != '') { // [![alt](src)](href) + + $text = stripslashes($md_a_img[1][0]); + $html = '' . $text . ''; + + } elseif (isset($md_img[2][0]) && $md_img[2][0] != '') { // ![alt](src) + + $text = stripslashes($md_img[1][0]); + $html = '' . $text . ''; + + } elseif (isset($md_a[2][0]) && $md_a[2][0] != '') { // [text](href) + + $text = stripslashes($md_a[1][0]); + $html = '' . $text . ''; + + } else { // text only + + $text = stripslashes($md); + $html = $text; - while ($dcleaning = $cleaning->FetchNextObject(false)) { - if (self::remove_sondage($connect, $dcleaning->id_sondage)) { - error_log(date('H:i:s d/m/Y:') . ' EXPIRATION: '. $dcleaning->id_sondage."\t".$dcleaning->format."\t".$dcleaning->nom_admin."\t".$dcleaning->mail_admin."\n", 3, $log_txt); - } } - $connect->CompleteTrans(); + + return $clear ? $text : $html; + } + + public static function htmlEscape($html) { + return htmlentities($html, ENT_HTML5 | ENT_QUOTES); + } + + public static function csvEscape($text) { + $escaped = str_replace('"', '""', $text); + $escaped = str_replace("\r\n", '', $escaped); + $escaped = str_replace("\n", '', $escaped); + + return '"' . $escaped . '"'; + } + + public static function cleanFilename($title) { + $cleaned = preg_replace('[^a-zA-Z0-9._-]', '_', $title); + $cleaned = preg_replace(' {2,}', ' ', $cleaned); + + return $cleaned; } } diff --git a/app/inc/constants.php.template b/app/inc/config.template.php similarity index 68% rename from app/inc/constants.php.template rename to app/inc/config.template.php index 82567d6..0c49704 100644 --- a/app/inc/constants.php.template +++ b/app/inc/config.template.php @@ -17,14 +17,8 @@ * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) */ -// FRAMADATE version -const VERSION = 0.8; - -// Server name -const STUDS_URL = ''; - // Application name -const NOMAPPLICATION = ""; +const NOMAPPLICATION = ''; // Database administrator email const ADRESSEMAILADMIN = ''; @@ -32,20 +26,20 @@ const ADRESSEMAILADMIN = ''; // Email for automatic responses (you should set it to "no-reply") const ADRESSEMAILREPONSEAUTO = ''; -// Database name -const BASE = ''; - // Database user -const USERBASE = ""; +const DB_USER= ''; // Database password -const USERPASSWD = ''; +const DB_PASSWORD = ''; // Database server name, leave empty to use a socket -const SERVEURBASE = ''; +const DB_CONNECTION_STRING = 'mysql:host=;dbname=;port='; -// Database type (mysql, postgres…) http://phplens.com/lens/adodb/docs-adodb.htm#drivers -const BASE_TYPE = ''; +// 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 LANGUE = 'fr_FR'; @@ -73,16 +67,11 @@ const URL_PROPRE = false; // Use REMOTE_USER data provided by web server const USE_REMOTE_USER = true; -const COMMENT_EMPTY = 0x0000000001; -const COMMENT_USER_EMPTY = 0x0000000010; -const COMMENT_INSERT_FAILED = 0x0000000100; -const NAME_EMPTY = 0x0000001000; -const NAME_TAKEN = 0x0000010000; -const NO_POLL = 0x0000100000; -const NO_POLL_ID = 0x0001000000; -const INVALID_EMAIL = 0x0010000000; -const TITLE_EMPTY = 0x0100000000; -const INVALID_DATE = 0x1000000000; +// 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 = [ @@ -93,8 +82,8 @@ $config = [ 'show_the_software' => true, // display technical information about the software 'show_cultivate_your_garden' => true, // display "developpement and administration" information /* choix_autre.php / choix_date.php */ - 'default_poll_duration' => 180, // default values for the new poll duration (number of days). + 'default_poll_duration' => 180, // default values for the new poll duration (number of days). /* choix_autre.php */ - 'user_can_add_img_or_link' => true, // user can add link or URL when creating his poll. + 'user_can_add_img_or_link' => true, // user can add link or URL when creating his poll. ]; diff --git a/app/inc/constants.php b/app/inc/constants.php new file mode 100644 index 0000000..f395541 --- /dev/null +++ b/app/inc/constants.php @@ -0,0 +1,42 @@ + $v ) { - if (substr($k,0,2)==substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2)) { + foreach ($ALLOWED_LANGUAGES as $k => $v) { + if (substr($k, 0, 2) == substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2)) { $mlocale = $k; + break; } } } -$locale = $mlocale . '.utf8';//unix format -if (strtoupper(substr(PHP_OS,0,3))=='WIN'){ - putenv("LC_ALL=$mlocale"); //Windows env. needed to switch between languages - switch ($mlocale){ - case 'fr_FR' : $locale = "fra";break; //$locale in windows locale format, needed to use php function that handle text : strftime() - case 'en_GB' : $locale = "english";break; //see http://msdn.microsoft.com/en-us/library/39cwe7zf%28v=vs.90%29.aspx - case 'de_DE' : $locale = "deu";break; - case 'es_ES' : $locale = "esp";break; - } -} - -putenv('LANGUAGE=');//sert à quoi? -setlocale(LC_ALL, $locale); -setlocale(LC_TIME, $locale); -setlocale(LC_MESSAGES, $locale); - +/* Tell PHP which locale to use */ $domain = 'Studs'; -bindtextdomain($domain, 'locale'); +$locale = $mlocale . '.utf8'; //unix format + +if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { + putenv("LC_ALL=$mlocale"); //Windows env. needed to switch between languages + switch ($mlocale) { + case 'fr_FR' : + $locale = "fra"; + break; //$locale in windows locale format, needed to use php function that handle text : strftime() + case 'en_GB' : + $locale = "english"; + break; //see http://msdn.microsoft.com/en-us/library/39cwe7zf%28v=vs.90%29.aspx + case 'de_DE' : + $locale = "deu"; + break; + case 'es_ES' : + $locale = "esp"; + break; + } +} +putenv('LANG=' . $locale); +setlocale(LC_ALL, $locale); +bindtextdomain($domain, ROOT_DIR . 'locale'); bind_textdomain_codeset($domain, 'UTF-8'); textdomain($domain); -/* temp, for compatibility :*/ -$a = explode('_', $mlocale); -$_SESSION['langue'] = strtoupper($a[0]); - -/* */ -$lang = ($_SESSION['langue']!='') ? strtolower($_SESSION['langue']) : 'fr'; - +/* */ +$html_lang = substr($locale, 0, 2); /* Date Format */ -$date_format['txt_full'] = _("%A, den %e. %B %Y"); //summary in choix_date.php and removal date in choix_(date|autre).php -$date_format['txt_short'] = "%A %e %B %Y"; // radio title -$date_format['txt_day'] = "%a %e"; -if (strtoupper(substr(PHP_OS,0,3))=='WIN'){ //%e can't be used on Windows platform, use %#d instead - foreach($date_format as $k => $v) { - $date_format[$k] = preg_replace('#(? $v) { + $date_format[$k] = preg_replace('#(?Connect(SERVEURBASE, USERBASE, USERPASSWD, BASE); +require_once __DIR__ . '/constants.php'; +require_once __DIR__ . '/config.php'; +require_once __DIR__ . '/i18n.php'; + +// Smarty +require_once __DIR__ . '/smarty.php'; + +// Connection to database +$connect = new FramaDB(DB_CONNECTION_STRING, DB_USER, DB_PASSWORD); $err = 0; diff --git a/app/inc/smarty.php b/app/inc/smarty.php new file mode 100644 index 0000000..c9bad47 --- /dev/null +++ b/app/inc/smarty.php @@ -0,0 +1,51 @@ +setTemplateDir(ROOT_DIR . '/tpl/'); +$smarty->setCompileDir(ROOT_DIR . '/tpl_c/'); +$smarty->setCacheDir(ROOT_DIR . '/cache/'); +$smarty->caching = false; + +$smarty->assign('APPLICATION_NAME', NOMAPPLICATION); +$smarty->assign('SERVER_URL', Utils::get_server_name()); +$smarty->assign('SCRIPT_NAME', $_SERVER['SCRIPT_NAME']); +$smarty->assign('TITLE_IMAGE', IMAGE_TITRE); +$smarty->assign('use_nav_js', file_exists($_SERVER['DOCUMENT_ROOT'] . '/nav/nav.js')); +$smarty->assign('html_lang', $html_lang); +$smarty->assign('langs', $ALLOWED_LANGUAGES); +$smarty->assign('date_format', $date_format); + +function smarty_modifier_poll_url($poll_id, $admin = false) { + return Utils::getUrlSondage($poll_id, $admin); +} + +function smarty_modifier_markdown($md, $clear = false) { + return Utils::markdown($md, $clear); +} + +function smarty_modifier_resource($link) { + return Utils::get_server_name() . $link; +} + +function smarty_modifier_html($html) { + return Utils::htmlEscape($html); +} diff --git a/bandeaux.php b/bandeaux.php index efbe726..d9c2bd2 100644 --- a/bandeaux.php +++ b/bandeaux.php @@ -16,7 +16,7 @@ * Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) */ -namespace Framadate; +use Framadate\Utils; include_once __DIR__ . '/app/inc/init.php'; @@ -28,7 +28,7 @@ function bandeau_titre($titre) echo '
    '; if(count($ALLOWED_LANGUAGES)>1){ - echo '
    + echo '
    @@ -43,16 +43,26 @@ function bandeau_titre($titre)
    '; + + global $connect; + $tables = $connect->allTables(); + $diff = array_diff([Utils::table('comment'), Utils::table('poll'), Utils::table('slot'), Utils::table('vote')], $tables); + if (0 != count($diff)) { + echo '
    '. _('Framadate is not properly installed, please check the "INSTALL" to setup the database before continuing.') .'
    '; + bandeau_pied(); + die(); + } + } function liste_lang() { - global $ALLOWED_LANGUAGES; global $lang; + global $ALLOWED_LANGUAGES; global $html_lang; $str = ''; foreach ($ALLOWED_LANGUAGES as $k => $v ) { - if (substr($k,0,2)==$lang) { + if (substr($k,0,2)==$html_lang) { $str .= '' . "\n" ; } else { $str .= '' . "\n" ; diff --git a/choix_autre.php b/choix_autre.php index f0187c5..9c04118 100644 --- a/choix_autre.php +++ b/choix_autre.php @@ -16,10 +16,21 @@ * Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) */ -namespace Framadate; +use Framadate\Services\LogService; +use Framadate\Services\PollService; +use Framadate\Services\MailService; +use Framadate\Services\PurgeService; +use Framadate\Utils; +use Framadate\Choice; -session_start(); -include_once('creation_sondage.php'); +include_once __DIR__ . '/app/inc/init.php'; + +/* Service */ +/*---------*/ +$logService = new LogService(); +$pollService = new PollService($connect, $logService); +$mailService = new MailService($config['use_smtp']); +$purgeService = new PurgeService($connect, $logService); if (file_exists('bandeaux_local.php')) { include_once('bandeaux_local.php'); @@ -27,151 +38,190 @@ if (file_exists('bandeaux_local.php')) { include_once('bandeaux.php'); } -// Step 1/3 : error if $_SESSION from info_sondage are not valid -if (Utils::issetAndNoEmpty('titre', $_SESSION) === false || Utils::issetAndNoEmpty('nom', $_SESSION) === false || (($config['use_smtp']) ? Utils::issetAndNoEmpty('adresse', $_SESSION) === false : false)) { +// Step 1/4 : error if $_SESSION from info_sondage are not valid +if (empty($_SESSION['form']->title) || empty($_SESSION['form']->admin_name) || (($config['use_smtp']) ? empty($_SESSION['form']->admin_mail) : false)) { - Utils::print_header ( _("Error!") ); + Utils::print_header(_("Error!")); bandeau_titre(_("Error!")); echo '
    -

    ' . _("You haven't filled the first section of the poll creation.") . ' !

    -

    ' . _("Back to the homepage of ") . ' ' . NOMAPPLICATION . '

    -
    '."\n"; +

    ' . _('You haven\'t filled the first section of the poll creation.') . ' !

    +

    ' . _('Back to the homepage of') . ' ' . NOMAPPLICATION . '

    +
    ' . "\n"; bandeau_pied(); } else { + $min_time = time() + 86400; + $max_time = time() + (86400 * $config['default_poll_duration']); + // Step 4 : Data prepare before insert in DB - if (isset($_POST["confirmecreation"])) { - //recuperation des données de champs textes - $temp_results = ''; - if (isset($_SESSION['choices'])) { - for ($i = 0; $i < count($_SESSION['choices']); $i++) { - if ($_SESSION['choices'][$i]!="") { - $temp_results.=','.str_replace(",", " ", htmlentities(html_entity_decode($_SESSION['choices'][$i], ENT_QUOTES, 'UTF-8'), ENT_QUOTES, 'UTF-8')); + if (isset($_POST['confirmecreation'])) { + + // Define expiration date + $enddate = filter_input(INPUT_POST, 'enddate', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '#^[0-9]{2}/[0-9]{2}/[0-9]{4}$#']]); + $min_time = time() + (24 * 60 * 60); + $max_time = time() + (86400 * $config['default_poll_duration']); + + if (!empty($enddate)) { + $registredate = explode('/', $enddate); + + if (is_array($registredate) && count($registredate) == 3) { + $time = mktime(0, 0, 0, $registredate[1], $registredate[0], $registredate[2]); + + if ($time < $min_time) { + $_SESSION['form']->end_date = $min_time; + } elseif ($max_time < $time) { + $_SESSION['form']->end_date = $max_time; + } else { + $_SESSION['form']->end_date = $time; } } } - $temp_results=substr($temp_results,1); - $_SESSION["toutchoix"]=$temp_results; + if (empty($_SESSION['form']->end_date)) { + // By default, expiration date is 6 months after last day + $_SESSION['form']->end_date = $max_time; + } + + // format du sondage AUTRE + $_SESSION['form']->format = 'A'; + + // Insert poll in database + $ids = $pollService->createPoll($_SESSION['form']); + $poll_id = $ids[0]; + $admin_poll_id = $ids[1]; - 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)) { - $_SESSION["champdatefin"]=$time; + // 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"; + $message .= stripslashes(html_entity_decode($_SESSION['form']->admin_name, ENT_QUOTES, "UTF-8")) . ' ' . _('hast just created a poll called') . ' : "' . stripslashes(htmlspecialchars_decode($_SESSION['form']->title, ENT_QUOTES)) . "\".\n"; + $message .= _('Thanks for filling the poll at the link above') . " :\n\n%s\n\n" . _('Thanks for your confidence.') . "\n" . NOMAPPLICATION; + + $message_admin = _("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"); + $message_admin .= " :\n\n" . "%s \n\n" . _('Thanks for your confidence.') . "\n" . NOMAPPLICATION; + + $message = sprintf($message, Utils::getUrlSondage($poll_id)); + $message_admin = sprintf($message_admin, Utils::getUrlSondage($admin_poll_id, true)); + + if ($mailService->isValidEmail($_SESSION['form']->admin_mail)) { + $mailService->send($_SESSION['form']->admin_mail, '[' . NOMAPPLICATION . '][' . _('Author\'s message') . '] ' . _('Poll') . ' : ' . stripslashes(htmlspecialchars_decode($_SESSION['form']->title, ENT_QUOTES)), $message_admin); + $mailService->send($_SESSION['form']->admin_mail, '[' . NOMAPPLICATION . '][' . _('For sending to the polled users') . '] ' . _('Poll') . ' : ' . stripslashes(htmlspecialchars_decode($_SESSION['form']->title, ENT_QUOTES)), $message); + } + } + + // Clean Form data in $_SESSION + unset($_SESSION['form']); + + // Delete old polls + $purgeService->purgeOldPolls(); + + // Redirect to poll administration + header('Location:' . Utils::getUrlSondage($admin_poll_id, true)); + exit; + + } // Step 3/4 : Confirm poll creation and choose a removal date + else if (isset($_POST['fin_sondage_autre'])) { + Utils::print_header(_('Removal date and confirmation (3 on 3)')); + bandeau_titre(_('Removal date and confirmation (3 on 3)')); + + + // Store choices in $_SESSION + if (isset($_POST['choices'])) { + $_SESSION['form']->clearChoices(); + foreach ($_POST['choices'] as $c) { + if (!empty($c)) { + $c = strip_tags($c); + $choice = new Choice($c); + $_SESSION['form']->addChoice($choice); } } } - //format du sondage AUTRE - $_SESSION["formatsondage"]="A".$_SESSION["studsplus"]; - - ajouter_sondage(); - - } - - // recuperation des sujets pour sondage AUTRE - if (isset($_POST['choices'])) { - $k = 0; - for ($i = 0; $i < count($_POST['choices']); $i++) { - if (Utils::issetAndNoEmpty($i, $_POST['choices'])) { - $_SESSION['choices'][$k]=htmlentities(html_entity_decode($_POST['choices'][$i], ENT_QUOTES, 'UTF-8'), ENT_QUOTES, 'UTF-8'); - $k++; - } - } - } - - // Step 3/3 : Confirm poll creation and choose a removal date - if (isset($_POST["fin_sondage_autre"])) { - Utils::print_header ( _("Removal date and confirmation (3 on 3)") ); - bandeau_titre(_("Removal date and confirmation (3 on 3)")); - // Expiration date is initialised with config parameter. Value will be modified in step 4 if user has defined an other date - $_SESSION["champdatefin"]= time()+ (86400 * $config['default_poll_duration']); //60 sec * 60 min * 24 hours * config - - $removal_date= utf8_encode(strftime($date_format['txt_full'], ($_SESSION["champdatefin"])));//textual date + $_SESSION['form']->end_date = time() + (86400 * $config['default_poll_duration']); //60 sec * 60 min * 24 hours * config // Summary $summary = '
      '; - for ($i=0;$igetChoices() as $choice) { - preg_match_all('/\[!\[(.*?)\]\((.*?)\)\]\((.*?)\)/',$_SESSION['choices'][$i],$md_a_img); // Markdown [![alt](src)](href) - preg_match_all('/!\[(.*?)\]\((.*?)\)/',$_SESSION['choices'][$i],$md_img); // Markdown ![alt](src) - preg_match_all('/\[(.*?)\]\((.*?)\)/',$_SESSION['choices'][$i],$md_a); // Markdown [text](href) - if (isset($md_a_img[2][0]) && $md_a_img[2][0]!='' && isset($md_a_img[3][0]) && $md_a_img[3][0]!='') { // [![alt](src)](href) + preg_match_all('/\[!\[(.*?)\]\((.*?)\)\]\((.*?)\)/', $choice->getName(), $md_a_img); // Markdown [![alt](src)](href) + preg_match_all('/!\[(.*?)\]\((.*?)\)/', $choice->getName(), $md_img); // Markdown ![alt](src) + preg_match_all('/\[(.*?)\]\((.*?)\)/', $choice->getName(), $md_a); // Markdown [text](href) + if (isset($md_a_img[2][0]) && $md_a_img[2][0] != '' && isset($md_a_img[3][0]) && $md_a_img[3][0] != '') { // [![alt](src)](href) - $li_subject_text = (isset($md_a_img[1][0]) && $md_a_img[1][0]!='') ? stripslashes($md_a_img[1][0]) : _("Choice") .' '.($i+1); - $li_subject_html = ''.$li_subject_text.''; + $li_subject_text = (isset($md_a_img[1][0]) && $md_a_img[1][0] != '') ? stripslashes($md_a_img[1][0]) : _('Choice') . ' ' . ($i + 1); + $li_subject_html = '' . $li_subject_text . ''; - } elseif (isset($md_img[2][0]) && $md_img[2][0]!='') { // ![alt](src) + } elseif (isset($md_img[2][0]) && $md_img[2][0] != '') { // ![alt](src) - $li_subject_text = (isset($md_img[1][0]) && $md_img[1][0]!='') ? stripslashes($md_img[1][0]) : _("Choice") .' '.($i+1); - $li_subject_html = ''.$li_subject_text.''; + $li_subject_text = (isset($md_img[1][0]) && $md_img[1][0] != '') ? stripslashes($md_img[1][0]) : _('Choice') . ' ' . ($i + 1); + $li_subject_html = '' . $li_subject_text . ''; - } elseif (isset($md_a[2][0]) && $md_a[2][0]!='') { // [text](href) + } elseif (isset($md_a[2][0]) && $md_a[2][0] != '') { // [text](href) - $li_subject_text = (isset($md_a[1][0]) && $md_a[1][0]!='') ? stripslashes($md_a[1][0]) : _("Choice") .' '.($i+1); - $li_subject_html = ''.$li_subject_text.''; + $li_subject_text = (isset($md_a[1][0]) && $md_a[1][0] != '') ? stripslashes($md_a[1][0]) : _('Choice') . ' ' . ($i + 1); + $li_subject_html = '' . $li_subject_text . ''; } else { // text only - $li_subject_text = stripslashes($_SESSION['choices'][$i]); + $li_subject_text = stripslashes($choice->getName()); $li_subject_html = $li_subject_text; } - $summary .= '
    1. '.$li_subject_html.'
    2. '."\n"; + $summary .= '
    3. ' . $li_subject_html . '
    4. ' . "\n"; } $summary .= '
    '; + $end_date_str = utf8_encode(strftime('%d/%m/%Y', $max_time)); //textual date + echo '
    -

    '. _("List of your choices").'

    - '. $summary .' +

    ' . _('List of your choices') . '

    + ' . $summary . '
    -

    ' . _("Your poll will be automatically removed after"). " " . $config['default_poll_duration'] . " " . _("days") . ': '.$removal_date.'.
    ' . _("You can fix another removal date for it.") .'

    +

    ' . _('Your poll will be automatically removed after') . ' ' . $config['default_poll_duration'] . ' ' . _('days') . '.
    ' . _('You can set a closer removal date for it.') . '

    - +
    - +
    - '. _("(dd/mm/yyyy)") .' + ' . _('(dd/mm/yyyy)') . '
    -

    '. _("Once you have confirmed the creation of your poll, you will be automatically redirected on the administration page of your poll."). '

    '; - if($config['use_smtp']==true){ +

    ' . _('Once you have confirmed the creation of your poll, you will be automatically redirected on the administration page of your poll.') . '

    '; + if ($config['use_smtp'] == true) { echo ' -

    ' . _("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.") .'

    '; +

    ' . _('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.') . '

    '; } echo '

    - - + +

    - '."\n"; + ' . "\n"; bandeau_pied(); - // Step 2/3 : Select choices of the poll + // Step 2/4 : Select choices of the poll } else { - Utils::print_header( _("Poll subjects (2 on 3)")); - bandeau_titre(_("Poll subjects (2 on 3)")); + Utils::print_header(_('Poll subjects (2 on 3)')); + bandeau_titre(_('Poll subjects (2 on 3)')); echo '
    @@ -179,40 +229,41 @@ if (Utils::issetAndNoEmpty('titre', $_SESSION) === false || Utils::issetAndNoEmp
    '; echo '
    -

    '. _("To make a generic poll, it's better to propose at least two choices between differents subjects.") .'

    -

    '. _("You can add or remove additional choices with the buttons") .' '. _("Remove") .' '. _("Add") .'

    '; - if($config['user_can_add_img_or_link']){ - echo '

    '. _("It's possible to propose links or images by using "). ''. _("the Markdown syntax") .'.

    '; +

    ' . _("To make a generic poll you need to propose at least two choices between differents subjects.") . '

    +

    ' . _("You can add or remove additional choices with the buttons") . ' ' . _("Remove") . ' ' . _("Add") . '

    '; + if ($config['user_can_add_img_or_link']) { + echo '

    ' . _("It's possible to propose links or images by using ") . '' . _("the Markdown syntax") . '.

    '; } - echo '
    '."\n"; + echo '
    ' . "\n"; // Fields choices : 5 by default - $nb_choices = (isset($_SESSION['choices'])) ? max(count($_SESSION['choices']), 5) : 5; + $choices = $_SESSION['form']->getChoices(); + $nb_choices = max(count($choices), 5); for ($i = 0; $i < $nb_choices; $i++) { - $choice_value = (isset($_SESSION['choices'][$i])) ? str_replace("\\","",$_SESSION['choices'][$i]) : ''; + $choice = isset($choices[$i]) ? $choices[$i] : new Choice(); echo '
    - +
    - '; - if($config['user_can_add_img_or_link']){ - echo ' '; - } + '; + if ($config['user_can_add_img_or_link']) { + echo ' '; + } echo '
    -
    '."\n"; + ' . "\n"; } echo '
    - - + +
    - '. _('Back') . ' - + ' . _('Back') . ' +
    @@ -220,32 +271,32 @@ if (Utils::issetAndNoEmpty('titre', $_SESSION) === false || Utils::issetAndNoEmp -
    '."\n"; + ' . "\n"; bandeau_pied(); diff --git a/choix_date.php b/choix_date.php index b8dae26..b94658f 100644 --- a/choix_date.php +++ b/choix_date.php @@ -5,7 +5,7 @@ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt * * Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ - * Authors of Framadate/OpenSondate: Framasoft (https://github.com/framasoft) + * Authors of Framadate/OpenSondate: Framasoft (https://github.com/framasoft https://git.framasoft.org/framasoft/framadate/) * * ============================= * @@ -14,13 +14,25 @@ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.txt * * Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ - * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) + * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft https://git.framasoft.org/framasoft/framadate/) */ -namespace Framadate; +use Framadate\Services\InputService; +use Framadate\Services\LogService; +use Framadate\Services\PollService; +use Framadate\Services\MailService; +use Framadate\Services\PurgeService; +use Framadate\Utils; +use Framadate\Choice; -session_start(); +include_once __DIR__ . '/app/inc/init.php'; -include_once('creation_sondage.php'); +/* Service */ +/*---------*/ +$logService = new LogService(); +$pollService = new PollService($connect, $logService); +$mailService = new MailService($config['use_smtp']); +$purgeService = new PurgeService($connect, $logService); +$inputService = new InputService(); if (is_readable('bandeaux_local.php')) { include_once('bandeaux_local.php'); @@ -28,145 +40,169 @@ if (is_readable('bandeaux_local.php')) { include_once('bandeaux.php'); } -// Step 1/3 : error if $_SESSION from info_sondage are not valid -if (Utils::issetAndNoEmpty('titre', $_SESSION) === false || Utils::issetAndNoEmpty('nom', $_SESSION) === false || (($config['use_smtp']) ? Utils::issetAndNoEmpty('adresse', $_SESSION) === false : false)) { +// Step 1/4 : error if $_SESSION from info_sondage are not valid +if (!isset($_SESSION['form']->title) || !isset($_SESSION['form']->admin_name) || ($config['use_smtp'] && !isset($_SESSION['form']->admin_mail))) { - Utils::print_header ( _("Error!") ); - bandeau_titre(_("Error!")); + Utils::print_header ( _('Error!') ); + bandeau_titre(_('Error!')); echo '
    -

    ' . _("You haven't filled the first section of the poll creation.") . ' !

    -

    ' . _("Back to the homepage of ") . ' ' . '' . NOMAPPLICATION . '.

    +

    ' . _('You haven\'t filled the first section of the poll creation.') . ' !

    +

    ' . _('Back to the homepage of ') . ' ' . '' . NOMAPPLICATION . '.

    '; + bandeau_pied(); } else { + $min_time = time() + 86400; + $max_time = time() + (86400 * $config['default_poll_duration']); + // 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]); - } - } + if (!empty($_POST['confirmation'])) { + + // Define expiration date + $enddate = filter_input(INPUT_POST, 'enddate', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '#^[0-9]{2}/[0-9]{2}/[0-9]{4}$#']]); + + if (!empty($enddate)) { + $registredate = explode('/', $enddate); + + if (is_array($registredate) && count($registredate) == 3) { + $time = mktime(0, 0, 0, $registredate[1], $registredate[0], $registredate[2]); + + if ($time < $min_time) { + $_SESSION['form']->end_date = $min_time; + } elseif ($max_time < $time) { + $_SESSION['form']->end_date = $max_time; } 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 time() + (24*60*60)) { - $_SESSION["champdatefin"]=$time; + $_SESSION['form']->end_date = $time; } } } - ajouter_sondage(); + if (empty($_SESSION['form']->end_date)) { + // By default, expiration date is 6 months after last day + $_SESSION['form']->end_date = $max_time; + } + + // Insert poll in database + $ids = $pollService->createPoll($_SESSION['form']); + $poll_id = $ids[0]; + $admin_poll_id = $ids[1]; + + + // 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"; + $message .= stripslashes(html_entity_decode($_SESSION['form']->admin_name, ENT_QUOTES, 'UTF-8')) . ' ' . _("hast just created a poll called") . ' : "' . stripslashes(htmlspecialchars_decode($_SESSION['form']->title, ENT_QUOTES)) . "\".\n"; + $message .= _('Thanks for filling the poll at the link above') . " :\n\n%s\n\n" . _('Thanks for your confidence.') . "\n" . NOMAPPLICATION; + + $message_admin = _("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"); + $message_admin .= " :\n\n" . "%s \n\n" . _('Thanks for your confidence.') . "\n" . NOMAPPLICATION; + + $message = sprintf($message, Utils::getUrlSondage($poll_id)); + $message_admin = sprintf($message_admin, Utils::getUrlSondage($admin_poll_id, true)); + + if ($mailService->isValidEmail($_SESSION['form']->admin_mail)) { + $mailService->send($_SESSION['form']->admin_mail, '[' . NOMAPPLICATION . '][' . _('Author\'s message') . '] ' . _('Poll') . ' : ' . stripslashes(htmlspecialchars_decode($_SESSION['form']->title, ENT_QUOTES)), $message_admin); + $mailService->send($_SESSION['form']->admin_mail, '[' . NOMAPPLICATION . '][' . _('For sending to the polled users') . '] ' . _('Poll') . ' : ' . stripslashes(htmlspecialchars_decode($_SESSION['form']->title, ENT_QUOTES)), $message); + } + } + + // Clean Form data in $_SESSION + unset($_SESSION['form']); + + // Delete old polls + $purgeService->purgeOldPolls(); + + // Redirect to poll administration + header('Location:' . Utils::getUrlSondage($admin_poll_id, true)); + exit; } else { - if (Utils::issetAndNoEmpty('days')) { - if (!isset($_SESSION["totalchoixjour"])) { - $_SESSION["totalchoixjour"]=array(); - } - $k = 0; - for ($i = 0; $i < count($_POST["days"]); $i++) { - if (isset($_POST["days"][$i]) && $_POST["days"][$i] !='') { - $_SESSION['totalchoixjour'][$k] = mktime(0, 0, 0, substr($_POST["days"][$i],3,2),substr($_POST["days"][$i],0,2),substr($_POST["days"][$i],6,4)); - $l = 0; - for($j = 0; $j < count($_POST['horaires'.$i]); $j++) { - if (isset($_POST['horaires'.$i][$j]) && $_POST['horaires'.$i][$j] != '') { - $_SESSION['horaires'.$k][$l] = $_POST['horaires'.$i][$j]; - $l++; + if (!empty($_POST['days'])) { + + // Clear previous choices + $_SESSION['form']->clearChoices(); + + for ($i = 0; $i < count($_POST['days']); $i++) { + $day = $_POST['days'][$i]; + + if (!empty($day)) { + // Add choice to Form data + $time = mktime(0, 0, 0, substr($_POST["days"][$i],3,2),substr($_POST["days"][$i],0,2),substr($_POST["days"][$i],6,4)); + $choice = new Choice($time); + $_SESSION['form']->addChoice($choice); + + $schedules = $inputService->filterArray($_POST['horaires'.$i], FILTER_DEFAULT); + for($j = 0; $j < count($schedules); $j++) { + if (!empty($schedules[$j])) { + $choice->addSlot(strip_tags($schedules[$j])); } } - $k++; } } } } //le format du sondage est DATE - $_SESSION["formatsondage"] = "D".$_SESSION["studsplus"]; + $_SESSION['form']->format = 'D'; - // Step 3/3 : Confirm poll creation - if (Utils::issetAndNoEmpty('choixheures') && Utils::issetAndNoEmpty('totalchoixjour', $_SESSION)) { + // Step 3/4 : Confirm poll creation + if (!empty($_POST['choixheures']) && !isset($_SESSION['form']->totalchoixjour)) { - Utils::print_header ( _("Removal date and confirmation (3 on 3)") ); - bandeau_titre(_("Removal date and confirmation (3 on 3)")); + Utils::print_header ( _('Removal date and confirmation (3 on 3)') ); + bandeau_titre(_('Removal date and confirmation (3 on 3)')); - $temp_array = array_unique($_SESSION["totalchoixjour"]); - sort($temp_array); - $removal_date=utf8_encode(strftime($date_format['txt_full'], end($temp_array)+ (86400 * $config['default_poll_duration']))); + $_SESSION['form']->sortChoices(); + $last_date = $_SESSION['form']->lastChoice()->getName(); + $removal_date = $last_date + (86400 * $config['default_poll_duration']); - // Sumary + // Summary $summary = ''; + $end_date_str = utf8_encode(strftime('%d/%m/%Y', $max_time)); //textual date + echo '
    -

    '. _("Confirm the creation of your poll") .'

    +

    '. _('Confirm the creation of your poll') .'

    -

    '. _("List of your choices").'

    +

    '. _('List of your choices').'

    '. $summary .'
    -

    ' . _("Your poll will be automatically removed "). $config['default_poll_duration'] . ' ' . _("days") ._(" after the last date of your poll:") . ' '.$removal_date.'.
    ' . _("You can fix another removal date for it.") .'

    +

    ' . _('Your poll will be automatically removed '). $config['default_poll_duration'] . ' ' . _('days') . ' ' ._('after the last date of your poll') . '.
    ' . _('You can set a closer removal date for it.') .'

    - +
    - +
    '. _("(dd/mm/yyyy)") .'
    -

    '. _("Once you have confirmed the creation of your poll, you will be automatically redirected on the administration page of your poll."). '

    '; - if($config['use_smtp']==true){ - echo ' -

    ' . _("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.") .'

    '; +

    '. _('Once you have confirmed the creation of your poll, you will be automatically redirected on the administration page of your poll.'). '

    '; + if($config['use_smtp'] == true) { + echo '

    ' . _('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.') .'

    '; } echo '
    @@ -180,45 +216,45 @@ if (Utils::issetAndNoEmpty('titre', $_SESSION) === false || Utils::issetAndNoEmp 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)")); + Utils::print_header ( _('Poll dates (2 on 3)') ); + bandeau_titre(_('Poll dates (2 on 3)')); echo '
    -

    '. _("Choose the dates of your poll") .'

    +

    '. _('Choose the dates of your poll') .'

    -

    '. _("To schedule an event, it's better to propose at least two choices (two hours for one day or two days).").'

    -

    '. _("You can add or remove additionnal days and hours with the buttons") .' '. _("Remove") .' '. _("Add") .'

    -

    '. _("For each selected day, you can choose, or not, meeting hours (e.g.: \"8h\", \"8:30\", \"8h-10h\", \"evening\", etc.)").'

    +

    '. _('To schedule an event you need to propose at least two choices (two hours for one day or two days).').'

    +

    '. _('You can add or remove additionnal days and hours with the buttons') .' '. _('Remove') .' '. _('Add') .'

    +

    '. _('For each selected day, you can choose, or not, meeting hours (e.g.: "8h", "8:30", "8h-10h", "evening", etc.)').'

    '; // Fields days : 3 by default - $nb_days = (isset($_SESSION["totalchoixjour"])) ? count($_SESSION["totalchoixjour"]) : 3; + $nb_days = (isset($_SESSION['totalchoixjour'])) ? count($_SESSION['totalchoixjour']) : 3; for ($i=0;$i<$nb_days;$i++) { - $day_value = isset($_SESSION["totalchoixjour"][$i]) ? strftime( "%d/%m/%Y", $_SESSION["totalchoixjour"][$i]) : ''; + $day_value = isset($_SESSION['totalchoixjour'][$i]) ? strftime('%d/%m/%Y', $_SESSION['totalchoixjour'][$i]) : ''; echo '
    - +
    - +
    - '. _("(dd/mm/yyyy)") .' + '. _('(dd/mm/yyyy)') .'
    '."\n"; // Fields hours : 3 by default - for ($j=0;$j - - + +
    '."\n"; } echo ' @@ -231,24 +267,24 @@ if (Utils::issetAndNoEmpty('titre', $_SESSION) === false || Utils::issetAndNoEmp } echo '
    - +
    - - + +
    '. _('Back') . ' - +
    diff --git a/composer.json b/composer.json index e4426a0..df41b50 100644 --- a/composer.json +++ b/composer.json @@ -4,16 +4,18 @@ "keywords": [ "poll" ], - "version": "0.8.0", + "version": "0.9.0", "license": "CeCILL-B", - + "type": "project", - + "require": { - "adodb/adodb-php": "5.19" + "smarty/smarty": "3.1.21" }, "autoload": { - "psr-0": {"Framadate": "app/classes/"} + "psr-4": { + "Framadate\\": "app/classes/Framadate/" + } } } diff --git a/composer.lock b/composer.lock index 90f3eba..c4f9e50 100644 --- a/composer.lock +++ b/composer.lock @@ -4,70 +4,70 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "3cdb051814926a50182b00bbf5297ed2", + "hash": "4bf9a3fa30eb400c9ed140dd2d6fa266", "packages": [ { - "name": "adodb/adodb-php", - "version": "v5.19", + "name": "smarty/smarty", + "version": "v3.1.21", "source": { "type": "git", - "url": "https://github.com/ADOdb/ADOdb.git", - "reference": "773bb9b7ccd81b403bf75f7ef476c3f2d7ee04de" + "url": "https://github.com/smarty-php/smarty.git", + "reference": "1f878e6d746ecc8ec8d00d9c75044cf7d23ad94a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ADOdb/ADOdb/zipball/773bb9b7ccd81b403bf75f7ef476c3f2d7ee04de", - "reference": "773bb9b7ccd81b403bf75f7ef476c3f2d7ee04de", + "url": "https://api.github.com/repos/smarty-php/smarty/zipball/1f878e6d746ecc8ec8d00d9c75044cf7d23ad94a", + "reference": "1f878e6d746ecc8ec8d00d9c75044cf7d23ad94a", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": ">=5.2" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, "autoload": { - "files": [ - "adodb.inc.php" + "classmap": [ + "libs/Smarty.class.php", + "libs/SmartyBC.class.php", + "libs/sysplugins/smarty_security.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-2.1", - " BSD-2-Clause" + "LGPL-3.0" ], "authors": [ { - "name": "John Lim", - "email": "jlim@natsoft.com", - "role": "Author" + "name": "Monte Ohrt", + "email": "monte@ohrt.com" }, { - "name": "Damien Regad", - "role": "Current maintainer" + "name": "Uwe Tews", + "email": "uwe.tews@googlemail.com" + }, + { + "name": "Rodney Rehm", + "email": "rodney.rehm@medialize.de" } ], - "description": "ADOdb is a PHP database abstraction layer library", - "homepage": "http://adodb.sourceforge.net/", + "description": "Smarty - the compiling PHP template engine", + "homepage": "http://www.smarty.net", "keywords": [ - "database" + "templating" ], - "time": "2014-04-23 14:37:03" + "time": "2014-10-31 04:22:20" } ], - "packages-dev": [ - - ], - "aliases": [ - - ], + "packages-dev": [], + "aliases": [], "minimum-stability": "stable", - "stability-flags": [ - - ], + "stability-flags": [], "prefer-stable": false, - "platform": [ - - ], - "platform-dev": [ - - ] + "prefer-lowest": false, + "platform": [], + "platform-dev": [] } diff --git a/css/frama.css b/css/frama.css index c683d2c..2a36d07 100644 --- a/css/frama.css +++ b/css/frama.css @@ -47,7 +47,7 @@ a.text-info:focus { .text-warning, .text-warning a, a.text-warning { - color: #8A6E3B; + color: #C05827; } .text-warning a:hover, .text-warning a:focus, @@ -85,7 +85,7 @@ a.bg-primary:hover { background-color: #FCF3E3; } .bg-danger,a.bg-danger:hover { - background-color: #F2E7E5; + background-color: #FDE0DC; } /* Alerts */ @@ -210,6 +210,7 @@ fieldset[disabled] .btn-primary.active { color: #fff; background-color: #849551; border-color: #748544; + text-shadow: 0px 0px 3px rgba(0, 0, 0, 0.7); } .btn-success:hover, .btn-success:focus, @@ -434,3 +435,8 @@ fieldset[disabled] .btn-link:focus { .modal-header h4,.modal-header h5,.modal-header h6 { font-size: 24px; } + +/* Admin > Polls */ +.table-polls .cell-format { + vertical-align: middle +} \ No newline at end of file diff --git a/css/print.css b/css/print.css index 04b33c8..5f677ec 100644 --- a/css/print.css +++ b/css/print.css @@ -4,16 +4,12 @@ body { background:none; } -.jumbotron { - page-break-after:always; +table { + page-break-after:always} } table { - page-break-after:always; -} - -table { - page-break-inside:auto; + page-break-inside:auto } tr { @@ -29,26 +25,6 @@ tfoot { display:table-footer-group; } -#tableContainer { - overflow-x:visible !important; -} - -#vote-form, .scroll-buttons, form .alert.alert-info { - display:none; -} - -table.results td { - border:2px solid #333; -} - -table.results tr td:last-child { - display:none; -} - -.container { - width:auto; -} - @page { size:landscape; } diff --git a/css/style.css b/css/style.css index 08cc585..43b400d 100644 --- a/css/style.css +++ b/css/style.css @@ -120,7 +120,9 @@ caption { #title-form h3 .btn-edit, #email-form .btn-edit, #description-form .btn-edit, -#poll-rules-form .btn-edit { +#poll-rules-form .btn-edit, +#expiration-form .btn-edit, +#name-form .btn-edit { position:absolute; left:-2000px; } @@ -132,7 +134,11 @@ caption { #description-form .btn-edit:focus, #description-form:hover .btn-edit, #poll-rules-form .btn-edit:focus, -#poll-rules-form:hover .btn-edit { +#poll-rules-form:hover .btn-edit, +#expiration-form .btn-edit:focus, +#expiration-form:hover .btn-edit, +#name-form .btn-edit:focus, +#name-form:hover .btn-edit { position:relative !important; left:0; padding: 0px 10px; @@ -245,18 +251,13 @@ table.results .btn-link.btn-sm { #vote-form td { border-top:2px solid white; - vertical-align:top; } .yes input, .ifneedbe input,.no input { - position: absolute; - width: 1px; - height: 1px; - padding: 0px; - margin: -1px; - overflow: hidden; - clip: rect(0px, 0px, 0px, 0px); - border: 0px none; + position:absolute; + left:0; + margin-left:-15px; + margin-top:0; } .choice input:focus + label { @@ -274,47 +275,45 @@ table.results .btn-link.btn-sm { .yes .btn, .ifneedbe .btn, .no .btn { width:32px; + color:#555; } -.yes .btn,.yes .btn:hover { +.yes .btn { border-bottom-right-radius:0px !important; border-bottom-left-radius:0px !important; margin-bottom:-1px !important; margin-top:4px !important; - color:#677835; } -.ifneedbe .btn,.ifneedbe .btn:hover { +.ifneedbe .btn { border-radius:0px; - color:#C48A1B; } -.no .btn,.no .btn:hover{ +.no .btn{ border-top-right-radius:0px !important; border-top-left-radius:0px !important; margin-bottom:4px !important; margin-top:-1px !important; - color:#AD220F; } .yes input[type="radio"]:checked + label { /* =.btn-success.active */ - color: #FFF; - background-color: #7D8C3F; - border-color: #7D8C3F; + color: #fff; + background-color: #768745; + border-color: #67753C; box-shadow: 0px 3px 5px rgba(0, 0, 0, 0.125) inset; } .ifneedbe input[type="radio"]:checked + label { /* =.btn-warning.active */ - color: #FFF; - background-color: #C48A1B; - border-color: #C48A1B; + color: #fff; + background-color: #CF9800; + border-color: #BD8A00; box-shadow: 0px 3px 5px rgba(0, 0, 0, 0.125) inset; } .no input[type="radio"]:checked + label { /* =.btn-danger.active */ - color: #FFF; - background-color: #B82E12; - border-color: #B82E12; + color: #fff; + background-color: #BF2511; + border-color: #AD220F; box-shadow: 0px 3px 5px rgba(0, 0, 0, 0.125) inset; } diff --git a/exportcsv.php b/exportcsv.php index fd868bf..509f6f6 100644 --- a/exportcsv.php +++ b/exportcsv.php @@ -16,89 +16,103 @@ * Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) */ -namespace Framadate; +use Framadate\Services\LogService; +use Framadate\Services\PollService; +use Framadate\Services\InputService; +use Framadate\Services\MailService; +use Framadate\Message; +use Framadate\Utils; include_once __DIR__ . '/app/inc/init.php'; -if(!isset($_GET['numsondage']) || ! preg_match(";^[\w\d]{16}$;i", $_GET['numsondage'])) { - header('Location: studs.php'); +ob_start(); + +/* Variables */ +/* --------- */ + +$poll_id = null; +$poll = null; + +/* Services */ +/*----------*/ + +$logService = new LogService(); +$pollService = new PollService($connect, $logService); + +/* PAGE */ +/* ---- */ + +if (!empty($_GET['poll'])) { + $poll_id = filter_input(INPUT_GET, 'poll', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^[a-z0-9]+$/']]); + $poll = $pollService->findById($poll_id); } -$sql = 'SELECT * FROM user_studs WHERE id_sondage='.$connect->Param('numsondage').' ORDER BY id_users'; -$sql = $connect->Prepare($sql); -$user_studs = $connect->Execute($sql, array($_GET['numsondage'])); +if (!$poll) { + $smarty->assign('error', _('This poll doesn\'t exist !')); + $smarty->display('error.tpl'); + exit; +} -$dsondage = Utils::get_sondage_from_id($_GET['numsondage']); -$nbcolonnes=substr_count($dsondage->sujet,',')+1; -$toutsujet=explode(",",$dsondage->sujet); +$slots = $pollService->allSlotsByPollId($poll_id); +$votes = $pollService->allVotesByPollId($poll_id); -//affichage des sujets du sondage -$input =","; -foreach ($toutsujet as $value) { - if ($dsondage->format=="D"||$dsondage->format=="D+") { - if (strpos($dsondage->sujet,'@') !== false) { - $days=explode("@",$value); - $input.= '"'.date("j/n/Y",$days[0]).'",'; - } else { - $input.= '"'.date("j/n/Y",$values).'",'; - } - } else { +// CSV header +if ($poll->format === 'D') { + $titles_line = ','; + $moments_line = ','; + foreach ($slots as $slot) { + $title = Utils::csvEscape(strftime($date_format['txt_date'], $slot->title)); + $moments = explode(',', $slot->moments); - preg_match_all('/\[!\[(.*?)\]\((.*?)\)\]\((.*?)\)/',$value,$md_a_img); // Markdown [![alt](src)](href) - preg_match_all('/!\[(.*?)\]\((.*?)\)/',$value,$md_img); // Markdown ![alt](src) - preg_match_all('/\[(.*?)\]\((.*?)\)/',$value,$md_a); // Markdown [text](href) - if (isset($md_a_img[2][0]) && $md_a_img[2][0]!='' && isset($md_a_img[3][0]) && $md_a_img[3][0]!='') { // [![alt](src)](href) - $subject_text = (isset($md_a_img[1][0]) && $md_a_img[1][0]!='') ? stripslashes($md_a_img[1][0]) : _("Choice") .' '.($i+1); - } elseif (isset($md_img[2][0]) && $md_img[2][0]!='') { // ![alt](src) - $subject_text = (isset($md_img[1][0]) && $md_img[1][0]!='') ? stripslashes($md_img[1][0]) : _("Choice") .' '.($i+1); - } elseif (isset($md_a[2][0]) && $md_a[2][0]!='') { // [text](href) - $subject_text = (isset($md_a[1][0]) && $md_a[1][0]!='') ? stripslashes($md_a[1][0]) : _("Choice") .' '.($i+1); - } else { // text only - $subject_text = stripslashes($value); - } - $input.= '"'.html_entity_decode($subject_text).'",'; + $titles_line .= str_repeat($title . ',', count($moments)); + $moments_line .= implode(',', array_map('\Framadate\Utils::csvEscape', $moments)) . ','; } -} - -$input.="\r\n"; - -if (strpos($dsondage->sujet,'@') !== false) { - $input.=","; - foreach ($toutsujet as $value) { - $heures=explode("@",$value); - $input.= '"'.$heures[1].'",'; + echo $titles_line . "\r\n"; + echo $moments_line . "\r\n"; +} else { + echo ','; + foreach ($slots as $slot) { + echo Utils::markdown($slot->title, true) . ','; } - - $input.="\r\n"; + echo "\r\n"; } +// END - CSV header -while ( $data=$user_studs->FetchNextObject(false)) { - // Le nom de l'utilisateur - $nombase=html_entity_decode(str_replace("°","'",$data->nom)); - $input.= '"'.$nombase.'",'; - //affichage des resultats - $ensemblereponses=$data->reponses; - for ($k=0;$k<$nbcolonnes;$k++) { - $car=substr($ensemblereponses,$k,1); - switch ($car) { - case "1": $input .= '"'._('Yes').'",'; $somme[$k]++; break; - case "2": $input .= '"'._('Ifneedbe').'",'; break; - default: $input .= '"'._('No').'",'; break; +// Vote lines +foreach ($votes as $vote) { + echo Utils::csvEscape($vote->name) . ','; + $choices = str_split($vote->choices); + foreach ($choices as $choice) { + switch ($choice) { + case 0: + $text = _('No'); + break; + case 1: + $text = _('Ifneedbe'); + break; + case 2: + $text = _('Yes'); + break; + default: + $text = 'unkown'; } + echo Utils::csvEscape($text); + echo ','; } - - $input.="\r\n"; + echo "\r\n"; } +// END - Vote lines -$filesize = strlen( $input ); -$filename=$_GET["numsondage"].".csv"; +// HTTP headers +$content = ob_get_clean(); +$filesize = strlen($content); +$filename = Utils::cleanFilename($poll->title) . '.csv'; -header( 'Content-Type: text/csv; charset=utf-8' ); -header( 'Content-Length: '.$filesize ); -header( 'Content-Disposition: attachment; filename="'.$filename.'"' ); -header( 'Cache-Control: max-age=10' ); +header('Content-Type: text/csv; charset=utf-8'); +header('Content-Length: ' . $filesize); +header('Content-Disposition: attachment; filename="' . $filename . '"'); +header('Cache-Control: max-age=10'); +// END - HTTP headers -echo str_replace('"','""',$input); - -die(); +echo $content; diff --git a/index.php b/index.php index 6fed009..4e46fbe 100644 --- a/index.php +++ b/index.php @@ -18,8 +18,6 @@ */ namespace Framadate; -use Framadate\Utils; - include_once __DIR__ . '/app/inc/init.php'; if (is_readable('bandeaux_local.php')) { @@ -28,12 +26,9 @@ if (is_readable('bandeaux_local.php')) { include_once('bandeaux.php'); } -session_start(); - // affichage de la page Utils::print_header( _("Home") ); bandeau_titre(_("Make your polls")); - echo '
    diff --git a/infos_sondage.php b/infos_sondage.php index 59d5848..d53140d 100644 --- a/infos_sondage.php +++ b/infos_sondage.php @@ -18,127 +18,112 @@ */ namespace Framadate; -session_start(); include_once __DIR__ . '/app/inc/init.php'; +function fromPostOrEmpty($postKey) { + return isset($_POST[$postKey]) ? Utils::htmlEscape($_POST[$postKey]) : ''; +} + +if (!isset($_SESSION['form'])) { + $_SESSION['form'] = new Form(); +} + if (file_exists('bandeaux_local.php')) { include_once('bandeaux_local.php'); } else { include_once('bandeaux.php'); } -// Type de sondage :

    - +
    diff --git a/install/install.mysql.sql b/install/install.mysql.sql index c873a75..aa0354c 100644 --- a/install/install.mysql.sql +++ b/install/install.mysql.sql @@ -1,100 +1,112 @@ --- Base de données: `opensondage` +-- -------------------------------------------------------- + -- +-- Table structure `poll` +-- + +CREATE TABLE IF NOT EXISTS `poll` ( + `id` CHAR(16) NOT NULL, + `admin_id` CHAR(24) NOT NULL, + `title` TEXT NOT NULL, + `description` 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', + `active` TINYINT(1) DEFAULT '1', + PRIMARY KEY (`id`) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; -- -------------------------------------------------------- -- --- Structure de la table `comments` +-- Table structure `slot` -- -CREATE TABLE IF NOT EXISTS `comments` ( - `id_comment` int(11) unsigned NOT NULL AUTO_INCREMENT, - `id_sondage` char(16) NOT NULL, - `comment` text NOT NULL, - `usercomment` text, - PRIMARY KEY (`id_comment`), - KEY `id_sondage` (`id_sondage`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE IF NOT EXISTS `slot` ( + `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `poll_id` CHAR(16) NOT NULL, + `title` TEXT, + `moments` TEXT, + PRIMARY KEY (`id`), + KEY `poll_id` (`poll_id`) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; -- -------------------------------------------------------- -- --- Structure de la table `sondage` +-- Table structure `comment` -- -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', - `statut` int(11) NOT NULL DEFAULT '1' COMMENT '1 = actif ; 0 = inactif ; ', - UNIQUE KEY `id_sondage` (`id_sondage`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE IF NOT EXISTS `comment` ( + `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `poll_id` CHAR(16) NOT NULL, + `name` TEXT, + `comment` TEXT NOT NULL, + PRIMARY KEY (`id`), + KEY `poll_id` (`poll_id`) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; -- -------------------------------------------------------- -- --- Structure de la table `sujet_studs` +-- Table structure `vote` -- -CREATE TABLE IF NOT EXISTS `sujet_studs` ( - `id_sondage` char(16) NOT NULL, - `sujet` text, - KEY `id_sondage` (`id_sondage`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE IF NOT EXISTS `vote` ( + `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `poll_id` CHAR(16) NOT NULL, + `name` VARCHAR(64) NOT NULL, + `choices` TEXT NOT NULL, + PRIMARY KEY (`id`), + KEY `poll_id` (`poll_id`) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; --- -------------------------------------------------------- -- --- Structure de la table `user_studs` +-- Data for Name: poll; Type: TABLE DATA; -- -CREATE TABLE IF NOT EXISTS `user_studs` ( - `id_users` int(11) unsigned NOT NULL AUTO_INCREMENT, - `nom` varchar(64) NOT NULL, - `id_sondage` char(16) NOT NULL, - `reponses` text NOT NULL, - PRIMARY KEY (`id_users`), - KEY `id_sondage` (`id_sondage`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=160284 ; - - - -INSERT INTO `sondage` -(`id_sondage`, `commentaires`, `mail_admin`, `nom_admin`, - `titre`, `id_sondage_admin`, - `date_fin`, `format`) +INSERT INTO `poll` +(`id`, `description`, `admin_mail`, `admin_name`, `title`, `admin_id`, `end_date`, `format`) VALUES -('aqg259dth55iuhwm','Repas de Noel du service','Stephanie@retaillard.com','Stephanie', - 'Repas de Noel','aqg259dth55iuhwmy9d8jlwk', - FROM_UNIXTIME('1627100361'),'D+'); + ('aqg259dth55iuhwm', 'Repas de Noel du service', 'Stephanie@retaillard.com', 'Stephanie', 'Repas de Noel', + 'aqg259dth55iuhwmy9d8jlwk', FROM_UNIXTIME('1627100361'), 'D'); -- --- Data for Name: sujet_studs; Type: TABLE DATA; +-- Data for Name: slot; Type: TABLE DATA; -- -INSERT INTO `sujet_studs` (`id_sondage`, `sujet`) VALUES -('aqg259dth55iuhwm','1225839600@12h,1225839600@19h,1226012400@12h,1226012400@19h,1226876400@12h,1226876400@19h,1227049200@12h,1227049200@19h,1227826800@12h,1227826800@19h'); +INSERT INTO `slot` (`poll_id`, `title`, `moments`) VALUES + ('aqg259dth55iuhwm', '1225839600', '12h,19h'), + ('aqg259dth55iuhwm', '1226012400', '12h,19h'), + ('aqg259dth55iuhwm', '1226876400', '12h,19h'), + ('aqg259dth55iuhwm', '1227826800', '12h,19h'); -- --- Data for Name: user_studs; Type: TABLE DATA; +-- Data for Name: vote; Type: TABLE DATA; -- -INSERT INTO `user_studs` (`nom`, `id_sondage`, `reponses`, `id_users`) VALUES -('marcel','aqg259dth55iuhwm','0110111101','933'), -('paul','aqg259dth55iuhwm','1011010111','935'), -('sophie','aqg259dth55iuhwm','1110110000','945'), -('barack','aqg259dth55iuhwm','0110000','948'), -('takashi','aqg259dth55iuhwm','0000110100','951'), -('albert','aqg259dth55iuhwm','1010110','975'), -('alfred','aqg259dth55iuhwm','0110010','1135'), -('marcs','aqg259dth55iuhwm','0100001010','1143'), -('laure','aqg259dth55iuhwm','0011000','1347'), -('benda','aqg259dth55iuhwm','1101101100','1667'), -('Albert','aqg259dth55iuhwm','1111110011','1668'); +INSERT INTO `vote` (`name`, `poll_id`, `choices`) VALUES + ('marcel', 'aqg259dth55iuhwm', '02202222'), + ('paul', 'aqg259dth55iuhwm', '20220202'), + ('sophie', 'aqg259dth55iuhwm', '22202200'), + ('barack', 'aqg259dth55iuhwm', '02200000'), + ('takashi', 'aqg259dth55iuhwm', '00002202'), + ('albert', 'aqg259dth55iuhwm', '20202200'), + ('alfred', 'aqg259dth55iuhwm', '02200200'), + ('marcs', 'aqg259dth55iuhwm', '02000020'), + ('laure', 'aqg259dth55iuhwm', '00220000'), + ('benda', 'aqg259dth55iuhwm', '22022022'), + ('albert', 'aqg259dth55iuhwm', '22222200'); diff --git a/js/core.js b/js/core.js index 329885f..19cd395 100644 --- a/js/core.js +++ b/js/core.js @@ -1,6 +1,6 @@ $(document).ready(function() { var lang = $('html').attr('lang'); - + // Datepicker var framadatepicker = function() { $('.input-group.date').datepicker({ @@ -32,25 +32,13 @@ $(document).ready(function() { var datepickerfocus = false; // a11y : datepicker not display on focus until there is one click on the button - var lastDate = new Date(); - + $(document).on('click','.input-group.date .input-group-addon', function() { datepickerfocus = true; // Re-init datepicker config before displaying $(this).parent().datepicker(framadatepicker()); $(this).parent().datepicker('show'); - - // Trick to keep the last datepicker view - if ($(this).parent().find('input').val() == '') { - $('.input-group.date input').each(function(){ - if($(this).val()!='') { - lastDate = $(this).val(); - } - }); - $(this).parent().datepicker('setDate', lastDate); - $(this).parent().datepicker('setDate', ''); - } - + // Trick to refresh calendar $('.datepicker-days .prev').trigger('click'); $('.datepicker-days .next').trigger('click'); @@ -60,9 +48,8 @@ $(document).ready(function() { $(document).on('focus','.input-group.date input', function() { if(datepickerfocus) { - // unfocus and click instead (because we are not in a11y mode anymore) - $(this).blur(); - $(this).parent().find('.input-group-addon').trigger('click'); + $(this).parent('.input-group.date').datepicker(framadatepicker()); + $(this).parent('.input-group.date').datepicker('show'); } }); /** @@ -201,17 +188,25 @@ $(document).ready(function() { }); }); - // 1 day filled and you can submit + // 1 day and 2 hours or 2 days and you can submit function SubmitDaysAvalaible() { var nb_filled_days = 0; + var nb_filled_hours = 0; $('#selected-days fieldset legend input').each(function() { if($(this).val()!='') { nb_filled_days++; } }); + $('#selected-days .hours').each(function() { + if($(this).val()!='') { + nb_filled_hours++; + } + }); - if (nb_filled_days>0) { + if (nb_filled_days>1) { + $('button[name="choixheures"]').removeClass('disabled'); + } else if (nb_filled_hours>1 && nb_filled_days==1) { $('button[name="choixheures"]').removeClass('disabled'); } else { $('button[name="choixheures"]').addClass('disabled'); @@ -223,8 +218,8 @@ $(document).ready(function() { }); SubmitDaysAvalaible(); - // 1 days and you can remove a day or copy hours - if($('#selected-days fieldset').length>0) { + // 2 days and you can remove a day or copy hours + if($('#selected-days fieldset').length>1) { $('#remove-a-day, #copyhours').removeClass('disabled'); } @@ -261,13 +256,13 @@ $(document).ready(function() { $('.choice-field:last').remove(); var nb_choices = $('.choice-field').length; $('#choice'+(nb_choices-1)).focus(); - if (nb_choices == 1) { + if (nb_choices == 2) { $('#remove-a-choice').addClass('disabled'); }; SubmitChoicesAvalaible(); }); - // 1 choice filled and you can submit + // 2 choices filled and you can submit function SubmitChoicesAvalaible() { var nb_filled_choices = 0; $('.choice-field input').each(function() { @@ -275,7 +270,7 @@ $(document).ready(function() { nb_filled_choices++; } }); - if(nb_filled_choices>0) { + if(nb_filled_choices>1) { $('button[name="fin_sondage_autre"]').removeClass('disabled'); } else { $('button[name="fin_sondage_autre"]').addClass('disabled'); @@ -327,6 +322,20 @@ $(document).ready(function() { return false; }); + $('#name-form .btn-edit').on('click', function() { + $('#name-form p').hide(); + $('.js-name').removeClass("hidden"); + $('.js-name input').focus(); + return false; + }); + + $('#name-form .btn-cancel').on('click', function() { + $('#name-form p').show(); + $('#name-form .js-name').addClass("hidden"); + $('#name-form .btn-edit').focus(); + return false; + }); + $('#email-form .btn-edit').on('click', function() { $('#email-form p').hide(); $('#email-form .js-email').removeClass("hidden"); @@ -369,6 +378,20 @@ $(document).ready(function() { return false; }); + $('#expiration-form .btn-edit').on('click', function() { + $('#expiration-form p').hide(); + $('.js-expiration').removeClass("hidden"); + $('.js-expiration input').focus(); + return false; + }); + + $('#expiration-form .btn-cancel').on('click', function() { + $('#expiration-form p').show(); + $('#expiration-form .js-expiration').addClass("hidden"); + $('#expiration-form .btn-edit').focus(); + return false; + }); + // Horizontal scroll buttons if($('.results').width() > $('.container').width()) { $('.scroll-buttons').removeClass('hidden'); diff --git a/locale/de_DE/LC_MESSAGES/Studs.mo b/locale/de_DE/LC_MESSAGES/Studs.mo index 3b051fc..ac83bd0 100644 Binary files a/locale/de_DE/LC_MESSAGES/Studs.mo and b/locale/de_DE/LC_MESSAGES/Studs.mo differ diff --git a/locale/de_DE/LC_MESSAGES/Studs.po b/locale/de_DE/LC_MESSAGES/Studs.po index 58ceb65..9a89c9a 100644 --- a/locale/de_DE/LC_MESSAGES/Studs.po +++ b/locale/de_DE/LC_MESSAGES/Studs.po @@ -1,677 +1,715 @@ -msgid "" -msgstr "" -"Project-Id-Version: Framadate 0.8\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-10-23 20:52+0100\n" -"PO-Revision-Date: 2014-10-23 20:52+0100\n" -"Last-Translator: Jonathan Brielmaier\n" -"Language-Team: Jonathan Brielmaier\n" -"Language: German\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Poedit-Language: German\n" -"X-Poedit-Country: GERMANY\n" -"X-Poedit-SourceCharset: utf-8\n" -"X-Poedit-KeywordsList: _\n" -"X-Poedit-Basepath: /var/www/studs\n" -"X-Poedit-SearchPath-0: .\n" - -########### Generic ########### -msgid "Make your polls" -msgstr "Eigene Umfragen erstellen" - -msgid "Home" -msgstr "Home" - -msgid "Poll" -msgstr "Umfrage" - -msgid "Save" -msgstr "Speichern" - -msgid "Cancel" -msgstr "Abbrechen" - -msgid "Add" -msgstr "Hinzufügen" - -msgid "Remove" -msgstr "Entfernen" - -msgid "Validate" -msgstr "Bestätigen" - -msgid "Edit" -msgstr "Bearbeiten" - -msgid "Next" -msgstr "Weiter" - -msgid "Back" -msgstr "Zurück" - -msgid "Close" -msgstr "Schließen" - -msgid "Your name" -msgstr "Ihr Name" - -msgid "Your email address" -msgstr "Ihre E-Mail Adresse" - -msgid "(in the format name@mail.com)" -msgstr "(Format: name@mail.com)" - -msgid "Description" -msgstr "Beschreibung" - -msgid "Back to the homepage of " -msgstr "Zurück zur Homepage von " - -msgid "Error!" -msgstr "Fehler!" - -msgid "(dd/mm/yyyy)" -msgstr "(tt/mm/jjjj)" - -msgid "dd/mm/yyyy" -msgstr "tt/mm/jjjj" - -msgid "%A, den %e. %B %Y" -msgstr "%A %e %B %Y" - -msgid "Expiration's date" -msgstr "Verfallsdatum" - -########### Language selector ########### -msgid "Change the language" -msgstr "Sprache wechseln" - -msgid "Select the language" -msgstr "Sprache wählen" - -############ Homepage ############ -msgid "Schedule an event" -msgstr "Termin finden" - -msgid "Make a classic poll" -msgstr "Klassische Umfrage" - -# 1st section -msgid "What is that?" -msgstr "Was ist das?" - -msgid "Framadate is an online service for planning an appointment or make a decision quickly and easily. No registration is required." -msgstr "Framadate ist ein Online-Dienst, das Ihnen hilft, Termine zu finden oder Entscheidungen schnell und einfach zu treffen. Keine Registrierung ist erforderlich. " - -msgid "Here is how it works:" -msgstr "So geht es:" - -msgid "Make a poll" -msgstr "Umfrage erstellen" - -msgid "Define dates or subjects to choose" -msgstr "Datum- oder Auswahlmöglichkeiten definieren" - -msgid "Send the poll link to your friends or colleagues" -msgstr "Link zur Umfrage an Ihre Freunde oder Kollegen schicken" - -msgid "Discuss and make a decision" -msgstr "Besprechen und Entscheidung treffen" - -msgid "Do you want to " -msgstr "Wollen Sie sich " - -msgid "view an example?" -msgstr "einen Beispiel ansehen?" - -# 2nd section -msgid "The software" -msgstr "Die Software" - -msgid "Framadate was initially based on " -msgstr "Framadate war am Anfang auf " - -msgid " a software developed by the University of Strasbourg. Today, it is devevoped by the association Framasoft" -msgstr " basiert, eine von der Straßburg-Universität entwickelte Software. Heutzutage wird sie von der Framasoft-Vereinigung entwickelt." - -msgid "This software needs javascript and cookies enabled. It is compatible with the following web browsers:" -msgstr "Für diese Software müssen Javascript und Cookie aktiviert sein. Sie ist mit den folgenden Browsers kompatibel:" - -msgid "It is governed by the " -msgstr "Sie ist lizenziert unter der " - -msgid "CeCILL-B license" -msgstr "CeCILL-B Lizenz" - -# 3rd section -msgid "Cultivate your garden" -msgstr "Bestellen Sie ihren Garten" - -msgid "To participate in the software development, suggest improvements or simply download it, please visit " -msgstr "Um zur Software-Entwicklung teilzunehmen, Verbesserungen vorzuschlagen oder um sie herunterzuladen, gehen Sie auf " - -msgid "the development site" -msgstr "die Entwicklung-Seite" - -msgid "If you want to install the software for your own use and thus increase your independence, we help you on:" -msgstr "Wenn Sie die Software für Ihre eigene Nutzung installieren möchten und Ihre Eigenständigkeit erhöhen, helfen wir Sie auf:" - -############## Poll ############## -msgid "Poll administration" -msgstr "Umfrage-Verwaltung" - -msgid "Legend:" -msgstr "Legende:" - -# Jumbotron adminstuds.php (+ studs.php) -msgid "Back to the poll" -msgstr "Zurück zur Umfrage" - -msgid "Print" -msgstr "Drucken" - -msgid "Export to CSV" -msgstr "CSV-Export" - -msgid "Remove the poll" -msgstr "Umfrage löschen" - -msgid "Title of the poll" -msgstr "Titel der Umfrage" - -msgid "Edit the title" -msgstr "Titel bearbeiten" - -msgid "Save the new title" -msgstr "Den neuen Titel speichern" - -msgid "Cancel the title edit" -msgstr "Änderung des Titels abbrechen" - -msgid "Initiator of the poll" -msgstr "Ersteller der Umfrage" - -msgid "Email" -msgstr "E-Mail Adresse" - -msgid "Edit the email adress" -msgstr "E-Mail Adresse ändern" - -msgid "Save the adress email" -msgstr "E-Mail Adresse speichern" - -msgid "Cancel the adress email edit" -msgstr "Änderung der E-Mail Adresse abbrechen" - -msgid "Edit the description" -msgstr "Beschreibung bearbeiten" - -msgid "Save the description" -msgstr "Beschreibung speichern" - -msgid "Cancel the description edit" -msgstr "Änderung der Beschreibung verwerfen" - -msgid "Public link of the poll" -msgstr "Öffentlicher Link zur Umfrage" - -msgid "Admin link of the poll" -msgstr "Administrator-Link der Umfrage" - -msgid "Poll rules" -msgstr "Regeln der Umfrage" - -msgid "Edit the poll rules" -msgstr "Regeln der Umfrage bearbeiten" - -msgid "Votes and comments are locked" -msgstr "Abstimmungen und Kommentare sind gesperrt" - -msgid "Votes and comments are open" -msgstr "Abstimmungen und Kommentare sind möglich" - -msgid "Votes are editable" -msgstr "Die Abstimmungen können geändert werden" - -msgid "Save the new rules" -msgstr "Neue Regeln speichern" - -msgid "Cancel the rules edit" -msgstr "Neue Regeln nicht speichern" - -# Help text adminstuds.php -msgid "As poll administrator, you can change all the lines of this poll with this button " -msgstr "Als Administrator der Umfrage, können Sie alle Zeilen der Umfrage über diesen Button ändern " - -msgid " remove a column or a line with " -msgstr " Zeile oder Spalte entfernen mit " - -msgid "and add a new column with " -msgstr "und neue Spalte hinzufügen mit " - -msgid "Finally, you can change the informations of this poll like the title, the comments or your email address." -msgstr "Sie können auch die Informationen dieser Umfrage wie Titel, Kommentare oder E-Mail Adresse ändern." - -# Help text studs.php -msgid "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." -msgstr "Wenn Sie bei dieser Umfrage abstimmen möchten, müssen Sie ihren Namen angeben. Wählen Sie die Optionen, die für Sie am besten passen und bestätigen Sie diese über den Plus-Button am Ende der Zeile." - -# Poll results -msgid "Votes of the poll " -msgstr "Abstimmungen der Umfrage " - -msgid "Remove the column" -msgstr "Spalte entfernen" - -msgid "Add a column" -msgstr "Spalte hinzufügen" - -msgid "Edit the line:" -msgstr "Zeile bearbeiten:" - -msgid "Remove the line:" -msgstr "Zeile entfernen:" - -msgid "Yes" -msgstr "Ja" - -msgid "Ifneedbe" -msgstr "Wenn notwendig" - -msgid ", ifneedbe" -msgstr ", wenn notwendig" - -msgid "No" -msgstr "Nein" - -msgid "Vote \"no\" for " -msgstr "Stimme « nein » für " - -msgid "Vote \"yes\" for " -msgstr "Stimme « ja » für " - -msgid "Vote \"ifneedbe\" for " -msgstr "Stimme « Wenn notwendig » für " - -msgid "Save the choices" -msgstr "Wahl speichern" - -msgid "Addition" -msgstr "Hinzufügen" - -msgid "Best choice" -msgstr "Bste Option" - -msgid "Best choices" -msgstr "Besten Optionen" - -msgid "The best choice at this time is:" -msgstr "Die beste Option ist derzeit:" - -msgid "The bests choices at this time are:" -msgstr "Die beste Optionen sind derzeit:" - -msgid "with" -msgstr "mit" - -msgid "vote" -msgstr "Stimme" - -msgid "votes" -msgstr "Stimmen" - -msgid "for" -msgstr "für" - -msgid "Remove all the votes" -msgstr "Alle Stimmungen löschen" - -msgid "Scroll to the left" -msgstr "Links scrollen" - -msgid "Scroll to the right" -msgstr "Rechts scrollen" - -# Comments -msgid "Comments of polled people" -msgstr "Kommentare von Teilnehmer" - -msgid "Remove the comment" -msgstr "Kommentar entfernen" - -msgid "Add a comment in the poll" -msgstr "Kommentar zur Umfrage hinzufügen" - -msgid "Your comment" -msgstr "Ihr Kommentar" - -msgid "Send the comment" -msgstr "Kommentar senden" - -msgid "anonyme" -msgstr "anonym" - -msgid "Remove all the comments" -msgstr "Alle Kommentare löschen" - -# Add a colum adminstuds.php -msgid "Column's adding" -msgstr "Spalte hinzufügen" - -msgid "You can add a new scheduling date to your poll." -msgstr "Sie können zur Umfrage ein neues Datum hinzufügen." - -msgid "If you just want to add a new hour to an existant date, put the same date and choose a new hour." -msgstr "Wenn Sie nur eine neue Uhrzeiteit zu einem existierenden Datum hinzufügen wollen, wählen Sie das selbe Datum und wählen Sie eine neue Zeit aus." - -# Remove poll adminstuds.php -msgid "Confirm removal of your poll" -msgstr "Löschen der Umfrage bestätigen" - -msgid "Remove this poll!" -msgstr "Diese Umfrage löschen!" - -msgid "Keep this poll!" -msgstr "Diese Umfrage nicht löschen!" - -msgid "Your poll has been removed!" -msgstr "Ihre Umfrage wurde gelöscht!" - -# Errors adminstuds.php/studs -msgid "This poll doesn't exist !" -msgstr "Diese Umfrage existiert nicht!" - -msgid "Enter a name" -msgstr "Geben Sie einen Namen ein" - -msgid "The name you've chosen already exist in this poll!" -msgstr "Der von Ihnen eingegebenen Name existiert bereits in dieser Umfrage" - -msgid "Enter a name and a comment!" -msgstr "Geben Sie einen Namen und ein Kommentar ein!" - -msgid "Failed to insert the comment!" -msgstr "Einfügen des Kommentars gescheitert!" - -msgid "Characters \" ' < et > are not permitted" -msgstr "Die Zeichen \" ' < und > sind nicht erlaubt !" - -msgid "The date is not correct !" -msgstr "Das Datum ist nicht korrekt!" - -########### Step 1 ########### -# Step 1 info_sondage.php -msgid "Poll creation (1 on 3)" -msgstr "Umfrage erstellen (1 von 3)" - -msgid "Framadate is not properly installed, please check the 'INSTALL' to setup the database before continuing." -msgstr "Framadate ist nicht richtig installiert, lesen Sie 'INSTALL' um die Datenbank aufzusetzen bevor es weiter geht." - -msgid "You are in the poll creation section." -msgstr "Sie können hier Umfragen erstellen" - -msgid "Required fields cannot be left blank." -msgstr "Mit * markierte Felder müssen ausgefüllt sein." - -msgid "Poll title" -msgstr "Umfragetitel" - -msgid "Voters can modify their vote themselves." -msgstr "Teilnehmer können ihre Antworten verändern" - -msgid "To receive an email for each new vote." -msgstr "Bei jeder neuen Abstimmung eine E-Mail erhalten." - -msgid "Go to step 2" -msgstr "Weiter zum 2. Schritt" - -# Errors info_sondage.php -msgid "Enter a title" -msgstr "Titel eingeben" - -msgid "Characters < > and \" are not permitted" -msgstr "Die Zeichen < > und \" sind nicht erlaubt !" - -msgid "Enter an email address" -msgstr "Sie müssen eine E-Mail Adresse eingeben" - -msgid "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." -msgstr "Die Adresse ist nicht korrekt! Sie sollten eine funktionierende E-Mail Adresse angeben, um den Link zu ihrer Umfrage zu erhalten" - -# Error choix_date.php/choix_autre.php -msgid "You haven't filled the first section of the poll creation." -msgstr "Sie haben den ersten Teil der Umfrageerstellung nicht ausgefüllt." - -msgid "Back to step 1" -msgstr "Zurück zum 1. Schritt" - -########### Step 2 ########### -# Step 2 choix_date.php -msgid "Poll dates (2 on 3)" -msgstr "Umfragedaten (2 von 3)" - -msgid "Choose the dates of your poll" -msgstr "Wählen Sie Terminmöglichkeiten für Ihre Umfrage" - -msgid "To schedule an event, it's better to propose at least two choices (two hours for one day or two days)." -msgstr "Um eine Umfrage für einen Termin zu erstellen, müssen Sie mindestens zwei Auswahlmöglichkeiten angeben (zwei verschiedene Zeiten an einem Tag oder zwei Tage)." - -msgid "You can add or remove additionnal days and hours with the buttons" -msgstr "Sie können weitere Tage und Uhrzeiten über diesen Button hinzufügen oder entfernen" - -msgid "For each selected day, you can choose, or not, meeting hours (e.g.: \"8h\", \"8:30\", \"8h-10h\", \"evening\", etc.)" -msgstr "Sie können (müssen aber nicht), für jeden ausgewählten Tage, Zeiten für den Termin (z.B. \"8h\", \"8:30\", \"8-10Uhr\", \"Abends\", etc.) angeben." - -msgid "Day" -msgstr "Tag" - -msgid "Time" -msgstr "Uhrzeit" - -msgid "Remove an hour" -msgstr "Eine Uhrzeit entfernen" - -msgid "Add an hour" -msgstr "Eine Uhrzeit hinzufügen" - -msgid "Copy hours of the first day" -msgstr "Uhrzeiten des ersten Tags kopieren" - -msgid "Remove a day" -msgstr "Einen Tag entfernen" - -msgid "Add a day" -msgstr "Einen Tag hinzufügen" - -msgid "Remove all days" -msgstr "Alle Tage entfernen" - -msgid "Remove all hours" -msgstr "Alle Uhrzeiten entfernen" - -# Step 2 choix_autre.php -msgid "Poll subjects (2 on 3)" -msgstr "Umfragethemen (2 von 3)" - -msgid "To make a generic poll, it's better to propose at least two choices between differents subjects." -msgstr "Um eine allgemeine Umfrage zu erstellen, benötigen Sie mindestens zwei Auswahlmöglichkeiten zwischen verschiedenen Themen." - -msgid "You can add or remove additional choices with the buttons" -msgstr "Sie können über den Button zusätzliche Auswahlmöglichkeiten hinzufügen oder entfernen" - -msgid "It's possible to propose links or images by using " -msgstr "Es besteht die Möglichkeit, Links oder Bilder vorszuschlagen mit " - -msgid "the Markdown syntax" -msgstr "Markdown" - -msgid "Choice" -msgstr "Wahl" - -msgid "Add a link or an image" -msgstr "Link oder Bild hinzufügen" - -msgid "These fields are optional. You can add a link, an image or both." -msgstr "Diese Felder sind optional. Sie können einen Link, ein Bild oder beide hinzufügen." - -msgid "URL of the image" -msgstr "URL des Bilds" - -msgid "Link" -msgstr "Link" - -msgid "Alternative text" -msgstr "Alternativer Text" - -msgid "Remove a choice" -msgstr "Eine Auswahlmöglichkeit entfernen" - -msgid "Add a choice" -msgstr "Eine Auswahlmöglichkeit hinzufügen" - -msgid "Back to step 2" -msgstr "Zurück zum 2. Schritt" - -msgid "Go to step 3" -msgstr "Weiter zum 3. Schritt" - -########### Step 3 ########### -msgid "Removal date and confirmation (3 on 3)" -msgstr "Löschdatum und Bestätigung (3 von 3)" - -msgid "Confirm the creation of your poll" -msgstr "Bestätigen Sie die Erstellung ihrer Umfrage" - -msgid "List of your choices" -msgstr "Liste Ihrer Auswahlmöglichkeiten" - -msgid "Once you have confirmed the creation of your poll, you will be automatically redirected on the administration page of your poll." -msgstr "Wenn Sie die Erstellung ihrer Umfrage bestätigt haben, werden sie automatisch zur Administrationsseite ihrer Umfrage weitergeleitet." - -msgid "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." -msgstr "Danach werden Sie zwei E-Mails erhalten: die Eine enthält den Link zur Umfrage für die Teilnehmer, die Andere enthält den Link zur Administrationsseite ihrer Umfrage." - -msgid "Create the poll" -msgstr "Umfrage erstellen" - -# Step 3 choix_date.php -msgid "Your poll will expire automatically 2 days after the last date of your poll." -msgstr "Ihre Umfrage wird automatisch zwei Tage nach dem letzten Datum ihrer Umfrage auslaufen." - -msgid "Removal date:" -msgstr "Löschdatum:" - -# Step 3 choix_autre.php -msgid "Your poll will be automatically removed after 6 months." -msgstr "Ihre Umfrage wird automatisch nach 6 Monaten gelöscht." - -msgid "You can fix another removal date for it." -msgstr "Sie können auch ein anderes Löschdatum festlegen." - -msgid "Removal date (optional)" -msgstr "Löschdatum (optional)" - -############# Admin ############# -msgid "Polls administrator" -msgstr "Umfrageadministrator" - -msgid "Confirm removal of the poll " -msgstr "Bestätigen Sie die Löschung ihrer Umfrage" - -msgid "polls in the database at this time" -msgstr "Umfragen derzeit in der Datenbank" - -msgid "Poll ID" -msgstr "Umfrage-ID" - -msgid "Format" -msgstr "Format" - -msgid "Title" -msgstr "Titel" - -msgid "Author" -msgstr "Autor" - -msgid "Users" -msgstr "Nutzer" - -msgid "Actions" -msgstr "Aktionen" - -msgid "See the poll" -msgstr "Umfrage sehen" - -msgid "Change the poll" -msgstr "Umfrage ändern" - -msgid "Logs" -msgstr "Verlauf" - -########### Mails ########### -# Mails studs.php -msgid "Poll's participation" -msgstr "Beteiligung an der Umfrage" - -msgid "" -"has filled a line.\n" -"You can find your poll at the link" -msgstr "" -" hat eine Zeile ausgefüllt.\n" -"Sie finden Ihre Umfrage unter dem folgenden Link:" - -msgid "Thanks for your confidence." -msgstr "Danke für Ihr Vertrauen." - -msgid "\n" -"--\n\n" -"« La route est longue, mais la voie est libre… »\n" -"Framasoft ne vit que par vos dons (déductibles des impôts).\n" -"Merci d'avance pour votre soutien http://soutenir.framasoft.org." -msgstr "\n" -"\n" -"\n" -"\n" -" " - -# Mails adminstuds.php -msgid "[ADMINISTRATOR] New settings for your poll" -msgstr "[ADMINISTRATOR] Neue Einstellungen für Ihre Umfrage " - -msgid "" -"You have changed the settings of your poll. \n" -"You can modify this poll with this link" -msgstr "" -"Sie haben die Einstellungen Ihrer Umfrage geändert. \n" -"Sie können Ihre Umfrage unter diesem Link ändern" - -# Mails creation_sondage.php -msgid "" -"This is the message you have to send to the people you want to poll. \n" -"Now, you have to send this message to everyone you want to poll." -msgstr "" -"Dies ist die Nachricht, die Sie an die Personen, die Sie zur Umfrage einladen möchten, schicken sollen. \n" -"Schicken Sie jetzt bitte diese Nachricht an alle Personen, die Sie zur Umfrage einladen möchten." - -msgid "hast just created a poll called" -msgstr " hat eine Umfrage erstellt - Name folgt: " - -msgid "Thanks for filling the poll at the link above" -msgstr "Danke, dass Sie die Umfrage unter dem obrigen Link ausgefüllt haben" - -msgid "" -"This message should NOT be sent to the polled people. It is private for the poll's creator.\n" -"\n" -"You can now modify it at the link above" -msgstr "" -"Diese Nachricht sollte NICHT an die befragten Personen gesendet werden. Sie nur für den Autor der Umfrage gemeint.\n" -"\n" -"Sie können die Umfrage unter dem oberen Link bearbeiten " - -msgid "Author's message" -msgstr "Nachricht vom Autor " - -msgid "For sending to the polled users" -msgstr "Nachricht für die Teilnehmer" +msgid "" +msgstr "" +"Project-Id-Version: Framadate 0.8\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-10-23 20:52+0100\n" +"PO-Revision-Date: 2014-10-23 20:52+0100\n" +"Last-Translator: Jonathan Brielmaier\n" +"Language-Team: Jonathan Brielmaier\n" +"Language: German\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: German\n" +"X-Poedit-Country: GERMANY\n" +"X-Poedit-SourceCharset: utf-8\n" +"X-Poedit-KeywordsList: _\n" +"X-Poedit-Basepath: /var/www/studs\n" +"X-Poedit-SearchPath-0: .\n" + +########### Generic ########### +msgid "Make your polls" +msgstr "Eigene Umfragen erstellen" + +msgid "Home" +msgstr "Home" + +msgid "Poll" +msgstr "Umfrage" + +msgid "Save" +msgstr "Speichern" + +msgid "Cancel" +msgstr "Abbrechen" + +msgid "Add" +msgstr "Hinzufügen" + +msgid "Remove" +msgstr "Entfernen" + +msgid "Validate" +msgstr "Bestätigen" + +msgid "Edit" +msgstr "Bearbeiten" + +msgid "Next" +msgstr "Weiter" + +msgid "Back" +msgstr "Zurück" + +msgid "Close" +msgstr "Schließen" + +msgid "Your name" +msgstr "Ihr Name" + +msgid "Your email address" +msgstr "Ihre E-Mail Adresse" + +msgid "(in the format name@mail.com)" +msgstr "(Format: name@mail.com)" + +msgid "Description" +msgstr "Beschreibung" + +msgid "Back to the homepage of" +msgstr "Zurück zur Homepage von " + +msgid "Error!" +msgstr "Fehler!" + +msgid "(dd/mm/yyyy)" +msgstr "(tt/mm/jjjj)" + +msgid "dd/mm/yyyy" +msgstr "tt/mm/jjjj" + +msgid "%A, den %e. %B %Y" +msgstr "%A %e %B %Y" + +msgid "Expiration's date" +msgstr "Verfallsdatum" + +########### Language selector ########### +msgid "Change the language" +msgstr "Sprache wechseln" + +msgid "Select the language" +msgstr "Sprache wählen" + +############ Homepage ############ +msgid "Schedule an event" +msgstr "Termin finden" + +msgid "Make a classic poll" +msgstr "Klassische Umfrage" + +# 1st section +msgid "What is that?" +msgstr "Was ist das?" + +msgid "Framadate is an online service for planning an appointment or make a decision quickly and easily. No registration is required." +msgstr "Framadate ist ein Online-Dienst, das Ihnen hilft, Termine zu finden oder Entscheidungen schnell und einfach zu treffen. Keine Registrierung ist erforderlich. " + +msgid "Here is how it works:" +msgstr "So geht es:" + +msgid "Make a poll" +msgstr "Umfrage erstellen" + +msgid "Define dates or subjects to choose" +msgstr "Datum- oder Auswahlmöglichkeiten definieren" + +msgid "Send the poll link to your friends or colleagues" +msgstr "Link zur Umfrage an Ihre Freunde oder Kollegen schicken" + +msgid "Discuss and make a decision" +msgstr "Besprechen und Entscheidung treffen" + +msgid "Do you want to " +msgstr "Wollen Sie sich " + +msgid "view an example?" +msgstr "einen Beispiel ansehen?" + +# 2nd section +msgid "The software" +msgstr "Die Software" + +msgid "Framadate was initially based on " +msgstr "Framadate war am Anfang auf " + +msgid " a software developed by the University of Strasbourg. Today, it is devevoped by the association Framasoft" +msgstr " basiert, eine von der Straßburg-Universität entwickelte Software. Heutzutage wird sie von der Framasoft-Vereinigung entwickelt." + +msgid "This software needs javascript and cookies enabled. It is compatible with the following web browsers:" +msgstr "Für diese Software müssen Javascript und Cookie aktiviert sein. Sie ist mit den folgenden Browsers kompatibel:" + +msgid "It is governed by the " +msgstr "Sie ist lizenziert unter der " + +msgid "CeCILL-B license" +msgstr "CeCILL-B Lizenz" + +# 3rd section +msgid "Cultivate your garden" +msgstr "Bestellen Sie ihren Garten" + +msgid "To participate in the software development, suggest improvements or simply download it, please visit " +msgstr "Um zur Software-Entwicklung teilzunehmen, Verbesserungen vorzuschlagen oder um sie herunterzuladen, gehen Sie auf " + +msgid "the development site" +msgstr "die Entwicklung-Seite" + +msgid "If you want to install the software for your own use and thus increase your independence, we help you on:" +msgstr "Wenn Sie die Software für Ihre eigene Nutzung installieren möchten und Ihre Eigenständigkeit erhöhen, helfen wir Sie auf:" + +############## Poll ############## +msgid "Poll administration" +msgstr "Umfrage-Verwaltung" + +msgid "Legend:" +msgstr "Legende:" + +# Jumbotron adminstuds.php (+ studs.php) +msgid "Back to the poll" +msgstr "Zurück zur Umfrage" + +msgid "Print" +msgstr "Drucken" + +msgid "Export to CSV" +msgstr "CSV-Export" + +msgid "Remove the poll" +msgstr "Umfrage löschen" + +msgid "Title of the poll" +msgstr "Titel der Umfrage" + +msgid "Edit the title" +msgstr "Titel bearbeiten" + +msgid "Save the new title" +msgstr "Den neuen Titel speichern" + +msgid "Cancel the title edit" +msgstr "Änderung des Titels abbrechen" + +msgid "Initiator of the poll" +msgstr "Ersteller der Umfrage" + +msgid "Email" +msgstr "E-Mail Adresse" + +msgid "Edit the email adress" +msgstr "E-Mail Adresse ändern" + +msgid "Save the adress email" +msgstr "E-Mail Adresse speichern" + +msgid "Cancel the adress email edit" +msgstr "Änderung der E-Mail Adresse abbrechen" + +msgid "Edit the description" +msgstr "Beschreibung bearbeiten" + +msgid "Save the description" +msgstr "Beschreibung speichern" + +msgid "Cancel the description edit" +msgstr "Änderung der Beschreibung verwerfen" + +msgid "Public link of the poll" +msgstr "Öffentlicher Link zur Umfrage" + +msgid "Admin link of the poll" +msgstr "Administrator-Link der Umfrage" + +msgid "Poll rules" +msgstr "Regeln der Umfrage" + +msgid "Edit the poll rules" +msgstr "Regeln der Umfrage bearbeiten" + +msgid "Votes and comments are locked" +msgstr "Abstimmungen und Kommentare sind gesperrt" + +msgid "Votes and comments are open" +msgstr "Abstimmungen und Kommentare sind möglich" + +msgid "Votes are editable" +msgstr "Die Abstimmungen können geändert werden" + +msgid "Save the new rules" +msgstr "Neue Regeln speichern" + +msgid "Cancel the rules edit" +msgstr "Neue Regeln nicht speichern" + +# Help text adminstuds.php +msgid "As poll administrator, you can change all the lines of this poll with this button" +msgstr "Als Administrator der Umfrage, können Sie alle Zeilen der Umfrage über diesen Button ändern" + +msgid "remove a column or a line with" +msgstr "Zeile oder Spalte entfernen mit" + +msgid "and add a new column with" +msgstr "und neue Spalte hinzufügen mit" + +msgid "Finally, you can change the informations of this poll like the title, the comments or your email address." +msgstr "Sie können auch die Informationen dieser Umfrage wie Titel, Kommentare oder E-Mail Adresse ändern." + +# Help text studs.php +msgid "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." +msgstr "Wenn Sie bei dieser Umfrage abstimmen möchten, müssen Sie ihren Namen angeben. Wählen Sie die Optionen, die für Sie am besten passen und bestätigen Sie diese über den Plus-Button am Ende der Zeile." + +# Poll results +msgid "Votes of the poll " +msgstr "Abstimmungen der Umfrage " + +msgid "Remove the column" +msgstr "Spalte entfernen" + +msgid "Add a column" +msgstr "Spalte hinzufügen" + +msgid "Edit the line:" +msgstr "Zeile bearbeiten:" + +msgid "Remove the line:" +msgstr "Zeile entfernen:" + +msgid "Yes" +msgstr "Ja" + +msgid "Ifneedbe" +msgstr "Wenn notwendig" + +msgid ", ifneedbe" +msgstr ", wenn notwendig" + +msgid "No" +msgstr "Nein" + +msgid "Vote \"no\" for " +msgstr "Stimme « nein » für " + +msgid "Vote \"yes\" for " +msgstr "Stimme « ja » für " + +msgid "Vote \"ifneedbe\" for " +msgstr "Stimme « Wenn notwendig » für " + +msgid "Save the choices" +msgstr "Wahl speichern" + +msgid "Addition" +msgstr "Hinzufügen" + +msgid "Best choice" +msgstr "Bste Option" + +msgid "Best choices" +msgstr "Besten Optionen" + +msgid "The best choice at this time is:" +msgstr "Die beste Option ist derzeit:" + +msgid "The bests choices at this time are:" +msgstr "Die beste Optionen sind derzeit:" + +msgid "with" +msgstr "mit" + +msgid "vote" +msgstr "Stimme" + +msgid "votes" +msgstr "Stimmen" + +msgid "for" +msgstr "für" + +msgid "Remove all the votes" +msgstr "Alle Stimmungen löschen" + +msgid "Scroll to the left" +msgstr "Links scrollen" + +msgid "Scroll to the right" +msgstr "Rechts scrollen" + +# Comments +msgid "Comments of polled people" +msgstr "Kommentare von Teilnehmer" + +msgid "Remove the comment" +msgstr "Kommentar entfernen" + +msgid "Add a comment in the poll" +msgstr "Kommentar zur Umfrage hinzufügen" + +msgid "Your comment" +msgstr "Ihr Kommentar" + +msgid "Send the comment" +msgstr "Kommentar senden" + +msgid "anonyme" +msgstr "anonym" + +msgid "Remove all the comments" +msgstr "Alle Kommentare löschen" + +# Add a colum adminstuds.php +msgid "Column's adding" +msgstr "Spalte hinzufügen" + +msgid "You can add a new scheduling date to your poll." +msgstr "Sie können zur Umfrage ein neues Datum hinzufügen." + +msgid "If you just want to add a new hour to an existant date, put the same date and choose a new hour." +msgstr "Wenn Sie nur eine neue Uhrzeiteit zu einem existierenden Datum hinzufügen wollen, wählen Sie das selbe Datum und wählen Sie eine neue Zeit aus." + +# Remove poll adminstuds.php +msgid "Confirm removal of your poll" +msgstr "Löschen der Umfrage bestätigen" + +msgid "Remove this poll!" +msgstr "Diese Umfrage löschen!" + +msgid "Keep this poll!" +msgstr "Diese Umfrage nicht löschen!" + +msgid "Your poll has been removed!" +msgstr "Ihre Umfrage wurde gelöscht!" + +# Errors adminstuds.php/studs +msgid "This poll doesn't exist !" +msgstr "Diese Umfrage existiert nicht!" + +msgid "Enter a name" +msgstr "Geben Sie einen Namen ein" + +msgid "The name you've chosen already exist in this poll!" +msgstr "Der von Ihnen eingegebenen Name existiert bereits in dieser Umfrage" + +msgid "Enter a name and a comment!" +msgstr "Geben Sie einen Namen und ein Kommentar ein!" + +msgid "Failed to insert the comment!" +msgstr "Einfügen des Kommentars gescheitert!" + +msgid "Characters \" ' < et > are not permitted" +msgstr "Die Zeichen \" ' < und > sind nicht erlaubt !" + +msgid "The date is not correct !" +msgstr "Das Datum ist nicht korrekt!" + +########### Step 1 ########### +# Step 1 info_sondage.php +msgid "Poll creation (1 on 3)" +msgstr "Umfrage erstellen (1 von 3)" + +msgid "Framadate is not properly installed, please check the 'INSTALL' to setup the database before continuing." +msgstr "Framadate ist nicht richtig installiert, lesen Sie 'INSTALL' um die Datenbank aufzusetzen bevor es weiter geht." + +msgid "You are in the poll creation section." +msgstr "Sie können hier Umfragen erstellen" + +msgid "Required fields cannot be left blank." +msgstr "Mit * markierte Felder müssen ausgefüllt sein." + +msgid "Poll title" +msgstr "Umfragetitel" + +msgid "Voters can modify their vote themselves." +msgstr "Teilnehmer können ihre Antworten verändern" + +msgid "To receive an email for each new vote." +msgstr "Bei jeder neuen Abstimmung eine E-Mail erhalten." + +msgid "Go to step 2" +msgstr "Weiter zum 2. Schritt" + +# Errors info_sondage.php +msgid "Enter a title" +msgstr "Titel eingeben" + +msgid "Something is wrong with the format" +msgstr "Something is wrong with the format" + +msgid "Enter an email address" +msgstr "Sie müssen eine E-Mail Adresse eingeben" + +msgid "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." +msgstr "Die Adresse ist nicht korrekt! Sie sollten eine funktionierende E-Mail Adresse angeben, um den Link zu ihrer Umfrage zu erhalten" + +# Error choix_date.php/choix_autre.php +msgid "You haven't filled the first section of the poll creation." +msgstr "Sie haben den ersten Teil der Umfrageerstellung nicht ausgefüllt." + +msgid "Back to step 1" +msgstr "Zurück zum 1. Schritt" + +########### Step 2 ########### +# Step 2 choix_date.php +msgid "Poll dates (2 on 3)" +msgstr "Umfragedaten (2 von 3)" + +msgid "Choose the dates of your poll" +msgstr "Wählen Sie Terminmöglichkeiten für Ihre Umfrage" + +msgid "To schedule an event you need to propose at least two choices (two hours for one day or two days)." +msgstr "Um eine Umfrage für einen Termin zu erstellen, müssen Sie mindestens zwei Auswahlmöglichkeiten angeben (zwei verschiedene Zeiten an einem Tag oder zwei Tage)." + +msgid "You can add or remove additionnal days and hours with the buttons" +msgstr "Sie können weitere Tage und Uhrzeiten über diesen Button hinzufügen oder entfernen" + +msgid "For each selected day, you can choose, or not, meeting hours (e.g.: \"8h\", \"8:30\", \"8h-10h\", \"evening\", etc.)" +msgstr "Sie können (müssen aber nicht), für jeden ausgewählten Tage, Zeiten für den Termin (z.B. \"8h\", \"8:30\", \"8-10Uhr\", \"Abends\", etc.) angeben." + +msgid "Day" +msgstr "Tag" + +msgid "Time" +msgstr "Uhrzeit" + +msgid "Remove an hour" +msgstr "Eine Uhrzeit entfernen" + +msgid "Add an hour" +msgstr "Eine Uhrzeit hinzufügen" + +msgid "Copy hours of the first day" +msgstr "Uhrzeiten des ersten Tags kopieren" + +msgid "Remove a day" +msgstr "Einen Tag entfernen" + +msgid "Add a day" +msgstr "Einen Tag hinzufügen" + +msgid "Remove all days" +msgstr "Alle Tage entfernen" + +msgid "Remove all hours" +msgstr "Alle Uhrzeiten entfernen" + +# Step 2 choix_autre.php +msgid "Poll subjects (2 on 3)" +msgstr "Umfragethemen (2 von 3)" + +msgid "To make a generic poll you need to propose at least two choices between differents subjects." +msgstr "Um eine allgemeine Umfrage zu erstellen, benötigen Sie mindestens zwei Auswahlmöglichkeiten zwischen verschiedenen Themen." + +msgid "You can add or remove additional choices with the buttons" +msgstr "Sie können über den Button zusätzliche Auswahlmöglichkeiten hinzufügen oder entfernen" + +msgid "It's possible to propose links or images by using " +msgstr "Es besteht die Möglichkeit, Links oder Bilder vorszuschlagen mit " + +msgid "the Markdown syntax" +msgstr "Markdown" + +msgid "Choice" +msgstr "Wahl" + +msgid "Add a link or an image" +msgstr "Link oder Bild hinzufügen" + +msgid "These fields are optional. You can add a link, an image or both." +msgstr "Diese Felder sind optional. Sie können einen Link, ein Bild oder beide hinzufügen." + +msgid "URL of the image" +msgstr "URL des Bilds" + +msgid "Link" +msgstr "Link" + +msgid "Alternative text" +msgstr "Alternativer Text" + +msgid "Remove a choice" +msgstr "Eine Auswahlmöglichkeit entfernen" + +msgid "Add a choice" +msgstr "Eine Auswahlmöglichkeit hinzufügen" + +msgid "Back to step 2" +msgstr "Zurück zum 2. Schritt" + +msgid "Go to step 3" +msgstr "Weiter zum 3. Schritt" + +########### Step 3 ########### +msgid "Removal date and confirmation (3 on 3)" +msgstr "Löschdatum und Bestätigung (3 von 3)" + +msgid "Confirm the creation of your poll" +msgstr "Bestätigen Sie die Erstellung ihrer Umfrage" + +msgid "List of your choices" +msgstr "Liste Ihrer Auswahlmöglichkeiten" + +msgid "Once you have confirmed the creation of your poll, you will be automatically redirected on the administration page of your poll." +msgstr "Wenn Sie die Erstellung ihrer Umfrage bestätigt haben, werden sie automatisch zur Administrationsseite ihrer Umfrage weitergeleitet." + +msgid "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." +msgstr "Danach werden Sie zwei E-Mails erhalten: die Eine enthält den Link zur Umfrage für die Teilnehmer, die Andere enthält den Link zur Administrationsseite ihrer Umfrage." + +msgid "Create the poll" +msgstr "Umfrage erstellen" + +# Step 3 choix_date.php +msgid "Your poll will expire automatically 2 days after the last date of your poll." +msgstr "Ihre Umfrage wird automatisch zwei Tage nach dem letzten Datum ihrer Umfrage auslaufen." + +msgid "Removal date:" +msgstr "Löschdatum:" + +# Step 3 choix_autre.php +msgid "Your poll will be automatically removed after 6 months." +msgstr "Ihre Umfrage wird automatisch nach 6 Monaten gelöscht." + +msgid "You can set a closer removal date for it." +msgstr "Sie können auch ein anderes Löschdatum festlegen." + +msgid "Removal date (optional)" +msgstr "Löschdatum (optional)" + +############# Admin ############# +msgid "Polls administrator" +msgstr "Umfrageadministrator" + +msgid "Confirm removal of the poll " +msgstr "Bestätigen Sie die Löschung ihrer Umfrage" + +msgid "polls in the database at this time" +msgstr "Umfragen derzeit in der Datenbank" + +msgid "Poll ID" +msgstr "Umfrage-ID" + +msgid "Format" +msgstr "Format" + +msgid "Title" +msgstr "Titel" + +msgid "Author" +msgstr "Autor" + +msgid "Users" +msgstr "Nutzer" + +msgid "Actions" +msgstr "Aktionen" + +msgid "See the poll" +msgstr "Umfrage sehen" + +msgid "Change the poll" +msgstr "Umfrage ändern" + +msgid "Logs" +msgstr "Verlauf" + +msgid "Summary" +msgstr "Zusammenfassung" + +msgid "Success" +msgstr "Erfolg" + +msgid "Fail" +msgstr "scheitern" + +msgid "Nothing" +msgstr "Nichts" + +msgid "Succeeded:" +msgstr "Erfolgreich:" + +msgid "Failed:" +msgstr "fehlgeschlagen:" + +msgid "Skipped:" +msgstr "übersprungene:" + +msgid "Pages:" +msgstr "Seiten:" + +########### Mails ########### +# Mails studs.php +msgid "Poll's participation" +msgstr "Beteiligung an der Umfrage" + +msgid "" +"filled a vote.\n" +"You can find your poll at the link" +msgstr "" +"hat eine Zeile ausgefüllt.\n" +"Sie finden Ihre Umfrage unter dem folgenden Link:" + +msgid "" +"updated a vote.\n" +"You can find your poll at the link" +msgstr "" +"updated a vote.\n" +"Sie finden Ihre Umfrage unter dem folgenden Link:" + +msgid "" +"wrote a comment.\n" +"You can find your poll at the link" +msgstr "" +"wrote a comment.\n" +"Sie finden Ihre Umfrage unter dem folgenden Link:" + +msgid "Thanks for your confidence." +msgstr "Danke für Ihr Vertrauen." + +msgid "\n" +"--\n\n" +"« La route est longue, mais la voie est libre… »\n" +"Framasoft ne vit que par vos dons (déductibles des impôts).\n" +"Merci d'avance pour votre soutien http://soutenir.framasoft.org." +msgstr "\n" +"\n" +"\n" +"\n" +" " + +# Mails adminstuds.php +msgid "[ADMINISTRATOR] New settings for your poll" +msgstr "[ADMINISTRATOR] Neue Einstellungen für Ihre Umfrage " + +msgid "" +"You have changed the settings of your poll. \n" +"You can modify this poll with this link" +msgstr "" +"Sie haben die Einstellungen Ihrer Umfrage geändert. \n" +"Sie können Ihre Umfrage unter diesem Link ändern" + +# Mails creation_sondage.php +msgid "" +"This is the message you have to send to the people you want to poll. \n" +"Now, you have to send this message to everyone you want to poll." +msgstr "" +"Dies ist die Nachricht, die Sie an die Personen, die Sie zur Umfrage einladen möchten, schicken sollen. \n" +"Schicken Sie jetzt bitte diese Nachricht an alle Personen, die Sie zur Umfrage einladen möchten." + +msgid "hast just created a poll called" +msgstr " hat eine Umfrage erstellt - Name folgt: " + +msgid "Thanks for filling the poll at the link above" +msgstr "Danke, dass Sie die Umfrage unter dem obrigen Link ausgefüllt haben" + +msgid "" +"This message should NOT be sent to the polled people. It is private for the poll's creator.\n" +"\n" +"You can now modify it at the link above" +msgstr "" +"Diese Nachricht sollte NICHT an die befragten Personen gesendet werden. Sie nur für den Autor der Umfrage gemeint.\n" +"\n" +"Sie können die Umfrage unter dem oberen Link bearbeiten " + +msgid "Author's message" +msgstr "Nachricht vom Autor " + +msgid "For sending to the polled users" +msgstr "Nachricht für die Teilnehmer" diff --git a/locale/en_GB/LC_MESSAGES/Studs.mo b/locale/en_GB/LC_MESSAGES/Studs.mo index b21ecdc..2646d04 100644 Binary files a/locale/en_GB/LC_MESSAGES/Studs.mo and b/locale/en_GB/LC_MESSAGES/Studs.mo differ diff --git a/locale/en_GB/LC_MESSAGES/Studs.po b/locale/en_GB/LC_MESSAGES/Studs.po index e22f5c9..d084ea4 100644 --- a/locale/en_GB/LC_MESSAGES/Studs.po +++ b/locale/en_GB/LC_MESSAGES/Studs.po @@ -66,8 +66,8 @@ msgstr "(in the format name@mail.com)" msgid "Description" msgstr "Description" -msgid "Back to the homepage of " -msgstr "Back to the homepage of " +msgid "Back to the homepage of" +msgstr "Back to the homepage of" msgid "Error!" msgstr "Error!" @@ -81,9 +81,6 @@ msgstr "dd/mm/yyyy" msgid "%A, den %e. %B %Y" msgstr "%A, den %e. %B %Y" -msgid "Expiration's date" -msgstr "Expiration's date" - msgid "days" msgstr "days" @@ -199,14 +196,23 @@ msgstr "Cancel the title edit" msgid "Initiator of the poll" msgstr "Initiator of the poll" +msgid "Edit the name" +msgstr "Edit the name" + +msgid "Save the new name" +msgstr "Save the new name" + +msgid "Cancel the name edit" +msgstr "Cancel the name edit" + msgid "Email" msgstr "Email" msgid "Edit the email adress" msgstr "Edit the email adress" -msgid "Save the email address " -msgstr "Save the email address " +msgid "Save the email address" +msgstr "Save the email address" msgid "Cancel the email address edit" msgstr "Cancel the email address edit" @@ -226,6 +232,18 @@ msgstr "Public link of the poll" msgid "Admin link of the poll" msgstr "Admin link of the poll" +msgid "Expiration's date" +msgstr "Expiration's date" + +msgid "Edit the expiration's date" +msgstr "Edit the expiration's date" + +msgid "Save the new expiration's date" +msgstr "Save the new expiration's date" + +msgid "Cancel the expiration's date edit" +msgstr "Cancel the expiration's date edit" + msgid "Poll rules" msgstr "Poll rules" @@ -247,15 +265,18 @@ msgstr "Save the new rules" msgid "Cancel the rules edit" msgstr "Cancel the rules edit" +msgid "The name is invalid." +msgstr "Le nom n'est pas valide." + # Help text adminstuds.php -msgid "As poll administrator, you can change all the lines of this poll with this button " -msgstr "As poll administrator, you can change all the lines of this poll with this button " +msgid "As poll administrator, you can change all the lines of this poll with this button" +msgstr "As poll administrator, you can change all the lines of this poll with this button" -msgid " remove a column or a line with " -msgstr " remove a column or a line with " +msgid "remove a column or a line with" +msgstr "remove a column or a line with" -msgid "and add a new column with " -msgstr "and add a new column with " +msgid "and add a new column with" +msgstr "and add a new column with" msgid "Finally, you can change the informations of this poll like the title, the comments or your email address." msgstr "Finally, you can change the informations of this poll like the title, the comments or your email address." @@ -437,8 +458,8 @@ msgstr "Go to step 2" msgid "Enter a title" msgstr "Enter a title" -msgid "Characters < > and \" are not permitted" -msgstr "Characters < > and \" are not permitted" +msgid "Something is wrong with the format" +msgstr "Something is wrong with the format" msgid "Enter an email address" msgstr "Enter an email address" @@ -461,8 +482,8 @@ msgstr "Poll dates (2 on 3)" msgid "Choose the dates of your poll" msgstr "Choose the dates of your poll" -msgid "To schedule an event, it's better to propose at least two choices (two hours for one day or two days)." -msgstr "To schedule an event, it's better to propose at least two choices (two hours for one day or two days)." +msgid "To schedule an event you need to propose at least two choices (two hours for one day or two days)." +msgstr "To schedule an event you need to propose at least two choices (two hours for one day or two days)." msgid "You can add or remove additionnal days and hours with the buttons" msgstr "You can add or remove additionnal days and hours with the buttons" @@ -501,8 +522,8 @@ msgstr "Remove all hours" msgid "Poll subjects (2 on 3)" msgstr "Poll subjects (2 on 3)" -msgid "To make a generic poll, it's better to propose at least two choices between differents subjects." -msgstr "To make a generic poll, it's better to propose at least two choices between differents subjects." +msgid "To make a generic poll you need to propose at least two choices between differents subjects." +msgstr "To make a generic poll you need to propose at least two choices between differents subjects." msgid "You can add or remove additional choices with the buttons" msgstr "You can add or remove additional choices with the buttons" @@ -576,15 +597,18 @@ msgstr "Removal date:" msgid "Your poll will be automatically removed after" msgstr "Your poll will be automatically removed after" -msgid "You can fix another removal date for it." -msgstr "You can fix another removal date for it." +msgid "You can set a closer removal date for it." +msgstr "You can set a closer removal date for it." msgid "Removal date (optional)" msgstr "Removal date (optional)" ############# Admin ############# -msgid "Polls administrator" -msgstr "Polls administrator" +msgid "Polls" +msgstr "Polls" + +msgid "Migration" +msgstr "Migration" msgid "Confirm removal of the poll " msgstr "Confirm removal of the poll " @@ -619,16 +643,54 @@ msgstr "Change the poll" msgid "Logs" msgstr "Logs" +msgid "Summary" +msgstr "Summary" + +msgid "Success" +msgstr "Success" + +msgid "Fail" +msgstr "Fail" + +msgid "Nothing" +msgstr "Nothing" + +msgid "Succeeded:" +msgstr "Succeeded:" + +msgid "Failed:" +msgstr "Failed:" + +msgid "Skipped:" +msgstr "Skipped:" + +msgid "Pages:" +msgstr "Pages:" + ########### Mails ########### # Mails studs.php msgid "Poll's participation" msgstr "Poll's participation" msgid "" -"has filled a line.\n" +"filled a vote.\n" "You can find your poll at the link" msgstr "" -"has filled a line.\n" +"filled a vote.\n" +"You can find your poll at the link" + +msgid "" +"updated a vote.\n" +"You can find your poll at the link" +msgstr "" +"updated a vote.\n" +"You can find your poll at the link" + +msgid "" +"wrote a comment.\n" +"You can find your poll at the link" +msgstr "" +"wrote a comment.\n" "You can find your poll at the link" msgid "Thanks for your confidence." diff --git a/locale/es_ES/LC_MESSAGES/Studs.mo b/locale/es_ES/LC_MESSAGES/Studs.mo index 54fc228..d742a11 100644 Binary files a/locale/es_ES/LC_MESSAGES/Studs.mo and b/locale/es_ES/LC_MESSAGES/Studs.mo differ diff --git a/locale/es_ES/LC_MESSAGES/Studs.po b/locale/es_ES/LC_MESSAGES/Studs.po index 0a0ba51..6633139 100644 --- a/locale/es_ES/LC_MESSAGES/Studs.po +++ b/locale/es_ES/LC_MESSAGES/Studs.po @@ -130,7 +130,7 @@ msgstr "Usted no habia llenado la primera pagina dela encuesta" #: choix_autre.php:63 #: adminstuds.php:79 #: adminstuds.php:1044 -msgid "Back to the homepage of " +msgid "Back to the homepage of" msgstr "Retroceder al inicio de" #: choix_date.php:220 @@ -255,8 +255,8 @@ msgstr "Introducza un título" #: infos_sondage.php:133 #: infos_sondage.php:138 #: infos_sondage.php:150 -msgid "Characters < > and \" are not permitted" -msgstr "Los caracteres < > y \" no estan autorizados!" +msgid "Something is wrong with the format" +msgstr "Something is wrong with the format" #: infos_sondage.php:136 msgid "Comments: " @@ -393,12 +393,26 @@ msgstr "Participación a la encuesta" #: studs.php:171 #: studs.php:211 msgid "" -"has filled a line.\n" +"filled a vote.\n" "You can find your poll at the link" msgstr "" "acaba de llenar una línea.\n" "Usted puede retroceder a su encuesta con el enlace siguiente" +msgid "" +"updated a vote.\n" +"You can find your poll at the link" +msgstr "" +"updated a vote.\n" +"Usted puede retroceder a su encuesta con el enlace siguiente" + +msgid "" +"wrote a comment.\n" +"You can find your poll at the link" +msgstr "" +"wrote a comment.\n" +"Usted puede retroceder a su encuesta con el enlace siguiente" + #: studs.php:246 #: adminstuds.php:567 msgid "Initiator of the poll" @@ -526,7 +540,7 @@ msgid "Characters \" < and > are not permitted" msgstr "Los caracteres \" < y > no estan autorizados!" #: choix_autre.php:191 -msgid "Your poll will be automatically removed after 6 months.
    You can fix another removal date for it." +msgid "Your poll will be automatically removed after 6 months.
    You can set a closer removal date for it." msgstr "Su encuesta será automaticamente borrado dentro de 6 meses.
    Mientras, usted puede cambiar este fecha aquí." #: choix_autre.php:193 @@ -612,8 +626,8 @@ msgstr "" "Usted puede cambiar su encuesta al enlace siguiente" #: adminstuds.php:582 -msgid "As poll administrator, you can change all the lines of this poll with this button : " -msgstr "En calidad de administrador, Usted puede cambiar todas la líneas de este encuesta con este botón :" +msgid "As poll administrator, you can change all the lines of this poll with this button" +msgstr "En calidad de administrador, Usted puede cambiar todas la líneas de este encuesta con este botón" msgid "Edit" msgstr "Cambio" diff --git a/locale/fr_FR/LC_MESSAGES/Studs.mo b/locale/fr_FR/LC_MESSAGES/Studs.mo index ea335f1..0c460f9 100644 Binary files a/locale/fr_FR/LC_MESSAGES/Studs.mo and b/locale/fr_FR/LC_MESSAGES/Studs.mo differ diff --git a/locale/fr_FR/LC_MESSAGES/Studs.po b/locale/fr_FR/LC_MESSAGES/Studs.po index 74af27d..7cd490e 100644 --- a/locale/fr_FR/LC_MESSAGES/Studs.po +++ b/locale/fr_FR/LC_MESSAGES/Studs.po @@ -66,7 +66,7 @@ msgstr "(au format nom@mail.com)" msgid "Description" msgstr "Description" -msgid "Back to the homepage of " +msgid "Back to the homepage of" msgstr "Retourner à la page d'accueil de" msgid "Error!" @@ -81,9 +81,6 @@ msgstr "jj/mm/aaaa" msgid "%A, den %e. %B %Y" msgstr "%A %e %B %Y" -msgid "Expiration's date" -msgstr "Date d'expiration" - msgid "days" msgstr "jours" @@ -199,13 +196,22 @@ msgstr "Annuler le changement de titre" msgid "Initiator of the poll" msgstr "Auteur du sondage" +msgid "Edit the name" +msgstr "Modification de l'auteur" + +msgid "Save the new name" +msgstr "Enregistrer l'auteur" + +msgid "Cancel the name edit" +msgstr "Annuler le changement d'auteur" + msgid "Email" msgstr "Courriel" msgid "Edit the email adress" msgstr "Modifier le courriel" -msgid "Save the email address " +msgid "Save the email address" msgstr "Enregistrer le courriel" msgid "Cancel the email address edit" @@ -226,6 +232,18 @@ msgstr "Lien public du sondage" msgid "Admin link of the poll" msgstr "Lien d'administration du sondage" +msgid "Expiration's date" +msgstr "Date d'expiration" + +msgid "Edit the expiration's date" +msgstr "Modifier la date d'expiration" + +msgid "Save the new expiration's date" +msgstr "Enregistrer la date d'expiration" + +msgid "Cancel the expiration's date edit" +msgstr "Annuler le changement de date d'expiration" + msgid "Poll rules" msgstr "Permissions du sondage" @@ -247,15 +265,18 @@ msgstr "Enregistrer les nouvelles permissions" msgid "Cancel the rules edit" msgstr "Annuler le changement de permissions" +msgid "The name is invalid." +msgstr "Le nom n'est pas valide." + # Help text adminstuds.php -msgid "As poll administrator, you can change all the lines of this poll with this button " -msgstr "En tant qu'administrateur, vous pouvez modifier toutes les lignes de ce sondage avec ce bouton " +msgid "As poll administrator, you can change all the lines of this poll with this button" +msgstr "En tant qu'administrateur, vous pouvez modifier toutes les lignes de ce sondage avec ce bouton" -msgid " remove a column or a line with " -msgstr " effacer une colonne ou une ligne avec " +msgid "remove a column or a line with" +msgstr "effacer une colonne ou une ligne avec" -msgid "and add a new column with " -msgstr "et si vous avez oublié de saisir un choix, vous pouvez rajouter une colonne en cliquant sur " +msgid "and add a new column with" +msgstr "et si vous avez oublié de saisir un choix, vous pouvez rajouter une colonne en cliquant sur" msgid "Finally, you can change the informations of this poll like the title, the comments or your email address." msgstr "Vous pouvez enfin également modifier les informations relatives à ce sondage comme le titre, les commentaires ou encore votre courriel." @@ -437,8 +458,8 @@ msgstr "Aller à l'étape 2" msgid "Enter a title" msgstr "Il faut saisir un titre !" -msgid "Characters < > and \" are not permitted" -msgstr "Les caractères < > et \" ne sont pas autorisés !" +msgid "Something is wrong with the format" +msgstr "Quelque chose ne va pas avec le format" msgid "Enter an email address" msgstr "Il faut saisir une adresse électronique !" @@ -461,8 +482,8 @@ msgstr "Choix des dates (2 sur 3)" msgid "Choose the dates of your poll" msgstr "Choisissez les dates de votre sondage" -msgid "To schedule an event, it's better to propose at least two choices (two hours for one day or two days)." -msgstr "Pour créer un sondage spécial dates, il est préférable de proposer au moins deux choix (deux horaires pour une même journée ou deux jours)." +msgid "To schedule an event you need to propose at least two choices (two hours for one day or two days)." +msgstr "Pour créer un sondage spécial dates vous devez proposer au moins deux choix (deux horaires pour une même journée ou deux jours)." msgid "You can add or remove additionnal days and hours with the buttons" msgstr "Vous pouvez ajouter ou supprimer des jours et horaires supplémentaires avec les boutons" @@ -501,8 +522,8 @@ msgstr "Effacer tous les horaires" msgid "Poll subjects (2 on 3)" msgstr "Choix des sujets (2 sur 3)" -msgid "To make a generic poll, it's better to propose at least two choices between differents subjects." -msgstr "Pour créer un sondage classique, il est préférable de proposer au moins deux choix différents." +msgid "To make a generic poll you need to propose at least two choices between differents subjects." +msgstr "Pour créer un sondage classique, vous devez proposer au moins deux choix différents." msgid "You can add or remove additional choices with the buttons" msgstr "Vous pouvez ajouter ou supprimer des choix supplémentaires avec les boutons" @@ -576,15 +597,18 @@ msgstr "Date de suppression :" msgid "Your poll will be automatically removed after" msgstr "Votre sondage sera automatiquement effacé dans" -msgid "You can fix another removal date for it." -msgstr "Néanmoins vous pouvez décider ci-dessous d'une date plus rapprochée pour la suppression de votre sondage." +msgid "You can set a closer removal date for it." +msgstr "Vous pouvez décider d'une date de suppression plus proche." msgid "Removal date (optional)" -msgstr "Date de suppression (facultative)" +msgstr "Date de fin (facultative)" ############# Admin ############# -msgid "Polls administrator" -msgstr "Administrateur de la base" +msgid "Polls" +msgstr "Sondages" + +msgid "Migration" +msgstr "Migration" msgid "Confirm removal of the poll " msgstr "Confirmer la suppression du sondage " @@ -619,16 +643,54 @@ msgstr "Modifier le sondage" msgid "Logs" msgstr "Historique" +msgid "Summary" +msgstr "Résumé" + +msgid "Success" +msgstr "Réussite" + +msgid "Fail" +msgstr "Échèc" + +msgid "Nothing" +msgstr "Rien" + +msgid "Succeeded:" +msgstr "Réussit:" + +msgid "Failed:" +msgstr "Échoué:" + +msgid "Skipped:" +msgstr "Passé:" + +msgid "Pages:" +msgstr "Pages :" + ########### Mails ########### # Mails studs.php msgid "Poll's participation" msgstr "Participation au sondage" msgid "" -"has filled a line.\n" +"filled a vote.\n" "You can find your poll at the link" msgstr "" -" vient de remplir une ligne.\n" +"vient de voter.\n" +"Vous pouvez retrouver votre sondage avec le lien suivant" + +msgid "" +"updated a vote.\n" +"You can find your poll at the link" +msgstr "" +"vient de mettre à jour un vote.\n" +"Vous pouvez retrouver votre sondage avec le lien suivant" + +msgid "" +"vient de rédiger un commentaire.\n" +"You can find your poll at the link" +msgstr "" +"wrote a comment.\n" "Vous pouvez retrouver votre sondage avec le lien suivant" msgid "Thanks for your confidence." diff --git a/studs.php b/studs.php index db63ea2..ddfc2b3 100644 --- a/studs.php +++ b/studs.php @@ -16,694 +16,192 @@ * Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) */ -namespace Framadate; - -session_start(); - -if (file_exists('bandeaux_local.php')) { - include_once('bandeaux_local.php'); -} else { - include_once('bandeaux.php'); -} +use Framadate\Services\LogService; +use Framadate\Services\PollService; +use Framadate\Services\InputService; +use Framadate\Services\MailService; +use Framadate\Message; +use Framadate\Utils; include_once __DIR__ . '/app/inc/init.php'; -// Le fichier studs.php sert a afficher les résultats d'un sondage à un simple utilisateur. -// C'est également l'interface pour ajouter une valeur à un sondage deja créé. -$numsondage = false; +/* Constants */ +/* --------- */ +const UPDATE_VOTE = 1; +const ADD_VOTE = 2; +const ADD_COMMENT = 3; -//On récupère le numéro de sondage par le lien web. -if(Utils::issetAndNoEmpty('sondage', $_GET) === true) { - $numsondage = $_GET["sondage"]; - $_SESSION["numsondage"] = $numsondage; -} +/* Variables */ +/* --------- */ -if(Utils::issetAndNoEmpty('sondage') === true) { - $numsondage = $_POST["sondage"]; - $_SESSION["numsondage"] = $numsondage; -} elseif(Utils::issetAndNoEmpty('sondage', $_COOKIE) === true) { - $numsondage = $_COOKIE["sondage"]; -} elseif(Utils::issetAndNoEmpty('numsondage', $_SESSION) === true) { - $numsondage = $_SESSION["numsondage"]; -} +$poll_id = null; +$poll = null; +$message = null; +$editingVoteId = 0; -$dsondage = ($numsondage != false) ? Utils::get_sondage_from_id($numsondage) : false; -if (!$dsondage || $dsondage->id_sondage == ''){ - Utils::print_header( _("Error!")); +/* Services */ +/*----------*/ - bandeau_titre(_("Error!")); +$logService = new LogService(); +$pollService = new PollService($connect, $logService); +$inputService = new InputService(); +$mailService = new MailService($config['use_smtp']); - echo ' -
    -

    ' . _("This poll doesn't exist !") . '

    -

    ' . _('Back to the homepage of ') . ' ' . NOMAPPLICATION . '

    -
    '."\n"; +/* Functions */ +/*-----------*/ - bandeau_pied(); - - die(); -} - -//output a CSV and die() -if(Utils::issetAndNoEmpty('export', $_GET) && $dsondage !== false) { - if($_GET['export'] == 'csv') { - require_once('exportcsv.php'); +/** + * Send a notification to the poll admin to notify him about an update. + * + * @param $poll stdClass The poll + * @param $mailService MailService The mail service + * @param $name string The name user who triggered the notification + * @param $type int cf: Constants on the top of this page + */ +function sendUpdateNotification($poll, $mailService, $name, $type) { + if (!isset($_SESSION['mail_sent'])) { + $_SESSION['mail_sent'] = []; } - die(); -} + if ($poll->receiveNewVotes && (!isset($_SESSION['mail_sent'][$poll->id]) || $_SESSION['mail_sent'][$poll->id] !== true)) { -// quand on ajoute un commentaire utilisateur -if(isset($_POST['ajoutcomment'])) { - if (isset($_SESSION['nom']) && Utils::issetAndNoEmpty('commentuser') === false) { - // Si le nom vient de la session, on le de-htmlentities - $comment_user = html_entity_decode($_SESSION['nom'], ENT_QUOTES, 'UTF-8'); - } elseif(Utils::issetAndNoEmpty('commentuser')) { - $comment_user = $_POST["commentuser"]; - } elseif(isset($_POST["commentuser"])) { - $err |= COMMENT_USER_EMPTY; - } else { - $comment_user = _('anonyme'); - } + $subject = '[' . NOMAPPLICATION . '] ' . _('Poll\'s participation') . ' : ' . $poll->title; - if(Utils::issetAndNoEmpty('comment') === false) { - $err |= COMMENT_EMPTY; - } - - if (isset($_POST["comment"]) && !Utils::is_error(COMMENT_EMPTY) && !Utils::is_error(NO_POLL) && !Utils::is_error(COMMENT_USER_EMPTY)) { - // protection contre les XSS : htmlentities - $comment = htmlentities($_POST['comment'], ENT_QUOTES, 'UTF-8'); - $comment_user = htmlentities($comment_user, ENT_QUOTES, 'UTF-8'); - - // Check for doublons - $comment_doublon = false; - $req = 'SELECT * FROM comments WHERE id_sondage='.$connect->Param('numsondage').' ORDER BY id_comment'; - $sql = $connect->Prepare($req); - $comment_user_doublon = $connect->Execute($sql, array($numsondage)); - if ($comment_user_doublon->RecordCount() != 0) { - while ( $dcomment_user_doublon=$comment_user_doublon->FetchNextObject(false)) { - if($dcomment_user_doublon->comment == $comment && $dcomment_user_doublon->usercomment == $comment_user) { - $comment_doublon = true; - }; - } + $message = $name . ' '; + switch ($type) { + case UPDATE_VOTE: + $message .= _('updated a vote.\nYou can find your poll at the link') . " :\n\n"; + break; + case ADD_VOTE: + $message .= _('filled a vote.\nYou can find your poll at the link') . " :\n\n"; + break; + case ADD_COMMENT: + $message .= _('wrote a comment.\nYou can find your poll at the link') . " :\n\n"; + break; } + $message .= Utils::getUrlSondage($poll->admin_id, true) . "\n\n"; + $message .= _('Thanks for your confidence.') . "\n" . NOMAPPLICATION; - if(!$comment_doublon) { - $req = 'INSERT INTO comments (id_sondage, comment, usercomment) VALUES ('. - $connect->Param('id_sondage').','. - $connect->Param('comment').','. - $connect->Param('comment_user').')'; - $sql = $connect->Prepare($req); + $mailService->send($poll->admin_mail, $subject, $message); - $comments = $connect->Execute($sql, array($numsondage, $comment, $comment_user)); - if ($comments === false) { - $err |= COMMENT_INSERT_FAILED; - } - } + $_SESSION['mail_sent'][$poll->id] = true; } } +/* PAGE */ +/* ---- */ -// Action quand on clique le bouton participer -$sql = 'SELECT * FROM user_studs WHERE id_sondage='.$connect->Param('numsondage').' ORDER BY id_users'; -$sql = $connect->Prepare($sql); -$user_studs = $connect->Execute($sql, array($numsondage)); - -$nbcolonnes = substr_count($dsondage->sujet, ',') + 1; -if (!Utils::is_error(NO_POLL) && (isset($_POST["boutonp"]))) { - //Si le nom est bien entré - if (Utils::issetAndNoEmpty('nom') === false) { - $err |= NAME_EMPTY; - } - - if(!Utils::is_error(NAME_EMPTY) && (! ( USE_REMOTE_USER && isset($_SERVER['REMOTE_USER']) ) || $_POST["nom"] == $_SESSION["nom"])) { - $nouveauchoix = ''; - for ($i=0;$i<$nbcolonnes;$i++) { - // radio checked 1 = Yes, 2 = Ifneedbe, 0 = No - if (isset($_POST["choix$i"])) { - switch ($_POST["choix$i"]) { - case 1: $nouveauchoix .= "1";break; - case 2: $nouveauchoix .= "2";break; - default: $nouveauchoix .= "0";break; - } - } - } - - $nom=substr($_POST["nom"],0,64); - - // protection contre les XSS : htmlentities - $nom = htmlentities($nom, ENT_QUOTES, 'UTF-8'); - - while($user = $user_studs->FetchNextObject(false)) { - if ($nom == $user->nom) { - $err |= NAME_TAKEN; - } - } - - // Ecriture des choix de l'utilisateur dans la base - if (!Utils::is_error(NAME_TAKEN) && !Utils::is_error(NAME_EMPTY)) { - - $sql = 'INSERT INTO user_studs (nom,id_sondage,reponses) VALUES ('. - $connect->Param('nom').', '. - $connect->Param('numsondage').', '. - $connect->Param('nouveauchoix').')'; - $sql = $connect->Prepare($sql); - - // Todo : Il faudrait lever une erreur en cas d'erreur d'insertion - $connect->Execute($sql, array($nom, $numsondage, $nouveauchoix)); - - if ($dsondage->mailsonde || /* compatibility for non boolean DB */ $dsondage->mailsonde=="yes" || $dsondage->mailsonde=="true") { - if($config['use_smtp']==true){ - Utils::sendEmail( "$dsondage->mail_admin", - "[".NOMAPPLICATION."] "._("Poll's participation")." : ".html_entity_decode($dsondage->titre, ENT_QUOTES, 'UTF-8')."", - html_entity_decode("\"$nom\" ", ENT_QUOTES, 'UTF-8'). - _("has filled a line.\nYou can find your poll at the link") . " :\n\n". - Utils::getUrlSondage($numsondage) . " \n\n" . - _("Thanks for your confidence.") . "\n". NOMAPPLICATION ); - } - } - } - } else { - $err |= NAME_EMPTY; - } +if (!empty($_GET['poll'])) { + $poll_id = filter_input(INPUT_GET, 'poll', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); + $poll = $pollService->findById($poll_id); } -if($err != 0) { - Utils::print_header(_("Error!").' - '.$dsondage->titre); - bandeau_titre(_("Error!")); - - echo '
      '."\n"; - - if(Utils::is_error(NAME_EMPTY)) { - echo '
    • ' . _("Enter a name") . "
    • \n"; - } - if(Utils::is_error(NAME_TAKEN)) { - echo '
    • ' . _("The name you've chosen already exist in this poll!") . "
    • \n"; - } - if(Utils::is_error(COMMENT_EMPTY) || Utils::is_error(COMMENT_USER_EMPTY)) { - echo '
    • ' . _("Enter a name and a comment!") . "
    • \n"; - } - if(Utils::is_error(COMMENT_INSERT_FAILED) ) { - echo '
    • ' . _("Failed to insert the comment!") . "
    • \n"; - } - - echo '
    '; - -} else { - Utils::print_header(_('Poll').' - '.$dsondage->titre); - bandeau_titre(_('Poll').' - '.$dsondage->titre); +if (!$poll) { + $smarty->assign('error', _('This poll doesn\'t exist !')); + $smarty->display('error.tpl'); + exit; } -$title=stripslashes(str_replace("\\","",$dsondage->titre)); -echo ' -
    -
    -
    -

    '.$title.'

    -
    -
    -
    - - -
    -
    -
    -
    -
    -
    -

    '. _("Initiator of the poll") .'

    -

    '.stripslashes($dsondage->nom_admin).'

    -
    - -
    '."\n"; +// ------------------------------- +// A vote is going to be edited +// ------------------------------- -//affichage de la description du sondage -if ($dsondage->commentaires) { - $commentaires = $dsondage->commentaires; - $commentaires=nl2br(str_replace("\\","",$commentaires)); - echo ' -
    -

    '._("Description") .'


    -

    '. $commentaires .'

    -
    '; -} -echo ' -
    -
    '."\n"; // .jumbotron - -//On récupere les données et les sujets du sondage -$nblignes = $user_studs->RecordCount(); - -//on teste pour voir si une ligne doit etre modifiée -$testmodifier = false; -$ligneamodifier = -1; -for ($i=0;$i<$nblignes;$i++) { - if (isset($_POST["modifierligne$i"])) { - $ligneamodifier = $i; - } - - //test pour voir si une ligne est a modifier - if (isset($_POST['validermodifier'.$i])) { - $modifier = $i; - $testmodifier = true; - } +if (!empty($_POST['edit_vote'])) { + $editingVoteId = filter_input(INPUT_POST, 'edit_vote', FILTER_VALIDATE_INT); } -//si le test est valide alors on affiche des checkbox pour entrer de nouvelles valeurs -if ($testmodifier) { - $nouveauchoix = ''; - for ($i=0;$i<$nbcolonnes;$i++) { - // radio checked 1 = Yes, 2 = Ifneedbe, 0 = No - if (isset($_POST["choix$i"])) { - switch ($_POST["choix$i"]) { - case 1: $nouveauchoix .= "1";break; - case 2: $nouveauchoix .= "2";break; - default: $nouveauchoix .= "0";break; - } - } +// ------------------------------- +// Something to save (edit or add) +// ------------------------------- + +if (!empty($_POST['save'])) { // Save edition of an old vote + $name = filter_input(INPUT_POST, 'name', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => NAME_REGEX]]); + $editedVote = filter_input(INPUT_POST, 'save', FILTER_VALIDATE_INT); + $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]); + + if (empty($editedVote)) { + $message = new Message('danger', _('Something is going wrong...')); + } + if (count($choices) != count($_POST['choices'])) { + $message = new Message('danger', _('There is a problem with your choices.')); } - $compteur=0; - while ($data = $user_studs->FetchNextObject(false) ) { - //mise a jour des données de l'utilisateur dans la base SQL - if ($compteur == $modifier) { - $sql = 'UPDATE user_studs SET reponses='.$connect->Param('nouveauchoix').' WHERE nom='.$connect->Param('nom').' AND id_users='.$connect->Param('id_users'); - $sql = $connect->Prepare($sql); - $connect->Execute($sql, array($nouveauchoix, $data->nom, $data->id_users)); - - if ($dsondage->mailsonde=="yes") { - Utils::sendEmail( "$dsondage->mail_admin", "[".NOMAPPLICATION."] " . _("Poll's participation") . " : ".html_entity_decode($dsondage->titre, ENT_QUOTES, 'UTF-8'), "\"".html_entity_decode($data->nom, ENT_QUOTES, 'UTF-8')."\""."" . _("has filled a line.\nYou can find your poll at the link") . " :\n\n" . Utils::getUrlSondage($numsondage) . " \n\n" . _("Thanks for your confidence.") . "\n".NOMAPPLICATION ); - } - } - $compteur++; - } -} - -//recuperation des utilisateurs du sondage -$sql = 'SELECT * FROM user_studs WHERE id_sondage='.$connect->Param('numsondage').' ORDER BY id_users'; -$sql = $connect->Prepare($sql); -$user_studs = $connect->Execute($sql, array($numsondage)); - -//reformatage des données des sujets du sondage -$toutsujet = explode(",",$dsondage->sujet); - -// Table headers -$thead = ''; - -// Button in the first td to avoid remove col on "Return" keypress) -$border = array(); // bordure pour distinguer les mois -$td_headers = array(); // for a11y, headers="M1 D4 H5" on each td -$radio_title = array(); // date for - -// Dates poll -if ($dsondage->format=="D"||$dsondage->format=="D+"||$dsondage->format=="D-") { - - $tr_months = ''; - $tr_days = ''; - $tr_hours = ''; - - // Headers - $colspan_month = 1; - $colspan_day = 1; - - for ($i = 0; $i < count($toutsujet); $i++) { - - // Current date - $current = $toutsujet[$i]; - $horoCur = explode("@",$current); //horoCur[0] = date, horoCur[1] = hour - if (isset($toutsujet[$i+1])){ - $next = $toutsujet[$i+1]; - $horoNext = explode("@",$next); - } - - $border[$i] = false; - $radio_title[$i] = strftime($date_format['txt_short'],$horoCur[0]); - - // Months - $td_headers[$i] = 'M'.($i+1-$colspan_month); - - if (isset($toutsujet[$i+1]) && strftime("%B", $horoCur[0]) == strftime("%B", $horoNext[0]) && strftime("%Y", $horoCur[0]) == strftime("%Y", $horoNext[0])){ - $colspan_month++; + if ($message == null) { + // Update vote + $result = $pollService->updateVote($poll_id, $editedVote, $name, $choices); + if ($result) { + $message = new Message('success', _('Update vote successfully.')); + sendUpdateNotification($poll, $mailService, $name, UPDATE_VOTE); } else { - $border[$i] = true; - $tr_months .= ''.strftime("%B",$horoCur[0]).' '.strftime("%Y", $horoCur[0]).''; - $colspan_month=1; + $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' => NAME_REGEX]]); + $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]); - // Days - $td_headers[$i] .= ' D'.($i+1-$colspan_day); + 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 (isset($toutsujet[$i+1]) && strftime($date_format['txt_day'],$horoCur[0])==strftime($date_format['txt_day'],$horoNext[0])&&strftime("%B",$horoCur[0])==strftime("%B",$horoNext[0])){ - $colspan_day++; + if ($message == null) { + // Add vote + $result = $pollService->addVote($poll_id, $name, $choices); + if ($result) { + $message = new Message('success', _('Update vote successfully.')); + sendUpdateNotification($poll, $mailService, $name, ADD_VOTE); } else { - $rbd = ($border[$i]) ? ' rbd' : ''; - $tr_days .= ''.strftime($date_format['txt_day'],$horoCur[0]).''; - $colspan_day=1; + $message = new Message('danger', _('Update vote failed.')); } + } +} - // Hours - $rbd = ($border[$i]) ? ' rbd' : ''; - if (isset($horoCur[1]) && $horoCur[1] !== '') { - $tr_hours .= ''.$horoCur[1].''; - $radio_title[$i] .= ' - '.$horoCur[1]; - $td_headers[$i] .= ' H'.$i; +// ------------------------------- +// Add a comment +// ------------------------------- + +if (isset($_POST['add_comment'])) { + $name = filter_input(INPUT_POST, 'name', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => NAME_REGEX]]); + $comment = strip_tags($_POST['comment']); + + if (empty($name)) { + $message = new Message('danger', _('Name is incorrect.')); + } + + if ($message == null) { + // Add comment + $result = $pollService->addComment($poll_id, $name, $comment); + if ($result) { + $message = new Message('success', _('Comment added.')); + sendUpdateNotification($poll, $mailService, $name, ADD_COMMENT); } else { - $tr_hours .= ''; + $message = new Message('danger', _('Comment failed.')); } } - $border[count($border)-1] = false; // suppression de la bordure droite du dernier mois - - $tr_months .= ''; - $tr_days .= ''; - $tr_hours .= ''; - - $thead = "\n".$tr_months."\n".$tr_days."\n".$tr_hours."\n"; - -// Subjects poll -} else { - $toutsujet=str_replace("@","
    ",$toutsujet); - - $tr_subjects = ''; - - for ($i = 0; isset($toutsujet[$i]); $i++) { - - $td_headers[$i]='';$radio_title[$i]=''; // init before concatenate - - // Subjects - preg_match_all('/\[!\[(.*?)\]\((.*?)\)\]\((.*?)\)/',$toutsujet[$i],$md_a_img); // Markdown [![alt](src)](href) - preg_match_all('/!\[(.*?)\]\((.*?)\)/',$toutsujet[$i],$md_img); // Markdown ![alt](src) - preg_match_all('/\[(.*?)\]\((.*?)\)/',$toutsujet[$i],$md_a); // Markdown [text](href) - if (isset($md_a_img[2][0]) && $md_a_img[2][0]!='' && isset($md_a_img[3][0]) && $md_a_img[3][0]!='') { // [![alt](src)](href) - - $th_subject_text = (isset($md_a_img[1][0]) && $md_a_img[1][0]!='') ? stripslashes($md_a_img[1][0]) : _("Choice") .' '.($i+1); - $th_subject_html = ''.$th_subject_text.''; - - } elseif (isset($md_img[2][0]) && $md_img[2][0]!='') { // ![alt](src) - - $th_subject_text = (isset($md_img[1][0]) && $md_img[1][0]!='') ? stripslashes($md_img[1][0]) : _("Choice") .' '.($i+1); - $th_subject_html = ''.$th_subject_text.''; - - } elseif (isset($md_a[2][0]) && $md_a[2][0]!='') { // [text](href) - - $th_subject_text = (isset($md_a[1][0]) && $md_a[1][0]!='') ? stripslashes($md_a[1][0]) : _("Choice") .' '.($i+1); - $th_subject_html = ''.$th_subject_text.''; - - } else { // text only - - $th_subject_text = stripslashes($toutsujet[$i]); - $th_subject_html = $th_subject_text; - - } - $tr_subjects .= ''.$th_subject_html.''; - - $border[$i] = false; - $td_headers[$i] .= 'S'.$i; - $radio_title[$i] .= $th_subject_text; - - } - - $thead = $tr_subjects.''; } -// Print headers -echo ' -
    - -'; -if ($dsondage->format=="A-" || $dsondage->format=="D-") { - echo ' -
    -

    ' . _("The administrator locked this poll, votes and comments are frozen, it's not possible to participate anymore.") . '

    - -
    '; -} else { - echo ' -
    -

    ' . _("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.") . '

    - -
    '; -} -echo' - +// Retrieve data +$slots = $pollService->allSlotsByPollId($poll_id); +$votes = $pollService->allVotesByPollId($poll_id); +$comments = $pollService->allCommentsByPollId($poll_id); -

    '._('Votes of the poll ').'

    -
    - - - '. $thead . ' - '; -// Print poll results +// Assign data to template +$smarty->assign('poll_id', $poll_id); +$smarty->assign('poll', $poll); +$smarty->assign('title', _('Poll') . ' - ' . $poll->title); +$smarty->assign('expired', $poll->end_date < time()); +$smarty->assign('deletion_date', $poll->end_date + PURGE_DELAY * 86400); +$smarty->assign('slots', $poll->format === 'D' ? $pollService->splitSlots($slots) : $slots); +$smarty->assign('votes', $pollService->splitVotes($votes)); +$smarty->assign('best_choices', $pollService->computeBestChoices($votes)); +$smarty->assign('comments', $comments); +$smarty->assign('editingVoteId', $editingVoteId); +$smarty->assign('message', $message); +$smarty->assign('admin', false); -//Usager pré-authentifié dans la liste? -$user_mod = false; - -//affichage des resultats actuels -$somme[] = 0; -$compteur = 0; - -while ($data = $user_studs->FetchNextObject(false)) { - - $ensemblereponses = $data->reponses; - - //affichage du nom - $nombase=str_replace("°","'",$data->nom); - echo ' -'."\n"; - - // ligne d'un usager pré-authentifié - $mod_ok = !( USE_REMOTE_USER && isset($_SERVER['REMOTE_USER']) ) || ($nombase == $_SESSION['nom']); - $user_mod |= $mod_ok; - - // pour chaque colonne - for ($k=0; $k < $nbcolonnes; $k++) { - // on remplace les choix de l'utilisateur par une ligne de checkbox pour recuperer de nouvelles valeurs - if ($compteur == $ligneamodifier) { - - $car = substr($ensemblereponses, $k , 1); - - // variable pour afficher la valeur cochée - $car_html[0]='value="0"';$car_html[1]='value="1"';$car_html[2]='value="2"'; - switch ($car) { - case "1": $car_html[1]='value="1" checked';break; - case "2": $car_html[2]='value="2" checked';break; - default: $car_html[0]='value="0" checked';break; - } - - echo ' - '."\n"; - - } else { - $rbd = ($border[$k]) ? ' rbd' : ''; - $car = substr($ensemblereponses, $k, 1); - switch ($car) { - case "1": echo ''."\n"; - if (isset($somme[$k]) === false) { - $somme[$k] = 0; - } - $somme[$k]++; break; - case "2": echo ''."\n"; break; - default: echo ''."\n"; - } - } - } - - //a la fin de chaque ligne se trouve les boutons modifier - if ($compteur != $ligneamodifier && ($dsondage->format=="A+"||$dsondage->format=="D+") && $mod_ok) { - echo ' - '."\n"; - } - - //demande de confirmation pour modification de ligne - for ($i=0;$i<$nblignes;$i++) { - if (isset($_POST["modifierligne$i"])) { - if ($compteur == $i) { - echo ''."\n"; - } - } - } - - $compteur++; - echo ''."\n"; -} - -// affichage de la ligne pour un nouvel utilisateur -if (( !(USE_REMOTE_USER && isset($_SERVER['REMOTE_USER'])) || !$user_mod) && $ligneamodifier==-1 && ($dsondage->format!="A-" && $dsondage->format!="D-")) { - //affichage de la case vide de texte pour un nouvel utilisateur - echo ' -'."\n"; - - //une ligne de checkbox pour le choix du nouvel utilisateur - for ($i = 0; $i < $nbcolonnes; $i++) { - echo ' - '."\n"; - } - - // Affichage du bouton de formulaire pour inscrire un nouvel utilisateur dans la base - echo ' -'."\n"; - -} - -// Addition and Best choice -//affichage de la ligne contenant les sommes de chaque colonne -$tr_addition = ''; -$meilleurecolonne = max($somme); -$compteursujet = 0; -$meilleursujet = '
      '; -for ($i = 0; $i < $nbcolonnes; $i++) { - if (isset($somme[$i]) && $somme[$i] > 0 ) { - if (in_array($i, array_keys($somme, max($somme)))){ - - $tr_addition .= '
    '; - - $meilleursujet.= '
  • '.$radio_title[$i].'
  • '; - $compteursujet++; - - } else { - $tr_addition .= ''; - } - } else { - $tr_addition .= ''; - } -} -$tr_addition .= ''; - -$meilleursujet = str_replace("°", "'", $meilleursujet).''; -$vote_str = ($meilleurecolonne > 1) ? $vote_str = _('votes') : _('vote'); - -// Print Addition and Best choice -echo $tr_addition.' - -
    '._('Votes of the poll ').$title.'
    '.stripslashes($nombase).' -
      -
    • - - -
    • -
    • - - -
    • -
    • - - -
    • -
    -
    ' . _('Yes') . '() ' . _('Yes') . _(', ifneedbe') . '' . _('No') . ' - -
    -
    - - -
    -
    -
      -
    • - - -
    • -
    • - - -
    • -
    • - - -
    • -
    -
    '. _("Addition") .''.$somme[$i].''.$somme[$i].'
    -
    -
    '."\n"; - -if ($compteursujet == 1) { - echo ' -

    ' . _("Best choice") . '

    -
    -

    ' . _("The best choice at this time is:") . '

    - ' . $meilleursujet . ' -

    ' . _("with") . ' ' . $meilleurecolonne . ' ' . $vote_str . '.

    -
    '."\n"; -} elseif ($compteursujet > 1) { - echo ' -

    ' . _("Best choices") . '

    -
    -

    ' . _("The bests choices at this time are:") . '

    - ' . $meilleursujet . ' -

    ' . _("with") . ' ' . $meilleurecolonne . ' ' . $vote_str . '.

    -
    '."\n"; -} - -echo ' -
    -
    '; - -// Comments -$sql = 'select * from comments where id_sondage='.$connect->Param('numsondage').' order by id_comment'; -$sql = $connect->Prepare($sql); -$comment_user=$connect->Execute($sql, array($numsondage)); - -if ($comment_user->RecordCount() != 0) { - echo '

    ' . _("Comments of polled people") . '

    '."\n"; - - while($dcomment = $comment_user->FetchNextObject(false)) { - echo ' -
    - '.stripslashes($dcomment->usercomment). ' : - ' . stripslashes(nl2br($dcomment->comment)) . ' -
    '; - } - - echo '
    '; -} - -if ($dsondage->format!="A-" && $dsondage->format!="D-") { -echo ' -
    -
    -
    ' . _("Add a comment in the poll") . ' -
    -

    -
    -
    -


    -

    -
    -

    -
    -
    -
    -
    '; -} - -echo ' -
    '; - -bandeau_pied(); +$smarty->display('studs.tpl'); diff --git a/tpl/add_slot.tpl b/tpl/add_slot.tpl new file mode 100644 index 0000000..40e23a6 --- /dev/null +++ b/tpl/add_slot.tpl @@ -0,0 +1,39 @@ +{extends file='page.tpl'} + +{block name=main} +
    +
    +

    {_('Column\'s adding')}

    + + {if $format === 'D'} +
    + +
    +
    + + +
    + {_('(dd/mm/yyyy)')} +
    +
    +
    + +
    + +
    +
    + {else} +
    + +
    + +
    +
    + {/if} +
    + + +
    +
    +
    +{/block} \ No newline at end of file diff --git a/tpl/admin/admin_page.tpl b/tpl/admin/admin_page.tpl new file mode 100644 index 0000000..2fb2f77 --- /dev/null +++ b/tpl/admin/admin_page.tpl @@ -0,0 +1,10 @@ +{extends 'page.tpl'} + +{block 'main'} + + {block 'admin_main'}{/block} +{/block} \ No newline at end of file diff --git a/tpl/admin/index.tpl b/tpl/admin/index.tpl new file mode 100644 index 0000000..a2453d3 --- /dev/null +++ b/tpl/admin/index.tpl @@ -0,0 +1,20 @@ +{extends 'admin/admin_page.tpl'} + +{block 'main'} +
    + + + + {if $logsAreReadable} + + {/if} +
    +{/block} \ No newline at end of file diff --git a/tpl/admin/logs.tpl b/tpl/admin/logs.tpl new file mode 100644 index 0000000..9855291 --- /dev/null +++ b/tpl/admin/logs.tpl @@ -0,0 +1,5 @@ +{extends 'admin/admin_page.tpl'} + +{block 'admin_main'} +
    {$logs|html}
    +{/block} diff --git a/tpl/admin/migration.tpl b/tpl/admin/migration.tpl new file mode 100644 index 0000000..1d904bf --- /dev/null +++ b/tpl/admin/migration.tpl @@ -0,0 +1,39 @@ +{extends 'admin/admin_page.tpl'} + +{block 'admin_main'} +
    +
    +

    {_('Summary')}

    + {_('Succeeded:')} {$countSucceeded|html} / {$countTotal|html} +
    + {_('Failed:')} {$countFailed|html} / {$countTotal|html} +
    + {_('Skipped:')} {$countSkipped|html} / {$countTotal|html} +
    +
    +

    {_('Success')}

    +
      + {foreach $success as $s} +
    • {$s|html}
    • + {foreachelse} +
    • {_('Nothing')}
    • + {/foreach} +
    +
    + +
    +

    {_('Fail')}

    +
      + {foreach $fail as $f} +
    • {$f|html}
    • + {foreachelse} +
    • {_('Nothing')}
    • + {/foreach} +
    +
    + +
    + {_('Page generated in')} {$time} {_('secondes')} +
    +
    +{/block} \ No newline at end of file diff --git a/tpl/admin/polls.tpl b/tpl/admin/polls.tpl new file mode 100644 index 0000000..9da7819 --- /dev/null +++ b/tpl/admin/polls.tpl @@ -0,0 +1,75 @@ +{extends 'admin/admin_page.tpl'} + +{block 'admin_main'} +
    + + {if $poll_to_delete} +
    +

    {_("Confirm removal of the poll ")}"{$poll_to_delete->id|html}"

    + +

    + + +

    +
    + {/if} + +
    +
    + {$polls|count} / {$count} {_('polls in the database at this time')} +
    + + + + + + + + + + + + + + {foreach $polls as $poll} + + + + + + + {if strtotime($poll->end_date) > time()} + + {else} + + {/if} + + + + + + + {/foreach} +
    {_('Title')}{_('Author')}{_('Email')}{_('Expiration\'s date')}{_('Users')}{_('Poll ID')}{_('Actions')}
    + {if $poll->format === 'D'} + {_('Date')} + {else} + {_('Classic')} + {/if} + {$poll->title|html}{$poll->admin_name|html}{$poll->admin_mail|html}{date('d/m/y', strtotime($poll->end_date))}{strtotime($poll->end_date)|date_format:'d/m/Y'}{$poll->votes|html}{$poll->id|html}{_('See the poll')}{_('Change the poll')}
    + +
    + {_('Pages:')} + {for $p=1 to $pages} + {if $p===$page} + {$p} + {else} + {$p} + {/if} + {/for} +
    +
    +
    +{/block} \ No newline at end of file diff --git a/tpl/admin/purge.tpl b/tpl/admin/purge.tpl new file mode 100644 index 0000000..d36553d --- /dev/null +++ b/tpl/admin/purge.tpl @@ -0,0 +1,13 @@ +{extends 'admin/admin_page.tpl'} + +{block 'admin_main'} + {if $message} + + {/if} +
    + +
    + +
    +
    +{/block} \ No newline at end of file diff --git a/tpl/confirm/delete_comments.tpl b/tpl/confirm/delete_comments.tpl new file mode 100644 index 0000000..bbc6a67 --- /dev/null +++ b/tpl/confirm/delete_comments.tpl @@ -0,0 +1,11 @@ +{extends file='page.tpl'} + +{block name=main} +
    +
    +

    {_('Confirm removal of all comments of the poll')}

    +

    +

    +
    +
    +{/block} \ No newline at end of file diff --git a/tpl/confirm/delete_poll.tpl b/tpl/confirm/delete_poll.tpl new file mode 100644 index 0000000..e2cbbe5 --- /dev/null +++ b/tpl/confirm/delete_poll.tpl @@ -0,0 +1,11 @@ +{extends file='page.tpl'} + +{block name=main} +
    +
    +

    {_('Confirm removal of your poll')}

    +

    +

    +
    +
    +{/block} \ No newline at end of file diff --git a/tpl/confirm/delete_votes.tpl b/tpl/confirm/delete_votes.tpl new file mode 100644 index 0000000..d807201 --- /dev/null +++ b/tpl/confirm/delete_votes.tpl @@ -0,0 +1,11 @@ +{extends file='page.tpl'} + +{block name=main} +
    +
    +

    {_('Confirm removal of all votes of the poll')}

    +

    +

    +
    +
    +{/block} \ No newline at end of file diff --git a/tpl/error.tpl b/tpl/error.tpl new file mode 100644 index 0000000..1c7452a --- /dev/null +++ b/tpl/error.tpl @@ -0,0 +1,8 @@ +{extends file='page.tpl'} + +{block name=main} +
    +

    {$error|html}

    +

    {_('Back to the homepage of')} {$APPLICATION_NAME|html}

    +
    +{/block} diff --git a/tpl/footer.tpl b/tpl/footer.tpl new file mode 100644 index 0000000..0313ca5 --- /dev/null +++ b/tpl/footer.tpl @@ -0,0 +1,4 @@ + +
    + + \ No newline at end of file diff --git a/tpl/head.tpl b/tpl/head.tpl new file mode 100644 index 0000000..3b8bbac --- /dev/null +++ b/tpl/head.tpl @@ -0,0 +1,29 @@ + + + + + + {if !empty($title)} + {$title|html} - {$APPLICATION_NAME|html} + {else} + {$APPLICATION_NAME|html} + {/if} + + + + + + + + + + + + + {if !empty($nav_js)} + + {/if} + + + +
    \ No newline at end of file diff --git a/tpl/header.tpl b/tpl/header.tpl new file mode 100644 index 0000000..1fa06c2 --- /dev/null +++ b/tpl/header.tpl @@ -0,0 +1,21 @@ +
    + {if count($langs)>1} +
    +
    + + + + +
    +
    + {/if} + +

    {$APPLICATION_NAME|html}

    + {if !empty($title)}

    {$title|html}

    {/if} + +
    +
    \ No newline at end of file diff --git a/tpl/page.tpl b/tpl/page.tpl new file mode 100644 index 0000000..025864a --- /dev/null +++ b/tpl/page.tpl @@ -0,0 +1,6 @@ +{include file='head.tpl'} +{include file='header.tpl'} + +{block name=main}{/block} + +{include file='footer.tpl'} \ No newline at end of file diff --git a/tpl/part/comments.tpl b/tpl/part/comments.tpl new file mode 100644 index 0000000..5923cc9 --- /dev/null +++ b/tpl/part/comments.tpl @@ -0,0 +1,40 @@ + +
    + + {* Comment list *} + + {if $comments|count > 0} +

    {_("Comments of polled people")}

    + {foreach $comments as $comment} +
    + {if $admin && !$expired} + + {/if} + {$comment->name|html}  + {nl2br($comment->comment|html)} +
    + {/foreach} + {/if} + + {* Add comment form *} + {if $active && !$expired} +
    +
    +
    {_("Add a comment to the poll")} +
    + + +
    +
    + + +
    +
    + +
    +
    +
    +
    +
    + {/if} +
    \ No newline at end of file diff --git a/tpl/part/poll_hint.tpl b/tpl/part/poll_hint.tpl new file mode 100644 index 0000000..341a9f1 --- /dev/null +++ b/tpl/part/poll_hint.tpl @@ -0,0 +1,11 @@ +{if $active} +
    +

    {_("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.")}

    + +
    +{else} +
    +

    {_("The administrator locked this poll, votes and comments are frozen, it's not possible to participate anymore.")}

    + +
    +{/if} \ No newline at end of file diff --git a/tpl/part/poll_hint_admin.tpl b/tpl/part/poll_hint_admin.tpl new file mode 100644 index 0000000..2b7c1c3 --- /dev/null +++ b/tpl/part/poll_hint_admin.tpl @@ -0,0 +1,7 @@ +
    +

    {_('As poll administrator, you can change all the lines of this poll with this button')} {_('Edit')}, + {_('remove a column or a line with')} {_('Remove')} + {_('and add a new column with')} {_('Add a column')}.

    +

    {_('Finally, you can change the informations of this poll like the title, the comments or your email address.')}

    + +
    \ No newline at end of file diff --git a/tpl/part/poll_info.tpl b/tpl/part/poll_info.tpl new file mode 100644 index 0000000..360e09a --- /dev/null +++ b/tpl/part/poll_info.tpl @@ -0,0 +1,160 @@ +{$admin = $admin|default:false} + +{if $admin}
    {/if} +
    +
    +
    +

    {$poll->title|html}{if $admin && !$expired} {/if}

    + {if $admin && !$expired} + + {/if} +
    +
    +
    + + {_('Export to CSV')} + {if $admin && !$expired} + + + {/if} +
    +
    +
    +
    +
    +

    {_('Initiator of the poll')}

    +

    {$poll->admin_name|html}{if $admin && !$expired} {/if}

    + {if $admin && !$expired} + + {/if} +
    +
    +
    + {if $admin} +
    +
    +

    {$poll->admin_mail|html}{if !$expired} {/if}

    + {if !$expired} + + {/if} +
    +
    + {/if} +
    +

    {_("Description")}{if $admin && !$expired} {/if}

    +

    {$poll->description|html}

    + {if $admin && !$expired} + + {/if} +
    +
    + +
    + + {if $admin} + +
    +

    {_('Expiration\'s date')}

    +

    {$poll->end_date|date_format:$date_format['txt_date']|html}{if !$expired} {/if}

    + {if !$expired} + + {/if} +
    + {/if} +
    + {if $admin} +
    +
    +
    + {if $poll->active} + {if $poll->editable} + {$rule_id = 2} + {$rule_icon = ''} + {$rule_txt = _('Votes are editable')} + {else} + {$rule_id = 1} + {$rule_icon = ''} + {$rule_txt = _('Votes and comments are open')} + {/if} + {else} + {$rule_id = 0} + {$rule_icon = ''} + {$rule_txt = _('Votes and comments are locked')} + {/if} +

    {$rule_icon} {$rule_txt|html}{if !$expired} {/if}

    + {if !$expired} + + {/if} +
    +
    +
    + {/if} +
    +{if $admin}
    {/if} diff --git a/tpl/part/vote_table_classic.tpl b/tpl/part/vote_table_classic.tpl new file mode 100644 index 0000000..c6dc236 --- /dev/null +++ b/tpl/part/vote_table_classic.tpl @@ -0,0 +1,196 @@ +{if !is_array($best_choices) || empty($best_choices)} + {$best_choices = [0]} +{/if} + +

    {_('Votes of the poll')}

    + +
    +
    + + + + {if $admin && !$expired} + + + {foreach $slots as $id=>$slot} + + {/foreach} + + + {/if} + + + {foreach $slots as $id=>$slot} + + {/foreach} + + + + + {foreach $votes as $vote} + + {* Edited line *} + + {if $editingVoteId == $vote->id} + + + + {foreach $vote->choices as $id=>$choice} + + + {/foreach} + + {else} + + {* Voted line *} + + + + {foreach $vote->choices as $id=>$choice} + + {if $choice==2} + + {elseif $choice==1} + + {else} + + {/if} + + {/foreach} + + {if $active && $poll->editable && !$expired} + + {else} + + {/if} + {/if} + + {/foreach} + + {* Line to add a new vote *} + + {if $active && $editingVoteId == 0 && !$expired} + + + {foreach $slots as $id=>$slot} + + {/foreach} + + + {/if} + + {* Line displaying best moments *} + {$count_bests = 0} + {$max = max($best_choices)} + {if $max > 0} + + + {foreach $best_choices as $best_choice} + {if $max == $best_choice} + {$count_bests = $count_bests +1} + + {else} + + {/if} + {/foreach} + + {/if} + +
    {_('Votes of the poll')} {$poll->title|html}
    + + + +
    {$slot->title|html|markdown}
    +
    + + +
    +
    +
      +
    • + + +
    • +
    • + + +
    • +
    • + + +
    • +
    +
    {$vote->name|html}{_('Yes')}(){_('Ifneedbe')}{_('No')} + + {if $admin} + + {/if} +
    +
    + + +
    +
    +
      +
    • + + +
    • +
    • + + +
    • +
    • + + +
    • +
    +
    {_("Addition")}{$best_choice|html}{$best_choice|html}
    +
    +
    + +{* Best votes listing *} + +{$max = max($best_choices)} +{if $max > 0} +
    + {if $count_bests == 1} +

    {_("Best choice")}

    +
    +

    {_('The best choice at this time is:')}

    + {elseif $count_bests > 1} +

    {_("Best choices")}

    +
    +

    {_('The bests choices at this time are:')}

    + {/if} + + + {$i = 0} +
      + {foreach $slots as $slot} + {if $best_choices[$i] == $max} +
    • {$slot->title|html|markdown:true}
    • + {/if} + {$i = $i+1} + {/foreach} +
    +

    {_('with')} {$max|html} {if $max==1}{_('vote')}{else}{_('votes')}{/if}.

    +
    +
    +{/if} \ No newline at end of file diff --git a/tpl/part/vote_table_date.tpl b/tpl/part/vote_table_date.tpl new file mode 100644 index 0000000..3343243 --- /dev/null +++ b/tpl/part/vote_table_date.tpl @@ -0,0 +1,246 @@ +{if !is_array($best_choices) || empty($best_choices)} + {$best_choices = [0]} +{/if} + +

    {_('Votes of the poll')}

    + +
    +
    + + + + {if $admin && !$expired} + + + {$headersDCount=0} + {foreach $slots as $slot} + {foreach $slot->moments as $id=>$moment} + + {$headersDCount = $headersDCount+1} + {/foreach} + {/foreach} + + + {/if} + + + {$count_same = 0} + {$previous = 0} + {foreach $slots as $id=>$slot} + {$display = $slot->day|date_format:$date_format.txt_year_month|html} + {if $previous !== 0 && $previous != $display} + + {$count_same = 0} + {/if} + + {$count_same = $count_same + $slot->moments|count} + + {if $slot@last} + + {/if} + + {$previous = $display} + + {for $foo=0 to ($slot->moments|count)-1} + {append var='headersM' value=$id} + {/for} + {/foreach} + + + + + {foreach $slots as $id=>$slot} + + {for $foo=0 to ($slot->moments|count)-1} + {append var='headersD' value=$id} + {/for} + {/foreach} + + + + + {$headersDCount=0} + {foreach $slots as $slot} + {foreach $slot->moments as $id=>$moment} + + {append var='headersH' value=$headersDCount} + {$headersDCount = $headersDCount+1} + {/foreach} + {/foreach} + + + + + {foreach $votes as $vote} + + {* Edited line *} + + {if $editingVoteId == $vote->id && !$expired} + + + + {foreach $vote->choices as $k=>$choice} + + + {/foreach} + + {else} + + {* Voted line *} + + + + {foreach $vote->choices as $k=>$choice} + + {if $choice==2} + + {elseif $choice==1} + + {else} + + {/if} + + {/foreach} + + {if $active && $poll->editable && !$expired} + + {else} + + {/if} + {/if} + + {/foreach} + + {* Line to add a new vote *} + + {if $active && $editingVoteId == 0 && !$expired} + + + {$i = 0} + {foreach $slots as $slot} + {foreach $slot->moments as $moment} + + {$i = $i+1} + {/foreach} + {/foreach} + + + {/if} + + {* Line displaying best moments *} + {$count_bests = 0} + {$max = max($best_choices)} + {if $max > 0} + + + {foreach $best_choices as $best_moment} + {if $max == $best_moment} + {$count_bests = $count_bests +1} + + {else} + + {/if} + {/foreach} + + {/if} + +
    {_('Votes of the poll')} {$poll->title|html}
    + + + +
    {$previous}{$display}
    {$slot->day|date_format:$date_format.txt_day|html}
    {$moment|html}
    +
    + + +
    +
    +
      +
    • + + +
    • +
    • + + +
    • +
    • + + +
    • +
    +
    {$vote->name|html}{_('Yes')}(){_('Ifneedbe')}{_('No')} + + {if $admin} + + {/if} +
    +
    + + +
    +
    +
      +
    • + + +
    • +
    • + + +
    • +
    • + + +
    • +
    +
    {_("Addition")}{$best_moment|html}{$best_moment|html}
    +
    +
    + +{* Best votes listing *} + +{$max = max($best_choices)} +{if $max > 0} +
    + {if $count_bests == 1} +

    {_('Best choice')}

    +
    +

    {_('The best choice at this time is:')}

    + {elseif $count_bests > 1} +

    {_('Best choices')}

    +
    +

    {_('The bests choices at this time are:')}

    + {/if} + + + {$i = 0} +
      + {foreach $slots as $slot} + {foreach $slot->moments as $moment} + {if $best_choices[$i] == $max} +
    • {$slot->day|date_format:$date_format.txt_full|html} - {$moment|html}
    • + {/if} + {$i = $i+1} + {/foreach} + {/foreach} +
    +

    {_('with')} {$max|html} {if $max==1}{_('vote')}{else}{_('votes')}{/if}.

    +
    +
    +{/if} \ No newline at end of file diff --git a/tpl/poll_deleted.tpl b/tpl/poll_deleted.tpl new file mode 100644 index 0000000..f0b46a2 --- /dev/null +++ b/tpl/poll_deleted.tpl @@ -0,0 +1,8 @@ +{extends file='page.tpl'} + +{block name=main} +
    +

    {_("Your poll has been removed!")}

    +

    {_('Back to the homepage of')} {$APPLICATION_NAME|html}

    +
    +{/block} \ No newline at end of file diff --git a/tpl/studs.tpl b/tpl/studs.tpl new file mode 100644 index 0000000..c4280fe --- /dev/null +++ b/tpl/studs.tpl @@ -0,0 +1,52 @@ +{extends file='page.tpl'} + +{block name=main} + + {if !empty($message)} + + {/if} + +{* Global informations about the current poll *} + +{include 'part/poll_info.tpl' admin=$admin} + +{* Information about voting *} +{if $expired} +
    +

    {_('The poll is expired, it will be deleted soon.')}

    +

    {_('Deletion date:')} {$deletion_date|date_format:$date_format['txt_short']|html}

    +
    +{else} + {if $admin} + {include 'part/poll_hint_admin.tpl'} + {else} + {include 'part/poll_hint.tpl' active=$poll->active} + {/if} +{/if} + +{* Scroll left and right *} + + + +{* Vote table *} + +{if $poll->format === 'D'} + {include 'part/vote_table_date.tpl' active=$poll->active} +{else} + {include 'part/vote_table_classic.tpl' active=$poll->active} +{/if} + +{* Comments *} + +{include 'part/comments.tpl' active=$poll->active comments=$comments} + +{/block} \ No newline at end of file