forked from tykayn/funky-framadate-front
Restart from scratch
This commit is contained in:
parent
b5581c7127
commit
39242f22db
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,5 +0,0 @@
|
|||||||
tpl_c/*.php
|
|
||||||
vendor/
|
|
||||||
|
|
||||||
po/*.po
|
|
||||||
po/*.json
|
|
@ -1,20 +0,0 @@
|
|||||||
image: framasoft/framadate-ci
|
|
||||||
|
|
||||||
pages:
|
|
||||||
stage: deploy
|
|
||||||
script:
|
|
||||||
- mkdir "${HOME}/.ssh"
|
|
||||||
- chmod 700 "${HOME}/.ssh"
|
|
||||||
# The following is stupid but required for some reason
|
|
||||||
- mkdir .public
|
|
||||||
- cp -r * .public
|
|
||||||
- mv .public public
|
|
||||||
- if [ ! -z ${DEPLOYEMENT_KNOWN_HOSTS+x} ]; then echo -e "${DEPLOYEMENT_KNOWN_HOSTS}" > ${HOME}/.ssh/known_hosts; fi
|
|
||||||
- eval `ssh-agent -s`
|
|
||||||
- if [ ! -z ${DEPLOYEMENT_KEY+x} ]; then ssh-add <(echo "${DEPLOYEMENT_KEY}" | base64 --decode -i); fi
|
|
||||||
- if [ ! -z ${DEPLOYEMENT_KEY+x} ]; then rsync -a --delete --exclude stats/ --exclude error/ public/ ${DEPLOYEMENT_USER}@${DEPLOYEMENT_HOST}:../../web/; fi
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- public
|
|
||||||
only:
|
|
||||||
- master
|
|
17
.htaccess
17
.htaccess
@ -1,17 +0,0 @@
|
|||||||
######################
|
|
||||||
# .htaccess example. #
|
|
||||||
######################
|
|
||||||
|
|
||||||
<IfModule mod_rewrite.c>
|
|
||||||
RewriteEngine On
|
|
||||||
RewriteCond %{REQUEST_FILENAME} -f [OR]
|
|
||||||
RewriteCond %{REQUEST_FILENAME} -d
|
|
||||||
RewriteRule . - [L]
|
|
||||||
|
|
||||||
RewriteRule ^([a-zA-Z0-9-]+)$ studs.php?poll=$1 [L]
|
|
||||||
RewriteRule ^([a-zA-Z0-9-]+)/action/([a-zA-Z_-]+)/(.+)$ studs.php?poll=$1&$2=$3
|
|
||||||
RewriteRule ^([a-zA-Z0-9-]+)/vote/([a-zA-Z0-9]{16})$ studs.php?poll=$1&vote=$2
|
|
||||||
RewriteRule ^([a-zA-Z0-9-]{24})/admin$ adminstuds.php?poll=$1
|
|
||||||
RewriteRule ^([a-zA-Z0-9-]{24})/admin/vote/([a-zA-Z0-9]{16})$ adminstuds.php?poll=$1&vote=$2
|
|
||||||
RewriteRule ^([a-zA-Z0-9-]{24})/admin/action/([a-zA-Z_-]+)(/(.+))?$ adminstuds.php?poll=$1&$2=$4
|
|
||||||
</IfModule>
|
|
14
AUTHORS.md
14
AUTHORS.md
@ -1,14 +0,0 @@
|
|||||||
# [Framasoft](http://framadate.org)
|
|
||||||
* Simon Leblanc (development),
|
|
||||||
* Pierre-Yves Gosset (development, graphism)
|
|
||||||
* Pascal Chevrel (development)
|
|
||||||
* Armony Altinier (accessibility)
|
|
||||||
* JosephK (development)
|
|
||||||
* Framasoft community
|
|
||||||
*For a list of people who have contributed to the codebase, see [GitHub's list of contributors](https://github.com/framasoft/OpenSondage/graphs/contributors).*
|
|
||||||
|
|
||||||
## [STUdS](http://studs.u-strasbg.fr)
|
|
||||||
* Guilhem Borghesi (borghesi@unistra.fr)
|
|
||||||
* Raphaël Droz
|
|
||||||
* Contributors from the University of Strasbourg: Guy, Christophe, Julien, Pierre, Romaric, Matthieu, Catherine, Christine, Olivier, Emmanuel and Florence
|
|
||||||
|
|
235
CHANGELOG.md
235
CHANGELOG.md
@ -1,235 +0,0 @@
|
|||||||
This changelog file is **deprecated**. For an up-to-date changelog, please check [the tags](https://framagit.org/framasoft/framadate/tags).
|
|
||||||
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
# Changelog de framadate
|
|
||||||
|
|
||||||
## Version 1.0 (Erik - Markus - Ecmu - Julien - Imre - Luc - Pierre - Antonin - Olivier)
|
|
||||||
- Amélioration : Conserver les votes en cours lors que l'utilisateur envoie un commentaire
|
|
||||||
- Amélioration : Les mails sont envoyés en multipart pour les lecteurs ne supportant pas HTML
|
|
||||||
- Amélioration : Masquer l'encart au dessus du tableau des votes, maintenant visible grâce à un bouton
|
|
||||||
- Amélioration : Les commentaires sont horodatés
|
|
||||||
- Amélioration : Auto wrapping de la description du sondage
|
|
||||||
- Amélioration : Protection de sondages par mots de passe
|
|
||||||
- Amélioration : Un click dans les champs URL sélectionne le contenu
|
|
||||||
- Amélioration : Choix du lien du sondage
|
|
||||||
- Amélioration : Possibilité de modifier un sondage après expiration
|
|
||||||
- Amélioration : Confirmation demandée pour supprimer une colonne
|
|
||||||
- Amélioration : Création d'une sondage par intervale de dates
|
|
||||||
- Amélioration : Possibilité de ne pas faire de choix sur une colonne
|
|
||||||
- Amélioration : Amélioration du format des mails
|
|
||||||
- Amélioration : Amélioration du mode où chaque votant ne peut modifier que son vote
|
|
||||||
- Amélioration : Fichier check.php pour vérifier la possibilité d'installation
|
|
||||||
- Amélioration : Changements de libellés
|
|
||||||
- Amélioration : Admin - Rechercher un sondage grâce à l'adresse mail
|
|
||||||
- Amélioration : Fluidification du défilement de la page
|
|
||||||
- Amélioration : Simplification de l'écran de création de sondage
|
|
||||||
- Fix : Correction de traductions
|
|
||||||
- Fix : Corrections diverses sur les dates et leurs formats
|
|
||||||
- Fix : Impossible d'ajouter une colonne vide
|
|
||||||
- Fix : Possibilité de supprimer des colonnes vides
|
|
||||||
- Fix : Correction du formulaire de commentaires
|
|
||||||
- Fix : Correction d'échappements de caractères
|
|
||||||
- Fix : Rectification des contraintes sur les sondage expirés
|
|
||||||
- Fix : Interdiction d'exporter les résultats lorsque l'utilisateur ne peut pas les voir
|
|
||||||
- Technique : Travail sur le service des notifications
|
|
||||||
- Technique : Prise en compte de l'entête X-Forwarded-Proto
|
|
||||||
- Technique : Utilisation de PHPMailer pour l'envoi de mails
|
|
||||||
- Technique : Encore de la Smartization
|
|
||||||
- Technique : Pas mal de nettoyage de code
|
|
||||||
|
|
||||||
## Version 0.9.6 (goofy-bz - Olivier - Quentin - Vincent)
|
|
||||||
- Fix : Corrections mineures de langues
|
|
||||||
- Amélioration : Nouvelle langue - Occitan
|
|
||||||
- Amélioration : Blocage d'un vote si l'admin a changé les possibilités entre temps
|
|
||||||
|
|
||||||
## Version 0.9.5 (Olivier)
|
|
||||||
- Fix : Corrections mineures de langues
|
|
||||||
- Fix : Correction de la suppresion de votes
|
|
||||||
- Amélioration : Possibilité d'ajouter plus de "moments" à une date
|
|
||||||
|
|
||||||
## Version 0.9.4 (JosephK - Olivier - Nikos)
|
|
||||||
- Fix : Correction de l'échappement des tables Vote et Slot
|
|
||||||
- Fix : Encodage des "actions" en base64 pour fonctionner avec l'UrlRewriting
|
|
||||||
- Fix : Correction d'attributs "title"
|
|
||||||
- Fix : Un seul jour est requis pour faire un sondage
|
|
||||||
- Fix : Correction de l'UrlRewriting
|
|
||||||
- Amélioration : Traduction en Italien
|
|
||||||
|
|
||||||
## Version 0.9.3 (Antonin - Olivier - Nikos)
|
|
||||||
- Fix : Traduction de textes en Italien
|
|
||||||
- Fix : Empêchement de la suppression de la dernière colonne
|
|
||||||
- Fix : Possiblité de supprimer des colonnes contenant des caractères spéciaux (par exemple "&")
|
|
||||||
- Fix : Correction de l'exemple d'URL rewriting (des efforts restent à faire)
|
|
||||||
- Amélioration : (Mode chacun son vote) Possiblité d'éditer son vote directement après un vote
|
|
||||||
- Amélioration : Message plus parlant lors de la création d'une colonne
|
|
||||||
## Version 0.9.2 (Olivier)
|
|
||||||
- Fix : Completion d'un manque de contrôle sur les ID
|
|
||||||
## Version 0.9.1 (JosephK - Olivier - Antonin - Michael - Paul)
|
|
||||||
- Fix : Correction des lenteurs de défilement
|
|
||||||
- Fix : Arrêt du défilement auto à gauche qu'on clique sur un choix
|
|
||||||
- Fix : Traductions Français/Anglais/Allemand
|
|
||||||
- Fix : Fin du tri automatique des colonnes (ex: 10h < 9h)
|
|
||||||
- Fix : Option à la création masquée dans certains cas
|
|
||||||
- Fix : Le nom peut maintenant contenir des caractères spéciaux (ex: , - ')
|
|
||||||
- Fix : Correction mineure de la doc d'installation
|
|
||||||
- Fix : Interdiction du caractère "," dans choix d'un vote
|
|
||||||
- Fix : Correction de la suppression de choix contenant des caractères spéciaux
|
|
||||||
- Fix : Correction du contrôle pour empêcher de supprimer le dernier choix d'un sondage
|
|
||||||
- Fix : Taille du champs "Votre nom" agrandie
|
|
||||||
- Technique : Ajout de logs
|
|
||||||
## Version 0.9 (JosephK - Olivier - Antonin - ...)
|
|
||||||
- Technique : Réorganisation des classes
|
|
||||||
- Technique : Découpage en MVC + Installation de Smarty
|
|
||||||
- Technique : Refonte de l'accès aux données + Remplacement de Adodb par PDO
|
|
||||||
- Technique : Définition claire des couches Service et Repository
|
|
||||||
- Technique : Utilisation de la librairie open source o80-i18n pour la gestion des langue
|
|
||||||
- Amélioration : Refonte de l'administration
|
|
||||||
- Amélioration : Formulaire de recherche pour trouver des sondages
|
|
||||||
- Amélioration : Notification de l'utilisation si JAvascript ou les cookies sont désactivés
|
|
||||||
- Amélioration : Découpage en 2 options pour recevoir ou non les nouveaux vote et commentaires
|
|
||||||
- Amélioration : Utilisation de jetons CSRF sur certaines actions
|
|
||||||
- Amélioration : Nouvelle option de sondage "Chaque participant peut modifier son propre vote"
|
|
||||||
- Amélioration : Nouvelle option de sondage "Vote caché, seul le créateur du sondage peu voir les résultats"
|
|
||||||
- Amélioration : Auto-cmoplétion des champs de dates (15/5 peut devenir 15/05/2015 ou 15/05/2016 en fonction de la date actuelle)
|
|
||||||
- Amélioration : Nouvelle page pour retrouver ses sondages par mail
|
|
||||||
- Amélioration : Mise à jour des fichiers .md pour faciliter la collaboration
|
|
||||||
- Amélioration : Le nom de l'auteur et la date d'expiration sont modifiables
|
|
||||||
- Amélioration : Le nom de vote est modifiable
|
|
||||||
- Amélioration : Affichage du comptage des "Si nécessaire" entre parenthèses
|
|
||||||
- Amélioration : Page d'installation
|
|
||||||
- Fix : Purge en 2 étapes → 1. Verrouillage du sondage → 2. 60 jours plus tard suppression du sondage
|
|
||||||
- Fix : Date d'expiration qui devient nulle quand on ajoute une colonne
|
|
||||||
- Fix : clic/focus sur oui/non/si nécessaire → retour à gauche de la barre de scroll sur Chromium
|
|
||||||
- Fix : Perte de ses votes quand le nom entré n'est pas valide
|
|
||||||
- Fix : Certains sondages sont créé avec un ID déjà existant
|
|
||||||
- Fix : 2 choix minimum sont nécessaires pour créer un sondage
|
|
||||||
- Fix : Ajout de la police d'écriture Déjà Vu
|
|
||||||
- Fix : Mémorisation de la langue entre l'application et l'administration
|
|
||||||
- Fix : Bug à la création d'un sondage sans Javascript ou sans Cookies
|
|
||||||
- Fix : Erreur d'url avec les noms de domaine contenant "admin"
|
|
||||||
- Fix : Mise à jour de la doc d'installation
|
|
||||||
|
|
||||||
## Version 0.8 (juillet 2014 Pascal Chevrel - Armony Altinier - JosephK)
|
|
||||||
- Améliorations sur l'accessibilité
|
|
||||||
- Améliorations sur l'ergonomie
|
|
||||||
- Améliorations sur l'internationalisation (nombreuses phrases en français dans le code)
|
|
||||||
- Découpage chaines de langue pour virer le code html
|
|
||||||
- Remise en place de l'export CSV
|
|
||||||
- Remise en place de get_server_name() pour permettre l'installation dans un sous dossier, en https ou sur un port différent
|
|
||||||
- Ajout Authors.md + en-têtes refaits
|
|
||||||
- Fix bug changement de langues en mode URL rewriting (requête GET passée en formulaire POST)
|
|
||||||
- Fix bug 2 boutons valider lorsqu'on édite un vote
|
|
||||||
- Fix focus javascript sur "Votre nom"
|
|
||||||
- Nettoyage + Bootstrap
|
|
||||||
- Ajout vote Oui/Non/Si nécessaire
|
|
||||||
- Formulaire simplifié pour l'ajout de colonne date (horaire libre)
|
|
||||||
- Restructuration
|
|
||||||
- Fix (partiel) bug modification du premier vote en tapant Entrée
|
|
||||||
|
|
||||||
## Version 0.7 (mars 2013)
|
|
||||||
- Fix : le sondage supprimé n'était pas forcément le sondage sélectionné (cfévrier)
|
|
||||||
- Fix : suppression de STUDS_DIR pour éviter toute confusion
|
|
||||||
- Fix : corrections l'en-tete et de l'encodage des e-mails (cfévrier)
|
|
||||||
- Fix : rend Optionnelle l'utilisation de la variable "REMOTE_USER" (cfévrier)
|
|
||||||
- Amélioration : ne faire apparaitre dans l'admin que les sondage actifs ou expirés depuis x mois (pyg)
|
|
||||||
- Amélioration : ajout d'un champs date_creation dans la table "sondage" (pyg)
|
|
||||||
- Amélioration : permet de faire fonctionner gettext avec le serveur de dev de PHP5.4 + enlève code commenté depuis des années (pascalchevrel)
|
|
||||||
- Fix : enlève les appels à get_server_name() partout sauf dans un appel à sendMail(), réécriture de la fonction pour cet usage (pascalchevrel)
|
|
||||||
- Amélioration : remplacement des define() par des const plus concis (pascalchevrel)
|
|
||||||
- Amélioration : possibilité de faire des liens directs vers les types de sondages à créer (pascalchevrel)
|
|
||||||
- Amélioration : meilleure intégration de la framanav (pyg)
|
|
||||||
- Amélioration : nombreuses modifications CSS pour un meilleur affichage (pyg)
|
|
||||||
|
|
||||||
## Changelog des 22 et 23 juin (pyg@framasoft.net)
|
|
||||||
- très nombreuses modifications CSS
|
|
||||||
- ajout de buttons.css pour des boutons plus propres
|
|
||||||
- ajout de print.css pour une impression sans la classe "corps"
|
|
||||||
- refonte de la page d'accueil
|
|
||||||
- ajout de la framanav
|
|
||||||
- qq retouches dans les fichiers .po
|
|
||||||
- date de destruction passée de 2j à 30j
|
|
||||||
- ajout de l'adresse à transmettre
|
|
||||||
- ajout d'un bouton imprimer
|
|
||||||
- généralisation des stripslashes
|
|
||||||
- fix d'un bug sur une requete (suppression). Reste la seconde partie : https://github.com/leblanc-simon/OpenSondage/issues/8
|
|
||||||
- modification du titre en image
|
|
||||||
- ajout de htmlspecialchars_decode avec param ENT_QUOTES pour l'envoi des emails
|
|
||||||
|
|
||||||
## Changelog du 21 juin 2011 (pyg@framasoft.net)
|
|
||||||
- très nombreuses modifications CSS
|
|
||||||
- modification adminstuds.php : ajout de classes aux formulaires et ajout de stripslashes à l'affichage
|
|
||||||
- modification infos_sondages.php : simplification du tableau de choix, ajouts de CSS, ajouts de labels pour faciliter la selection
|
|
||||||
|
|
||||||
## Changelog version 0.6.7 (mai 2011)
|
|
||||||
- fork du projet STUdS (https://sourcesup.cru.fr/projects/studs/) de la version trunk du 15 mai 2011)
|
|
||||||
- reprise par Simon Leblanc
|
|
||||||
- nettoyage du code (indentation, cohérence de la convention de codage)
|
|
||||||
- suppression des warning php
|
|
||||||
- résolution d'une faille de sécurité par injection SQL
|
|
||||||
- résolution d'une faille de sécurité par injection mail
|
|
||||||
- correction dans le fichier de langue (merci à Julien Reitzel)
|
|
||||||
- possibilité de mettre un texte libre pour les horaires
|
|
||||||
- version Framasoft
|
|
||||||
|
|
||||||
# Les dernières améliorations de STUdS
|
|
||||||
Changelog version 0.6.6 (XXX 2011) :
|
|
||||||
- internationalisation avec gettext
|
|
||||||
- abstraction de la base de données avec ADOdb
|
|
||||||
- support de mysql (fichier d'initialisation disponible)
|
|
||||||
- meilleure compatibilité avec le mode strict de PHP
|
|
||||||
- factorisation de code et de CSS
|
|
||||||
- moins de boutons de formulaire, plus de liens <a href>
|
|
||||||
|
|
||||||
Changelog version 0.6.5 (juin 2010) :
|
|
||||||
- Changement de deux icones dans la creation d'un sondage.
|
|
||||||
|
|
||||||
Changelog version 0.6.4 (mars 2010) :
|
|
||||||
- Corrections de bug
|
|
||||||
|
|
||||||
Changelog version 0.6.3 (janvier 2010) :
|
|
||||||
- Corrections de bug
|
|
||||||
|
|
||||||
Changelog version 0.6.2 (novembre 2009) :
|
|
||||||
- Correction dans l'affichage des bandeaux,
|
|
||||||
- Modification de la partie "A propos",
|
|
||||||
- Préparation à l'authentification,
|
|
||||||
- De UdSification de l'application dans certains fichiers.
|
|
||||||
|
|
||||||
Changelog version 0.6.1 (octobre 2009) :
|
|
||||||
- Corrections d'erreurs dans les traductions et d'oublis de traduction dans certaines pages.
|
|
||||||
|
|
||||||
Changelog version 0.6 (août 2009) :
|
|
||||||
- Mise sous la licence CeCILL-B du code source de STUdS,
|
|
||||||
- Passage de STUdS en encodage UTF8,
|
|
||||||
- Ajout des icones des menus dans toutes les pages et non pas seulement sur la page d'accueil,
|
|
||||||
- Correction d'un bug lors du rajout d'une colonne dans l'interface d'administration des sondages.
|
|
||||||
|
|
||||||
Changelog version 0.5 (février 2009) :
|
|
||||||
- Traduction de STUdS en anglais, allemand et espagnol,
|
|
||||||
- Changement de la CSS avec ajout du logo de l'Université de Strasbourg,
|
|
||||||
- Possibilité d'ajouter un commentaire pour les sondés.
|
|
||||||
|
|
||||||
Changelog version 0.4 (janvier 2009) :
|
|
||||||
- Possibilité de faire un export PDF pour envoyer la lettre de convocation à la date de réunion,
|
|
||||||
- Possibilité de rajouter des colonnes dans la partie administration de sondage,
|
|
||||||
- Correction de bugs d'affichage avec les caractères ' et " .
|
|
||||||
|
|
||||||
Changelog version 0.3 (novembre 2008) :
|
|
||||||
- Possibilité de faire un export CSV pour exploiter le sondage dans un tableur,
|
|
||||||
- Mise en place d'un repository Subversion pour partager les nouvelles versions de STUdS,
|
|
||||||
- Amélioration de la CSS pour un meilleur affichage,
|
|
||||||
- Modification du code source pour le rendre portable vers une autre machine.
|
|
||||||
|
|
||||||
Changelog version 0.2 (novembre 2008) :
|
|
||||||
- Lors de la création d'un sondage DATE, classement des dates par ordre croissant,
|
|
||||||
- Lors de la création d'un sondage DATE, accepter les horaires au format "8h" ou "8H",
|
|
||||||
- Lors de la création d'un sondage DATE, possibilité de copier des horaires entre les dates,
|
|
||||||
- Lors d'une modification de ligne, cocher les cases initialement choisies et non pas des cases vides,
|
|
||||||
- Changement du format d'affichage des dates pour un formatage type : "Mardi 13/06",
|
|
||||||
- Meilleure visualisation des choix les plus votés,
|
|
||||||
- Possibilité pour l'administrateur du sondage de choisir de recevoir un mail d'alerte à chaque participation d'un sondé,
|
|
||||||
- Remplacement des boutons de formulaire par des images moins austères,
|
|
||||||
- Correction de quelques petits bugs d'affichage,
|
|
||||||
- Possibilité de rajouter des cases supplémentaires lors de la création d'un sondage AUTRE,
|
|
||||||
- Possibilité de rajouter des cases supplémentaires lors de la création d'un sondage DATE.
|
|
@ -1,7 +0,0 @@
|
|||||||
# Contributing
|
|
||||||
|
|
||||||
Please report issues on <https://framagit.org/framasoft/framadate/issues>
|
|
||||||
|
|
||||||
If you made a change and want it to be available in official repository, merge requests are welcome!
|
|
||||||
|
|
||||||
Read the [guidelines](https://framagit.org/framasoft/framadate/wikis/coding) to submit your changes.
|
|
@ -1 +0,0 @@
|
|||||||
# [Now available here](https://framagit.org/framasoft/framadate/wikis/home)
|
|
519
LICENCE.fr.txt
519
LICENCE.fr.txt
@ -1,519 +0,0 @@
|
|||||||
CONTRAT DE LICENCE DE LOGICIEL LIBRE CeCILL-B
|
|
||||||
|
|
||||||
|
|
||||||
Avertissement
|
|
||||||
|
|
||||||
Ce contrat est une licence de logiciel libre issue d'une concertation
|
|
||||||
entre ses auteurs afin que le respect de deux grands principes préside à
|
|
||||||
sa rédaction:
|
|
||||||
|
|
||||||
* d'une part, le respect des principes de diffusion des logiciels
|
|
||||||
libres: accès au code source, droits étendus conférés aux
|
|
||||||
utilisateurs,
|
|
||||||
* d'autre part, la désignation d'un droit applicable, le droit
|
|
||||||
français, auquel elle est conforme, tant au regard du droit de la
|
|
||||||
responsabilité civile que du droit de la propriété intellectuelle
|
|
||||||
et de la protection qu'il offre aux auteurs et titulaires des
|
|
||||||
droits patrimoniaux sur un logiciel.
|
|
||||||
|
|
||||||
Les auteurs de la licence CeCILL-B (pour Ce[a] C[nrs] I[nria] L[ogiciel]
|
|
||||||
L[ibre]) sont:
|
|
||||||
|
|
||||||
Commissariat à l'Energie Atomique - CEA, établissement public de
|
|
||||||
recherche à caractère scientifique, technique et industriel, dont le
|
|
||||||
siège est situé 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris.
|
|
||||||
|
|
||||||
Centre National de la Recherche Scientifique - CNRS, établissement
|
|
||||||
public à caractère scientifique et technologique, dont le siège est
|
|
||||||
situé 3 rue Michel-Ange, 75794 Paris cedex 16.
|
|
||||||
|
|
||||||
Institut National de Recherche en Informatique et en Automatique -
|
|
||||||
INRIA, établissement public à caractère scientifique et technologique,
|
|
||||||
dont le siège est situé Domaine de Voluceau, Rocquencourt, BP 105, 78153
|
|
||||||
Le Chesnay cedex.
|
|
||||||
|
|
||||||
|
|
||||||
Préambule
|
|
||||||
|
|
||||||
Ce contrat est une licence de logiciel libre dont l'objectif est de
|
|
||||||
conférer aux utilisateurs une très large liberté de modification et de
|
|
||||||
redistribution du logiciel régi par cette licence.
|
|
||||||
|
|
||||||
L'exercice de cette liberté est assorti d'une obligation forte de
|
|
||||||
citation à la charge de ceux qui distribueraient un logiciel incorporant
|
|
||||||
un logiciel régi par la présente licence afin d'assurer que les
|
|
||||||
contributions de tous soient correctement identifiées et reconnues.
|
|
||||||
|
|
||||||
L'accessibilité au code source et les droits de copie, de modification
|
|
||||||
et de redistribution qui découlent de ce contrat ont pour contrepartie
|
|
||||||
de n'offrir aux utilisateurs qu'une garantie limitée et de ne faire
|
|
||||||
peser sur l'auteur du logiciel, le titulaire des droits patrimoniaux et
|
|
||||||
les concédants successifs qu'une responsabilité restreinte.
|
|
||||||
|
|
||||||
A cet égard l'attention de l'utilisateur est attirée sur les risques
|
|
||||||
associés au chargement, à l'utilisation, à la modification et/ou au
|
|
||||||
développement et à la reproduction du logiciel par l'utilisateur étant
|
|
||||||
donné sa spécificité de logiciel libre, qui peut le rendre complexe à
|
|
||||||
manipuler et qui le réserve donc à des développeurs ou des
|
|
||||||
professionnels avertis possédant des connaissances informatiques
|
|
||||||
approfondies. Les utilisateurs sont donc invités à charger et tester
|
|
||||||
l'adéquation du logiciel à leurs besoins dans des conditions permettant
|
|
||||||
d'assurer la sécurité de leurs systèmes et/ou de leurs données et, plus
|
|
||||||
généralement, à l'utiliser et l'exploiter dans les mêmes conditions de
|
|
||||||
sécurité. Ce contrat peut être reproduit et diffusé librement, sous
|
|
||||||
réserve de le conserver en l'état, sans ajout ni suppression de clauses.
|
|
||||||
|
|
||||||
Ce contrat est susceptible de s'appliquer à tout logiciel dont le
|
|
||||||
titulaire des droits patrimoniaux décide de soumettre l'exploitation aux
|
|
||||||
dispositions qu'il contient.
|
|
||||||
|
|
||||||
|
|
||||||
Article 1 - DEFINITIONS
|
|
||||||
|
|
||||||
Dans ce contrat, les termes suivants, lorsqu'ils seront écrits avec une
|
|
||||||
lettre capitale, auront la signification suivante:
|
|
||||||
|
|
||||||
Contrat: désigne le présent contrat de licence, ses éventuelles versions
|
|
||||||
postérieures et annexes.
|
|
||||||
|
|
||||||
Logiciel: désigne le logiciel sous sa forme de Code Objet et/ou de Code
|
|
||||||
Source et le cas échéant sa documentation, dans leur état au moment de
|
|
||||||
l'acceptation du Contrat par le Licencié.
|
|
||||||
|
|
||||||
Logiciel Initial: désigne le Logiciel sous sa forme de Code Source et
|
|
||||||
éventuellement de Code Objet et le cas échéant sa documentation, dans
|
|
||||||
leur état au moment de leur première diffusion sous les termes du Contrat.
|
|
||||||
|
|
||||||
Logiciel Modifié: désigne le Logiciel modifié par au moins une
|
|
||||||
Contribution.
|
|
||||||
|
|
||||||
Code Source: désigne l'ensemble des instructions et des lignes de
|
|
||||||
programme du Logiciel et auquel l'accès est nécessaire en vue de
|
|
||||||
modifier le Logiciel.
|
|
||||||
|
|
||||||
Code Objet: désigne les fichiers binaires issus de la compilation du
|
|
||||||
Code Source.
|
|
||||||
|
|
||||||
Titulaire: désigne le ou les détenteurs des droits patrimoniaux d'auteur
|
|
||||||
sur le Logiciel Initial.
|
|
||||||
|
|
||||||
Licencié: désigne le ou les utilisateurs du Logiciel ayant accepté le
|
|
||||||
Contrat.
|
|
||||||
|
|
||||||
Contributeur: désigne le Licencié auteur d'au moins une Contribution.
|
|
||||||
|
|
||||||
Concédant: désigne le Titulaire ou toute personne physique ou morale
|
|
||||||
distribuant le Logiciel sous le Contrat.
|
|
||||||
|
|
||||||
Contribution: désigne l'ensemble des modifications, corrections,
|
|
||||||
traductions, adaptations et/ou nouvelles fonctionnalités intégrées dans
|
|
||||||
le Logiciel par tout Contributeur, ainsi que tout Module Interne.
|
|
||||||
|
|
||||||
Module: désigne un ensemble de fichiers sources y compris leur
|
|
||||||
documentation qui permet de réaliser des fonctionnalités ou services
|
|
||||||
supplémentaires à ceux fournis par le Logiciel.
|
|
||||||
|
|
||||||
Module Externe: désigne tout Module, non dérivé du Logiciel, tel que ce
|
|
||||||
Module et le Logiciel s'exécutent dans des espaces d'adressage
|
|
||||||
différents, l'un appelant l'autre au moment de leur exécution.
|
|
||||||
|
|
||||||
Module Interne: désigne tout Module lié au Logiciel de telle sorte
|
|
||||||
qu'ils s'exécutent dans le même espace d'adressage.
|
|
||||||
|
|
||||||
Parties: désigne collectivement le Licencié et le Concédant.
|
|
||||||
|
|
||||||
Ces termes s'entendent au singulier comme au pluriel.
|
|
||||||
|
|
||||||
|
|
||||||
Article 2 - OBJET
|
|
||||||
|
|
||||||
Le Contrat a pour objet la concession par le Concédant au Licencié d'une
|
|
||||||
licence non exclusive, cessible et mondiale du Logiciel telle que
|
|
||||||
définie ci-après à l'article 5 pour toute la durée de protection des droits
|
|
||||||
portant sur ce Logiciel.
|
|
||||||
|
|
||||||
|
|
||||||
Article 3 - ACCEPTATION
|
|
||||||
|
|
||||||
3.1 L'acceptation par le Licencié des termes du Contrat est réputée
|
|
||||||
acquise du fait du premier des faits suivants:
|
|
||||||
|
|
||||||
* (i) le chargement du Logiciel par tout moyen notamment par
|
|
||||||
téléchargement à partir d'un serveur distant ou par chargement à
|
|
||||||
partir d'un support physique;
|
|
||||||
* (ii) le premier exercice par le Licencié de l'un quelconque des
|
|
||||||
droits concédés par le Contrat.
|
|
||||||
|
|
||||||
3.2 Un exemplaire du Contrat, contenant notamment un avertissement
|
|
||||||
relatif aux spécificités du Logiciel, à la restriction de garantie et à
|
|
||||||
la limitation à un usage par des utilisateurs expérimentés a été mis à
|
|
||||||
disposition du Licencié préalablement à son acceptation telle que
|
|
||||||
définie à l'article 3.1 ci dessus et le Licencié reconnaît en avoir pris
|
|
||||||
connaissance.
|
|
||||||
|
|
||||||
|
|
||||||
Article 4 - ENTREE EN VIGUEUR ET DUREE
|
|
||||||
|
|
||||||
|
|
||||||
4.1 ENTREE EN VIGUEUR
|
|
||||||
|
|
||||||
Le Contrat entre en vigueur à la date de son acceptation par le Licencié
|
|
||||||
telle que définie en 3.1.
|
|
||||||
|
|
||||||
|
|
||||||
4.2 DUREE
|
|
||||||
|
|
||||||
Le Contrat produira ses effets pendant toute la durée légale de
|
|
||||||
protection des droits patrimoniaux portant sur le Logiciel.
|
|
||||||
|
|
||||||
|
|
||||||
Article 5 - ETENDUE DES DROITS CONCEDES
|
|
||||||
|
|
||||||
Le Concédant concède au Licencié, qui accepte, les droits suivants sur
|
|
||||||
le Logiciel pour toutes destinations et pour la durée du Contrat dans
|
|
||||||
les conditions ci-après détaillées.
|
|
||||||
|
|
||||||
Par ailleurs, si le Concédant détient ou venait à détenir un ou
|
|
||||||
plusieurs brevets d'invention protégeant tout ou partie des
|
|
||||||
fonctionnalités du Logiciel ou de ses composants, il s'engage à ne pas
|
|
||||||
opposer les éventuels droits conférés par ces brevets aux Licenciés
|
|
||||||
successifs qui utiliseraient, exploiteraient ou modifieraient le
|
|
||||||
Logiciel. En cas de cession de ces brevets, le Concédant s'engage à
|
|
||||||
faire reprendre les obligations du présent alinéa aux cessionnaires.
|
|
||||||
|
|
||||||
|
|
||||||
5.1 DROIT D'UTILISATION
|
|
||||||
|
|
||||||
Le Licencié est autorisé à utiliser le Logiciel, sans restriction quant
|
|
||||||
aux domaines d'application, étant ci-après précisé que cela comporte:
|
|
||||||
|
|
||||||
1. la reproduction permanente ou provisoire du Logiciel en tout ou
|
|
||||||
partie par tout moyen et sous toute forme.
|
|
||||||
|
|
||||||
2. le chargement, l'affichage, l'exécution, ou le stockage du
|
|
||||||
Logiciel sur tout support.
|
|
||||||
|
|
||||||
3. la possibilité d'en observer, d'en étudier, ou d'en tester le
|
|
||||||
fonctionnement afin de déterminer les idées et principes qui sont
|
|
||||||
à la base de n'importe quel élément de ce Logiciel; et ceci,
|
|
||||||
lorsque le Licencié effectue toute opération de chargement,
|
|
||||||
d'affichage, d'exécution, de transmission ou de stockage du
|
|
||||||
Logiciel qu'il est en droit d'effectuer en vertu du Contrat.
|
|
||||||
|
|
||||||
|
|
||||||
5.2 DROIT D'APPORTER DES CONTRIBUTIONS
|
|
||||||
|
|
||||||
Le droit d'apporter des Contributions comporte le droit de traduire,
|
|
||||||
d'adapter, d'arranger ou d'apporter toute autre modification au Logiciel
|
|
||||||
et le droit de reproduire le logiciel en résultant.
|
|
||||||
|
|
||||||
Le Licencié est autorisé à apporter toute Contribution au Logiciel sous
|
|
||||||
réserve de mentionner, de façon explicite, son nom en tant qu'auteur de
|
|
||||||
cette Contribution et la date de création de celle-ci.
|
|
||||||
|
|
||||||
|
|
||||||
5.3 DROIT DE DISTRIBUTION
|
|
||||||
|
|
||||||
Le droit de distribution comporte notamment le droit de diffuser, de
|
|
||||||
transmettre et de communiquer le Logiciel au public sur tout support et
|
|
||||||
par tout moyen ainsi que le droit de mettre sur le marché à titre
|
|
||||||
onéreux ou gratuit, un ou des exemplaires du Logiciel par tout procédé.
|
|
||||||
|
|
||||||
Le Licencié est autorisé à distribuer des copies du Logiciel, modifié ou
|
|
||||||
non, à des tiers dans les conditions ci-après détaillées.
|
|
||||||
|
|
||||||
|
|
||||||
5.3.1 DISTRIBUTION DU LOGICIEL SANS MODIFICATION
|
|
||||||
|
|
||||||
Le Licencié est autorisé à distribuer des copies conformes du Logiciel,
|
|
||||||
sous forme de Code Source ou de Code Objet, à condition que cette
|
|
||||||
distribution respecte les dispositions du Contrat dans leur totalité et
|
|
||||||
soit accompagnée:
|
|
||||||
|
|
||||||
1. d'un exemplaire du Contrat,
|
|
||||||
|
|
||||||
2. d'un avertissement relatif à la restriction de garantie et de
|
|
||||||
responsabilité du Concédant telle que prévue aux articles 8
|
|
||||||
et 9,
|
|
||||||
|
|
||||||
et que, dans le cas où seul le Code Objet du Logiciel est redistribué,
|
|
||||||
le Licencié permette un accès effectif au Code Source complet du
|
|
||||||
Logiciel pendant au moins toute la durée de sa distribution du Logiciel,
|
|
||||||
étant entendu que le coût additionnel d'acquisition du Code Source ne
|
|
||||||
devra pas excéder le simple coût de transfert des données.
|
|
||||||
|
|
||||||
|
|
||||||
5.3.2 DISTRIBUTION DU LOGICIEL MODIFIE
|
|
||||||
|
|
||||||
Lorsque le Licencié apporte une Contribution au Logiciel, le Logiciel
|
|
||||||
Modifié peut être distribué sous un contrat de licence autre que le
|
|
||||||
présent Contrat sous réserve du respect des dispositions de l'article
|
|
||||||
5.3.4.
|
|
||||||
|
|
||||||
|
|
||||||
5.3.3 DISTRIBUTION DES MODULES EXTERNES
|
|
||||||
|
|
||||||
Lorsque le Licencié a développé un Module Externe les conditions du
|
|
||||||
Contrat ne s'appliquent pas à ce Module Externe, qui peut être distribué
|
|
||||||
sous un contrat de licence différent.
|
|
||||||
|
|
||||||
|
|
||||||
5.3.4 CITATIONS
|
|
||||||
|
|
||||||
Le Licencié qui distribue un Logiciel Modifié s'engage expressément:
|
|
||||||
|
|
||||||
1. à indiquer dans sa documentation qu'il a été réalisé à partir du
|
|
||||||
Logiciel régi par le Contrat, en reproduisant les mentions de
|
|
||||||
propriété intellectuelle du Logiciel,
|
|
||||||
|
|
||||||
2. à faire en sorte que l'utilisation du Logiciel, ses mentions de
|
|
||||||
propriété intellectuelle et le fait qu'il est régi par le Contrat
|
|
||||||
soient indiqués dans un texte facilement accessible depuis
|
|
||||||
l'interface du Logiciel Modifié,
|
|
||||||
|
|
||||||
3. à mentionner, sur un site Web librement accessible décrivant le
|
|
||||||
Logiciel Modifié, et pendant au moins toute la durée de sa
|
|
||||||
distribution, qu'il a été réalisé à partir du Logiciel régi par le
|
|
||||||
Contrat, en reproduisant les mentions de propriété intellectuelle
|
|
||||||
du Logiciel,
|
|
||||||
|
|
||||||
4. lorsqu'il le distribue à un tiers susceptible de distribuer
|
|
||||||
lui-même un Logiciel Modifié, sans avoir à en distribuer le code
|
|
||||||
source, à faire ses meilleurs efforts pour que les obligations du
|
|
||||||
présent article 5.3.4 soient reprises par le dit tiers.
|
|
||||||
|
|
||||||
Lorsque le Logiciel modifié ou non est distribué avec un Module Externe
|
|
||||||
qui a été conçu pour l'utiliser, le Licencié doit soumettre le dit
|
|
||||||
Module Externe aux obligations précédentes.
|
|
||||||
|
|
||||||
|
|
||||||
5.3.5 COMPATIBILITE AVEC LES LICENCES CeCILL et CeCILL-C
|
|
||||||
|
|
||||||
Lorsqu'un Logiciel Modifié contient une Contribution soumise au contrat
|
|
||||||
de licence CeCILL, les stipulations prévues à l'article 5.3.4 sont
|
|
||||||
facultatives.
|
|
||||||
|
|
||||||
Un Logiciel Modifié peut être distribué sous le contrat de licence
|
|
||||||
CeCILL-C. Les stipulations prévues à l'article 5.3.4 sont alors
|
|
||||||
facultatives.
|
|
||||||
|
|
||||||
|
|
||||||
Article 6 - PROPRIETE INTELLECTUELLE
|
|
||||||
|
|
||||||
|
|
||||||
6.1 SUR LE LOGICIEL INITIAL
|
|
||||||
|
|
||||||
Le Titulaire est détenteur des droits patrimoniaux sur le Logiciel
|
|
||||||
Initial. Toute utilisation du Logiciel Initial est soumise au respect
|
|
||||||
des conditions dans lesquelles le Titulaire a choisi de diffuser son
|
|
||||||
oeuvre et nul autre n'a la faculté de modifier les conditions de
|
|
||||||
diffusion de ce Logiciel Initial.
|
|
||||||
|
|
||||||
Le Titulaire s'engage à ce que le Logiciel Initial reste au moins régi
|
|
||||||
par le Contrat et ce, pour la durée visée à l'article 4.2.
|
|
||||||
|
|
||||||
|
|
||||||
6.2 SUR LES CONTRIBUTIONS
|
|
||||||
|
|
||||||
Le Licencié qui a développé une Contribution est titulaire sur celle-ci
|
|
||||||
des droits de propriété intellectuelle dans les conditions définies par
|
|
||||||
la législation applicable.
|
|
||||||
|
|
||||||
|
|
||||||
6.3 SUR LES MODULES EXTERNES
|
|
||||||
|
|
||||||
Le Licencié qui a développé un Module Externe est titulaire sur celui-ci
|
|
||||||
des droits de propriété intellectuelle dans les conditions définies par
|
|
||||||
la législation applicable et reste libre du choix du contrat régissant
|
|
||||||
sa diffusion.
|
|
||||||
|
|
||||||
|
|
||||||
6.4 DISPOSITIONS COMMUNES
|
|
||||||
|
|
||||||
Le Licencié s'engage expressément:
|
|
||||||
|
|
||||||
1. à ne pas supprimer ou modifier de quelque manière que ce soit les
|
|
||||||
mentions de propriété intellectuelle apposées sur le Logiciel;
|
|
||||||
|
|
||||||
2. à reproduire à l'identique lesdites mentions de propriété
|
|
||||||
intellectuelle sur les copies du Logiciel modifié ou non.
|
|
||||||
|
|
||||||
Le Licencié s'engage à ne pas porter atteinte, directement ou
|
|
||||||
indirectement, aux droits de propriété intellectuelle du Titulaire et/ou
|
|
||||||
des Contributeurs sur le Logiciel et à prendre, le cas échéant, à
|
|
||||||
l'égard de son personnel toutes les mesures nécessaires pour assurer le
|
|
||||||
respect des dits droits de propriété intellectuelle du Titulaire et/ou
|
|
||||||
des Contributeurs.
|
|
||||||
|
|
||||||
|
|
||||||
Article 7 - SERVICES ASSOCIES
|
|
||||||
|
|
||||||
7.1 Le Contrat n'oblige en aucun cas le Concédant à la réalisation de
|
|
||||||
prestations d'assistance technique ou de maintenance du Logiciel.
|
|
||||||
|
|
||||||
Cependant le Concédant reste libre de proposer ce type de services. Les
|
|
||||||
termes et conditions d'une telle assistance technique et/ou d'une telle
|
|
||||||
maintenance seront alors déterminés dans un acte séparé. Ces actes de
|
|
||||||
maintenance et/ou assistance technique n'engageront que la seule
|
|
||||||
responsabilité du Concédant qui les propose.
|
|
||||||
|
|
||||||
7.2 De même, tout Concédant est libre de proposer, sous sa seule
|
|
||||||
responsabilité, à ses licenciés une garantie, qui n'engagera que lui,
|
|
||||||
lors de la redistribution du Logiciel et/ou du Logiciel Modifié et ce,
|
|
||||||
dans les conditions qu'il souhaite. Cette garantie et les modalités
|
|
||||||
financières de son application feront l'objet d'un acte séparé entre le
|
|
||||||
Concédant et le Licencié.
|
|
||||||
|
|
||||||
|
|
||||||
Article 8 - RESPONSABILITE
|
|
||||||
|
|
||||||
8.1 Sous réserve des dispositions de l'article 8.2, le Licencié a la
|
|
||||||
faculté, sous réserve de prouver la faute du Concédant concerné, de
|
|
||||||
solliciter la réparation du préjudice direct qu'il subirait du fait du
|
|
||||||
Logiciel et dont il apportera la preuve.
|
|
||||||
|
|
||||||
8.2 La responsabilité du Concédant est limitée aux engagements pris en
|
|
||||||
application du Contrat et ne saurait être engagée en raison notamment:
|
|
||||||
(i) des dommages dus à l'inexécution, totale ou partielle, de ses
|
|
||||||
obligations par le Licencié, (ii) des dommages directs ou indirects
|
|
||||||
découlant de l'utilisation ou des performances du Logiciel subis par le
|
|
||||||
Licencié et (iii) plus généralement d'un quelconque dommage indirect. En
|
|
||||||
particulier, les Parties conviennent expressément que tout préjudice
|
|
||||||
financier ou commercial (par exemple perte de données, perte de
|
|
||||||
bénéfices, perte d'exploitation, perte de clientèle ou de commandes,
|
|
||||||
manque à gagner, trouble commercial quelconque) ou toute action dirigée
|
|
||||||
contre le Licencié par un tiers, constitue un dommage indirect et
|
|
||||||
n'ouvre pas droit à réparation par le Concédant.
|
|
||||||
|
|
||||||
|
|
||||||
Article 9 - GARANTIE
|
|
||||||
|
|
||||||
9.1 Le Licencié reconnaît que l'état actuel des connaissances
|
|
||||||
scientifiques et techniques au moment de la mise en circulation du
|
|
||||||
Logiciel ne permet pas d'en tester et d'en vérifier toutes les
|
|
||||||
utilisations ni de détecter l'existence d'éventuels défauts. L'attention
|
|
||||||
du Licencié a été attirée sur ce point sur les risques associés au
|
|
||||||
chargement, à l'utilisation, la modification et/ou au développement et à
|
|
||||||
la reproduction du Logiciel qui sont réservés à des utilisateurs avertis.
|
|
||||||
|
|
||||||
Il relève de la responsabilité du Licencié de contrôler, par tous
|
|
||||||
moyens, l'adéquation du produit à ses besoins, son bon fonctionnement et
|
|
||||||
de s'assurer qu'il ne causera pas de dommages aux personnes et aux biens.
|
|
||||||
|
|
||||||
9.2 Le Concédant déclare de bonne foi être en droit de concéder
|
|
||||||
l'ensemble des droits attachés au Logiciel (comprenant notamment les
|
|
||||||
droits visés à l'article 5).
|
|
||||||
|
|
||||||
9.3 Le Licencié reconnaît que le Logiciel est fourni "en l'état" par le
|
|
||||||
Concédant sans autre garantie, expresse ou tacite, que celle prévue à
|
|
||||||
l'article 9.2 et notamment sans aucune garantie sur sa valeur commerciale,
|
|
||||||
son caractère sécurisé, innovant ou pertinent.
|
|
||||||
|
|
||||||
En particulier, le Concédant ne garantit pas que le Logiciel est exempt
|
|
||||||
d'erreur, qu'il fonctionnera sans interruption, qu'il sera compatible
|
|
||||||
avec l'équipement du Licencié et sa configuration logicielle ni qu'il
|
|
||||||
remplira les besoins du Licencié.
|
|
||||||
|
|
||||||
9.4 Le Concédant ne garantit pas, de manière expresse ou tacite, que le
|
|
||||||
Logiciel ne porte pas atteinte à un quelconque droit de propriété
|
|
||||||
intellectuelle d'un tiers portant sur un brevet, un logiciel ou sur tout
|
|
||||||
autre droit de propriété. Ainsi, le Concédant exclut toute garantie au
|
|
||||||
profit du Licencié contre les actions en contrefaçon qui pourraient être
|
|
||||||
diligentées au titre de l'utilisation, de la modification, et de la
|
|
||||||
redistribution du Logiciel. Néanmoins, si de telles actions sont
|
|
||||||
exercées contre le Licencié, le Concédant lui apportera son aide
|
|
||||||
technique et juridique pour sa défense. Cette aide technique et
|
|
||||||
juridique est déterminée au cas par cas entre le Concédant concerné et
|
|
||||||
le Licencié dans le cadre d'un protocole d'accord. Le Concédant dégage
|
|
||||||
toute responsabilité quant à l'utilisation de la dénomination du
|
|
||||||
Logiciel par le Licencié. Aucune garantie n'est apportée quant à
|
|
||||||
l'existence de droits antérieurs sur le nom du Logiciel et sur
|
|
||||||
l'existence d'une marque.
|
|
||||||
|
|
||||||
|
|
||||||
Article 10 - RESILIATION
|
|
||||||
|
|
||||||
10.1 En cas de manquement par le Licencié aux obligations mises à sa
|
|
||||||
charge par le Contrat, le Concédant pourra résilier de plein droit le
|
|
||||||
Contrat trente (30) jours après notification adressée au Licencié et
|
|
||||||
restée sans effet.
|
|
||||||
|
|
||||||
10.2 Le Licencié dont le Contrat est résilié n'est plus autorisé à
|
|
||||||
utiliser, modifier ou distribuer le Logiciel. Cependant, toutes les
|
|
||||||
licences qu'il aura concédées antérieurement à la résiliation du Contrat
|
|
||||||
resteront valides sous réserve qu'elles aient été effectuées en
|
|
||||||
conformité avec le Contrat.
|
|
||||||
|
|
||||||
|
|
||||||
Article 11 - DISPOSITIONS DIVERSES
|
|
||||||
|
|
||||||
|
|
||||||
11.1 CAUSE EXTERIEURE
|
|
||||||
|
|
||||||
Aucune des Parties ne sera responsable d'un retard ou d'une défaillance
|
|
||||||
d'exécution du Contrat qui serait dû à un cas de force majeure, un cas
|
|
||||||
fortuit ou une cause extérieure, telle que, notamment, le mauvais
|
|
||||||
fonctionnement ou les interruptions du réseau électrique ou de
|
|
||||||
télécommunication, la paralysie du réseau liée à une attaque
|
|
||||||
informatique, l'intervention des autorités gouvernementales, les
|
|
||||||
catastrophes naturelles, les dégâts des eaux, les tremblements de terre,
|
|
||||||
le feu, les explosions, les grèves et les conflits sociaux, l'état de
|
|
||||||
guerre...
|
|
||||||
|
|
||||||
11.2 Le fait, par l'une ou l'autre des Parties, d'omettre en une ou
|
|
||||||
plusieurs occasions de se prévaloir d'une ou plusieurs dispositions du
|
|
||||||
Contrat, ne pourra en aucun cas impliquer renonciation par la Partie
|
|
||||||
intéressée à s'en prévaloir ultérieurement.
|
|
||||||
|
|
||||||
11.3 Le Contrat annule et remplace toute convention antérieure, écrite
|
|
||||||
ou orale, entre les Parties sur le même objet et constitue l'accord
|
|
||||||
entier entre les Parties sur cet objet. Aucune addition ou modification
|
|
||||||
aux termes du Contrat n'aura d'effet à l'égard des Parties à moins
|
|
||||||
d'être faite par écrit et signée par leurs représentants dûment habilités.
|
|
||||||
|
|
||||||
11.4 Dans l'hypothèse où une ou plusieurs des dispositions du Contrat
|
|
||||||
s'avèrerait contraire à une loi ou à un texte applicable, existants ou
|
|
||||||
futurs, cette loi ou ce texte prévaudrait, et les Parties feraient les
|
|
||||||
amendements nécessaires pour se conformer à cette loi ou à ce texte.
|
|
||||||
Toutes les autres dispositions resteront en vigueur. De même, la
|
|
||||||
nullité, pour quelque raison que ce soit, d'une des dispositions du
|
|
||||||
Contrat ne saurait entraîner la nullité de l'ensemble du Contrat.
|
|
||||||
|
|
||||||
|
|
||||||
11.5 LANGUE
|
|
||||||
|
|
||||||
Le Contrat est rédigé en langue française et en langue anglaise, ces
|
|
||||||
deux versions faisant également foi.
|
|
||||||
|
|
||||||
|
|
||||||
Article 12 - NOUVELLES VERSIONS DU CONTRAT
|
|
||||||
|
|
||||||
12.1 Toute personne est autorisée à copier et distribuer des copies de
|
|
||||||
ce Contrat.
|
|
||||||
|
|
||||||
12.2 Afin d'en préserver la cohérence, le texte du Contrat est protégé
|
|
||||||
et ne peut être modifié que par les auteurs de la licence, lesquels se
|
|
||||||
réservent le droit de publier périodiquement des mises à jour ou de
|
|
||||||
nouvelles versions du Contrat, qui posséderont chacune un numéro
|
|
||||||
distinct. Ces versions ultérieures seront susceptibles de prendre en
|
|
||||||
compte de nouvelles problématiques rencontrées par les logiciels libres.
|
|
||||||
|
|
||||||
12.3 Tout Logiciel diffusé sous une version donnée du Contrat ne pourra
|
|
||||||
faire l'objet d'une diffusion ultérieure que sous la même version du
|
|
||||||
Contrat ou une version postérieure.
|
|
||||||
|
|
||||||
|
|
||||||
Article 13 - LOI APPLICABLE ET COMPETENCE TERRITORIALE
|
|
||||||
|
|
||||||
13.1 Le Contrat est régi par la loi française. Les Parties conviennent
|
|
||||||
de tenter de régler à l'amiable les différends ou litiges qui
|
|
||||||
viendraient à se produire par suite ou à l'occasion du Contrat.
|
|
||||||
|
|
||||||
13.2 A défaut d'accord amiable dans un délai de deux (2) mois à compter
|
|
||||||
de leur survenance et sauf situation relevant d'une procédure d'urgence,
|
|
||||||
les différends ou litiges seront portés par la Partie la plus diligente
|
|
||||||
devant les Tribunaux compétents de Paris.
|
|
||||||
|
|
||||||
|
|
||||||
Version 1.0 du 2006-09-05.
|
|
||||||
|
|
515
LICENSE.en.txt
515
LICENSE.en.txt
@ -1,515 +0,0 @@
|
|||||||
CeCILL-B FREE SOFTWARE LICENSE AGREEMENT
|
|
||||||
|
|
||||||
|
|
||||||
Notice
|
|
||||||
|
|
||||||
This Agreement is a Free Software license agreement that is the result
|
|
||||||
of discussions between its authors in order to ensure compliance with
|
|
||||||
the two main principles guiding its drafting:
|
|
||||||
|
|
||||||
* firstly, compliance with the principles governing the distribution
|
|
||||||
of Free Software: access to source code, broad rights granted to
|
|
||||||
users,
|
|
||||||
* secondly, the election of a governing law, French law, with which
|
|
||||||
it is conformant, both as regards the law of torts and
|
|
||||||
intellectual property law, and the protection that it offers to
|
|
||||||
both authors and holders of the economic rights over software.
|
|
||||||
|
|
||||||
The authors of the CeCILL-B (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre])
|
|
||||||
license are:
|
|
||||||
|
|
||||||
Commissariat à l'Energie Atomique - CEA, a public scientific, technical
|
|
||||||
and industrial research establishment, having its principal place of
|
|
||||||
business at 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris, France.
|
|
||||||
|
|
||||||
Centre National de la Recherche Scientifique - CNRS, a public scientific
|
|
||||||
and technological establishment, having its principal place of business
|
|
||||||
at 3 rue Michel-Ange, 75794 Paris cedex 16, France.
|
|
||||||
|
|
||||||
Institut National de Recherche en Informatique et en Automatique -
|
|
||||||
INRIA, a public scientific and technological establishment, having its
|
|
||||||
principal place of business at Domaine de Voluceau, Rocquencourt, BP
|
|
||||||
105, 78153 Le Chesnay cedex, France.
|
|
||||||
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
This Agreement is an open source software license intended to give users
|
|
||||||
significant freedom to modify and redistribute the software licensed
|
|
||||||
hereunder.
|
|
||||||
|
|
||||||
The exercising of this freedom is conditional upon a strong obligation
|
|
||||||
of giving credits for everybody that distributes a software
|
|
||||||
incorporating a software ruled by the current license so as all
|
|
||||||
contributions to be properly identified and acknowledged.
|
|
||||||
|
|
||||||
In consideration of access to the source code and the rights to copy,
|
|
||||||
modify and redistribute granted by the license, users are provided only
|
|
||||||
with a limited warranty and the software's author, the holder of the
|
|
||||||
economic rights, and the successive licensors only have limited liability.
|
|
||||||
|
|
||||||
In this respect, the risks associated with loading, using, modifying
|
|
||||||
and/or developing or reproducing the software by the user are brought to
|
|
||||||
the user's attention, given its Free Software status, which may make it
|
|
||||||
complicated to use, with the result that its use is reserved for
|
|
||||||
developers and experienced professionals having in-depth computer
|
|
||||||
knowledge. Users are therefore encouraged to load and test the
|
|
||||||
suitability of the software as regards their requirements in conditions
|
|
||||||
enabling the security of their systems and/or data to be ensured and,
|
|
||||||
more generally, to use and operate it in the same conditions of
|
|
||||||
security. This Agreement may be freely reproduced and published,
|
|
||||||
provided it is not altered, and that no provisions are either added or
|
|
||||||
removed herefrom.
|
|
||||||
|
|
||||||
This Agreement may apply to any or all software for which the holder of
|
|
||||||
the economic rights decides to submit the use thereof to its provisions.
|
|
||||||
|
|
||||||
|
|
||||||
Article 1 - DEFINITIONS
|
|
||||||
|
|
||||||
For the purpose of this Agreement, when the following expressions
|
|
||||||
commence with a capital letter, they shall have the following meaning:
|
|
||||||
|
|
||||||
Agreement: means this license agreement, and its possible subsequent
|
|
||||||
versions and annexes.
|
|
||||||
|
|
||||||
Software: means the software in its Object Code and/or Source Code form
|
|
||||||
and, where applicable, its documentation, "as is" when the Licensee
|
|
||||||
accepts the Agreement.
|
|
||||||
|
|
||||||
Initial Software: means the Software in its Source Code and possibly its
|
|
||||||
Object Code form and, where applicable, its documentation, "as is" when
|
|
||||||
it is first distributed under the terms and conditions of the Agreement.
|
|
||||||
|
|
||||||
Modified Software: means the Software modified by at least one
|
|
||||||
Contribution.
|
|
||||||
|
|
||||||
Source Code: means all the Software's instructions and program lines to
|
|
||||||
which access is required so as to modify the Software.
|
|
||||||
|
|
||||||
Object Code: means the binary files originating from the compilation of
|
|
||||||
the Source Code.
|
|
||||||
|
|
||||||
Holder: means the holder(s) of the economic rights over the Initial
|
|
||||||
Software.
|
|
||||||
|
|
||||||
Licensee: means the Software user(s) having accepted the Agreement.
|
|
||||||
|
|
||||||
Contributor: means a Licensee having made at least one Contribution.
|
|
||||||
|
|
||||||
Licensor: means the Holder, or any other individual or legal entity, who
|
|
||||||
distributes the Software under the Agreement.
|
|
||||||
|
|
||||||
Contribution: means any or all modifications, corrections, translations,
|
|
||||||
adaptations and/or new functions integrated into the Software by any or
|
|
||||||
all Contributors, as well as any or all Internal Modules.
|
|
||||||
|
|
||||||
Module: means a set of sources files including their documentation that
|
|
||||||
enables supplementary functions or services in addition to those offered
|
|
||||||
by the Software.
|
|
||||||
|
|
||||||
External Module: means any or all Modules, not derived from the
|
|
||||||
Software, so that this Module and the Software run in separate address
|
|
||||||
spaces, with one calling the other when they are run.
|
|
||||||
|
|
||||||
Internal Module: means any or all Module, connected to the Software so
|
|
||||||
that they both execute in the same address space.
|
|
||||||
|
|
||||||
Parties: mean both the Licensee and the Licensor.
|
|
||||||
|
|
||||||
These expressions may be used both in singular and plural form.
|
|
||||||
|
|
||||||
|
|
||||||
Article 2 - PURPOSE
|
|
||||||
|
|
||||||
The purpose of the Agreement is the grant by the Licensor to the
|
|
||||||
Licensee of a non-exclusive, transferable and worldwide license for the
|
|
||||||
Software as set forth in Article 5 hereinafter for the whole term of the
|
|
||||||
protection granted by the rights over said Software.
|
|
||||||
|
|
||||||
|
|
||||||
Article 3 - ACCEPTANCE
|
|
||||||
|
|
||||||
3.1 The Licensee shall be deemed as having accepted the terms and
|
|
||||||
conditions of this Agreement upon the occurrence of the first of the
|
|
||||||
following events:
|
|
||||||
|
|
||||||
* (i) loading the Software by any or all means, notably, by
|
|
||||||
downloading from a remote server, or by loading from a physical
|
|
||||||
medium;
|
|
||||||
* (ii) the first time the Licensee exercises any of the rights
|
|
||||||
granted hereunder.
|
|
||||||
|
|
||||||
3.2 One copy of the Agreement, containing a notice relating to the
|
|
||||||
characteristics of the Software, to the limited warranty, and to the
|
|
||||||
fact that its use is restricted to experienced users has been provided
|
|
||||||
to the Licensee prior to its acceptance as set forth in Article 3.1
|
|
||||||
hereinabove, and the Licensee hereby acknowledges that it has read and
|
|
||||||
understood it.
|
|
||||||
|
|
||||||
|
|
||||||
Article 4 - EFFECTIVE DATE AND TERM
|
|
||||||
|
|
||||||
|
|
||||||
4.1 EFFECTIVE DATE
|
|
||||||
|
|
||||||
The Agreement shall become effective on the date when it is accepted by
|
|
||||||
the Licensee as set forth in Article 3.1.
|
|
||||||
|
|
||||||
|
|
||||||
4.2 TERM
|
|
||||||
|
|
||||||
The Agreement shall remain in force for the entire legal term of
|
|
||||||
protection of the economic rights over the Software.
|
|
||||||
|
|
||||||
|
|
||||||
Article 5 - SCOPE OF RIGHTS GRANTED
|
|
||||||
|
|
||||||
The Licensor hereby grants to the Licensee, who accepts, the following
|
|
||||||
rights over the Software for any or all use, and for the term of the
|
|
||||||
Agreement, on the basis of the terms and conditions set forth hereinafter.
|
|
||||||
|
|
||||||
Besides, if the Licensor owns or comes to own one or more patents
|
|
||||||
protecting all or part of the functions of the Software or of its
|
|
||||||
components, the Licensor undertakes not to enforce the rights granted by
|
|
||||||
these patents against successive Licensees using, exploiting or
|
|
||||||
modifying the Software. If these patents are transferred, the Licensor
|
|
||||||
undertakes to have the transferees subscribe to the obligations set
|
|
||||||
forth in this paragraph.
|
|
||||||
|
|
||||||
|
|
||||||
5.1 RIGHT OF USE
|
|
||||||
|
|
||||||
The Licensee is authorized to use the Software, without any limitation
|
|
||||||
as to its fields of application, with it being hereinafter specified
|
|
||||||
that this comprises:
|
|
||||||
|
|
||||||
1. permanent or temporary reproduction of all or part of the Software
|
|
||||||
by any or all means and in any or all form.
|
|
||||||
|
|
||||||
2. loading, displaying, running, or storing the Software on any or
|
|
||||||
all medium.
|
|
||||||
|
|
||||||
3. entitlement to observe, study or test its operation so as to
|
|
||||||
determine the ideas and principles behind any or all constituent
|
|
||||||
elements of said Software. This shall apply when the Licensee
|
|
||||||
carries out any or all loading, displaying, running, transmission
|
|
||||||
or storage operation as regards the Software, that it is entitled
|
|
||||||
to carry out hereunder.
|
|
||||||
|
|
||||||
|
|
||||||
5.2 ENTITLEMENT TO MAKE CONTRIBUTIONS
|
|
||||||
|
|
||||||
The right to make Contributions includes the right to translate, adapt,
|
|
||||||
arrange, or make any or all modifications to the Software, and the right
|
|
||||||
to reproduce the resulting software.
|
|
||||||
|
|
||||||
The Licensee is authorized to make any or all Contributions to the
|
|
||||||
Software provided that it includes an explicit notice that it is the
|
|
||||||
author of said Contribution and indicates the date of the creation thereof.
|
|
||||||
|
|
||||||
|
|
||||||
5.3 RIGHT OF DISTRIBUTION
|
|
||||||
|
|
||||||
In particular, the right of distribution includes the right to publish,
|
|
||||||
transmit and communicate the Software to the general public on any or
|
|
||||||
all medium, and by any or all means, and the right to market, either in
|
|
||||||
consideration of a fee, or free of charge, one or more copies of the
|
|
||||||
Software by any means.
|
|
||||||
|
|
||||||
The Licensee is further authorized to distribute copies of the modified
|
|
||||||
or unmodified Software to third parties according to the terms and
|
|
||||||
conditions set forth hereinafter.
|
|
||||||
|
|
||||||
|
|
||||||
5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION
|
|
||||||
|
|
||||||
The Licensee is authorized to distribute true copies of the Software in
|
|
||||||
Source Code or Object Code form, provided that said distribution
|
|
||||||
complies with all the provisions of the Agreement and is accompanied by:
|
|
||||||
|
|
||||||
1. a copy of the Agreement,
|
|
||||||
|
|
||||||
2. a notice relating to the limitation of both the Licensor's
|
|
||||||
warranty and liability as set forth in Articles 8 and 9,
|
|
||||||
|
|
||||||
and that, in the event that only the Object Code of the Software is
|
|
||||||
redistributed, the Licensee allows effective access to the full Source
|
|
||||||
Code of the Software at a minimum during the entire period of its
|
|
||||||
distribution of the Software, it being understood that the additional
|
|
||||||
cost of acquiring the Source Code shall not exceed the cost of
|
|
||||||
transferring the data.
|
|
||||||
|
|
||||||
|
|
||||||
5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE
|
|
||||||
|
|
||||||
If the Licensee makes any Contribution to the Software, the resulting
|
|
||||||
Modified Software may be distributed under a license agreement other
|
|
||||||
than this Agreement subject to compliance with the provisions of Article
|
|
||||||
5.3.4.
|
|
||||||
|
|
||||||
|
|
||||||
5.3.3 DISTRIBUTION OF EXTERNAL MODULES
|
|
||||||
|
|
||||||
When the Licensee has developed an External Module, the terms and
|
|
||||||
conditions of this Agreement do not apply to said External Module, that
|
|
||||||
may be distributed under a separate license agreement.
|
|
||||||
|
|
||||||
|
|
||||||
5.3.4 CREDITS
|
|
||||||
|
|
||||||
Any Licensee who may distribute a Modified Software hereby expressly
|
|
||||||
agrees to:
|
|
||||||
|
|
||||||
1. indicate in the related documentation that it is based on the
|
|
||||||
Software licensed hereunder, and reproduce the intellectual
|
|
||||||
property notice for the Software,
|
|
||||||
|
|
||||||
2. ensure that written indications of the Software intended use,
|
|
||||||
intellectual property notice and license hereunder are included in
|
|
||||||
easily accessible format from the Modified Software interface,
|
|
||||||
|
|
||||||
3. mention, on a freely accessible website describing the Modified
|
|
||||||
Software, at least throughout the distribution term thereof, that
|
|
||||||
it is based on the Software licensed hereunder, and reproduce the
|
|
||||||
Software intellectual property notice,
|
|
||||||
|
|
||||||
4. where it is distributed to a third party that may distribute a
|
|
||||||
Modified Software without having to make its source code
|
|
||||||
available, make its best efforts to ensure that said third party
|
|
||||||
agrees to comply with the obligations set forth in this Article .
|
|
||||||
|
|
||||||
If the Software, whether or not modified, is distributed with an
|
|
||||||
External Module designed for use in connection with the Software, the
|
|
||||||
Licensee shall submit said External Module to the foregoing obligations.
|
|
||||||
|
|
||||||
|
|
||||||
5.3.5 COMPATIBILITY WITH THE CeCILL AND CeCILL-C LICENSES
|
|
||||||
|
|
||||||
Where a Modified Software contains a Contribution subject to the CeCILL
|
|
||||||
license, the provisions set forth in Article 5.3.4 shall be optional.
|
|
||||||
|
|
||||||
A Modified Software may be distributed under the CeCILL-C license. In
|
|
||||||
such a case the provisions set forth in Article 5.3.4 shall be optional.
|
|
||||||
|
|
||||||
|
|
||||||
Article 6 - INTELLECTUAL PROPERTY
|
|
||||||
|
|
||||||
|
|
||||||
6.1 OVER THE INITIAL SOFTWARE
|
|
||||||
|
|
||||||
The Holder owns the economic rights over the Initial Software. Any or
|
|
||||||
all use of the Initial Software is subject to compliance with the terms
|
|
||||||
and conditions under which the Holder has elected to distribute its work
|
|
||||||
and no one shall be entitled to modify the terms and conditions for the
|
|
||||||
distribution of said Initial Software.
|
|
||||||
|
|
||||||
The Holder undertakes that the Initial Software will remain ruled at
|
|
||||||
least by this Agreement, for the duration set forth in Article 4.2.
|
|
||||||
|
|
||||||
|
|
||||||
6.2 OVER THE CONTRIBUTIONS
|
|
||||||
|
|
||||||
The Licensee who develops a Contribution is the owner of the
|
|
||||||
intellectual property rights over this Contribution as defined by
|
|
||||||
applicable law.
|
|
||||||
|
|
||||||
|
|
||||||
6.3 OVER THE EXTERNAL MODULES
|
|
||||||
|
|
||||||
The Licensee who develops an External Module is the owner of the
|
|
||||||
intellectual property rights over this External Module as defined by
|
|
||||||
applicable law and is free to choose the type of agreement that shall
|
|
||||||
govern its distribution.
|
|
||||||
|
|
||||||
|
|
||||||
6.4 JOINT PROVISIONS
|
|
||||||
|
|
||||||
The Licensee expressly undertakes:
|
|
||||||
|
|
||||||
1. not to remove, or modify, in any manner, the intellectual property
|
|
||||||
notices attached to the Software;
|
|
||||||
|
|
||||||
2. to reproduce said notices, in an identical manner, in the copies
|
|
||||||
of the Software modified or not.
|
|
||||||
|
|
||||||
The Licensee undertakes not to directly or indirectly infringe the
|
|
||||||
intellectual property rights of the Holder and/or Contributors on the
|
|
||||||
Software and to take, where applicable, vis-à-vis its staff, any and all
|
|
||||||
measures required to ensure respect of said intellectual property rights
|
|
||||||
of the Holder and/or Contributors.
|
|
||||||
|
|
||||||
|
|
||||||
Article 7 - RELATED SERVICES
|
|
||||||
|
|
||||||
7.1 Under no circumstances shall the Agreement oblige the Licensor to
|
|
||||||
provide technical assistance or maintenance services for the Software.
|
|
||||||
|
|
||||||
However, the Licensor is entitled to offer this type of services. The
|
|
||||||
terms and conditions of such technical assistance, and/or such
|
|
||||||
maintenance, shall be set forth in a separate instrument. Only the
|
|
||||||
Licensor offering said maintenance and/or technical assistance services
|
|
||||||
shall incur liability therefor.
|
|
||||||
|
|
||||||
7.2 Similarly, any Licensor is entitled to offer to its licensees, under
|
|
||||||
its sole responsibility, a warranty, that shall only be binding upon
|
|
||||||
itself, for the redistribution of the Software and/or the Modified
|
|
||||||
Software, under terms and conditions that it is free to decide. Said
|
|
||||||
warranty, and the financial terms and conditions of its application,
|
|
||||||
shall be subject of a separate instrument executed between the Licensor
|
|
||||||
and the Licensee.
|
|
||||||
|
|
||||||
|
|
||||||
Article 8 - LIABILITY
|
|
||||||
|
|
||||||
8.1 Subject to the provisions of Article 8.2, the Licensee shall be
|
|
||||||
entitled to claim compensation for any direct loss it may have suffered
|
|
||||||
from the Software as a result of a fault on the part of the relevant
|
|
||||||
Licensor, subject to providing evidence thereof.
|
|
||||||
|
|
||||||
8.2 The Licensor's liability is limited to the commitments made under
|
|
||||||
this Agreement and shall not be incurred as a result of in particular:
|
|
||||||
(i) loss due the Licensee's total or partial failure to fulfill its
|
|
||||||
obligations, (ii) direct or consequential loss that is suffered by the
|
|
||||||
Licensee due to the use or performance of the Software, and (iii) more
|
|
||||||
generally, any consequential loss. In particular the Parties expressly
|
|
||||||
agree that any or all pecuniary or business loss (i.e. loss of data,
|
|
||||||
loss of profits, operating loss, loss of customers or orders,
|
|
||||||
opportunity cost, any disturbance to business activities) or any or all
|
|
||||||
legal proceedings instituted against the Licensee by a third party,
|
|
||||||
shall constitute consequential loss and shall not provide entitlement to
|
|
||||||
any or all compensation from the Licensor.
|
|
||||||
|
|
||||||
|
|
||||||
Article 9 - WARRANTY
|
|
||||||
|
|
||||||
9.1 The Licensee acknowledges that the scientific and technical
|
|
||||||
state-of-the-art when the Software was distributed did not enable all
|
|
||||||
possible uses to be tested and verified, nor for the presence of
|
|
||||||
possible defects to be detected. In this respect, the Licensee's
|
|
||||||
attention has been drawn to the risks associated with loading, using,
|
|
||||||
modifying and/or developing and reproducing the Software which are
|
|
||||||
reserved for experienced users.
|
|
||||||
|
|
||||||
The Licensee shall be responsible for verifying, by any or all means,
|
|
||||||
the suitability of the product for its requirements, its good working
|
|
||||||
order, and for ensuring that it shall not cause damage to either persons
|
|
||||||
or properties.
|
|
||||||
|
|
||||||
9.2 The Licensor hereby represents, in good faith, that it is entitled
|
|
||||||
to grant all the rights over the Software (including in particular the
|
|
||||||
rights set forth in Article 5).
|
|
||||||
|
|
||||||
9.3 The Licensee acknowledges that the Software is supplied "as is" by
|
|
||||||
the Licensor without any other express or tacit warranty, other than
|
|
||||||
that provided for in Article 9.2 and, in particular, without any warranty
|
|
||||||
as to its commercial value, its secured, safe, innovative or relevant
|
|
||||||
nature.
|
|
||||||
|
|
||||||
Specifically, the Licensor does not warrant that the Software is free
|
|
||||||
from any error, that it will operate without interruption, that it will
|
|
||||||
be compatible with the Licensee's own equipment and software
|
|
||||||
configuration, nor that it will meet the Licensee's requirements.
|
|
||||||
|
|
||||||
9.4 The Licensor does not either expressly or tacitly warrant that the
|
|
||||||
Software does not infringe any third party intellectual property right
|
|
||||||
relating to a patent, software or any other property right. Therefore,
|
|
||||||
the Licensor disclaims any and all liability towards the Licensee
|
|
||||||
arising out of any or all proceedings for infringement that may be
|
|
||||||
instituted in respect of the use, modification and redistribution of the
|
|
||||||
Software. Nevertheless, should such proceedings be instituted against
|
|
||||||
the Licensee, the Licensor shall provide it with technical and legal
|
|
||||||
assistance for its defense. Such technical and legal assistance shall be
|
|
||||||
decided on a case-by-case basis between the relevant Licensor and the
|
|
||||||
Licensee pursuant to a memorandum of understanding. The Licensor
|
|
||||||
disclaims any and all liability as regards the Licensee's use of the
|
|
||||||
name of the Software. No warranty is given as regards the existence of
|
|
||||||
prior rights over the name of the Software or as regards the existence
|
|
||||||
of a trademark.
|
|
||||||
|
|
||||||
|
|
||||||
Article 10 - TERMINATION
|
|
||||||
|
|
||||||
10.1 In the event of a breach by the Licensee of its obligations
|
|
||||||
hereunder, the Licensor may automatically terminate this Agreement
|
|
||||||
thirty (30) days after notice has been sent to the Licensee and has
|
|
||||||
remained ineffective.
|
|
||||||
|
|
||||||
10.2 A Licensee whose Agreement is terminated shall no longer be
|
|
||||||
authorized to use, modify or distribute the Software. However, any
|
|
||||||
licenses that it may have granted prior to termination of the Agreement
|
|
||||||
shall remain valid subject to their having been granted in compliance
|
|
||||||
with the terms and conditions hereof.
|
|
||||||
|
|
||||||
|
|
||||||
Article 11 - MISCELLANEOUS
|
|
||||||
|
|
||||||
|
|
||||||
11.1 EXCUSABLE EVENTS
|
|
||||||
|
|
||||||
Neither Party shall be liable for any or all delay, or failure to
|
|
||||||
perform the Agreement, that may be attributable to an event of force
|
|
||||||
majeure, an act of God or an outside cause, such as defective
|
|
||||||
functioning or interruptions of the electricity or telecommunications
|
|
||||||
networks, network paralysis following a virus attack, intervention by
|
|
||||||
government authorities, natural disasters, water damage, earthquakes,
|
|
||||||
fire, explosions, strikes and labor unrest, war, etc.
|
|
||||||
|
|
||||||
11.2 Any failure by either Party, on one or more occasions, to invoke
|
|
||||||
one or more of the provisions hereof, shall under no circumstances be
|
|
||||||
interpreted as being a waiver by the interested Party of its right to
|
|
||||||
invoke said provision(s) subsequently.
|
|
||||||
|
|
||||||
11.3 The Agreement cancels and replaces any or all previous agreements,
|
|
||||||
whether written or oral, between the Parties and having the same
|
|
||||||
purpose, and constitutes the entirety of the agreement between said
|
|
||||||
Parties concerning said purpose. No supplement or modification to the
|
|
||||||
terms and conditions hereof shall be effective as between the Parties
|
|
||||||
unless it is made in writing and signed by their duly authorized
|
|
||||||
representatives.
|
|
||||||
|
|
||||||
11.4 In the event that one or more of the provisions hereof were to
|
|
||||||
conflict with a current or future applicable act or legislative text,
|
|
||||||
said act or legislative text shall prevail, and the Parties shall make
|
|
||||||
the necessary amendments so as to comply with said act or legislative
|
|
||||||
text. All other provisions shall remain effective. Similarly, invalidity
|
|
||||||
of a provision of the Agreement, for any reason whatsoever, shall not
|
|
||||||
cause the Agreement as a whole to be invalid.
|
|
||||||
|
|
||||||
|
|
||||||
11.5 LANGUAGE
|
|
||||||
|
|
||||||
The Agreement is drafted in both French and English and both versions
|
|
||||||
are deemed authentic.
|
|
||||||
|
|
||||||
|
|
||||||
Article 12 - NEW VERSIONS OF THE AGREEMENT
|
|
||||||
|
|
||||||
12.1 Any person is authorized to duplicate and distribute copies of this
|
|
||||||
Agreement.
|
|
||||||
|
|
||||||
12.2 So as to ensure coherence, the wording of this Agreement is
|
|
||||||
protected and may only be modified by the authors of the License, who
|
|
||||||
reserve the right to periodically publish updates or new versions of the
|
|
||||||
Agreement, each with a separate number. These subsequent versions may
|
|
||||||
address new issues encountered by Free Software.
|
|
||||||
|
|
||||||
12.3 Any Software distributed under a given version of the Agreement may
|
|
||||||
only be subsequently distributed under the same version of the Agreement
|
|
||||||
or a subsequent version.
|
|
||||||
|
|
||||||
|
|
||||||
Article 13 - GOVERNING LAW AND JURISDICTION
|
|
||||||
|
|
||||||
13.1 The Agreement is governed by French law. The Parties agree to
|
|
||||||
endeavor to seek an amicable solution to any disagreements or disputes
|
|
||||||
that may arise during the performance of the Agreement.
|
|
||||||
|
|
||||||
13.2 Failing an amicable solution within two (2) months as from their
|
|
||||||
occurrence, and unless emergency proceedings are necessary, the
|
|
||||||
disagreements or disputes shall be referred to the Paris Courts having
|
|
||||||
jurisdiction, by the more diligent Party.
|
|
||||||
|
|
||||||
|
|
||||||
Version 1.0 dated 2006-09-05.
|
|
||||||
|
|
22
Makefile
22
Makefile
@ -1,22 +0,0 @@
|
|||||||
locales:
|
|
||||||
scripts/locales.sh
|
|
||||||
|
|
||||||
push-locales: locales
|
|
||||||
zanata-cli -q -B push --errors --project-version `git branch | grep \* | cut -d ' ' -f2-`
|
|
||||||
|
|
||||||
pull-locales:
|
|
||||||
zanata-cli -q -B pull --min-doc-percent 50 --project-version `git branch | grep \* | cut -d ' ' -f2-`
|
|
||||||
scripts/po2json.sh
|
|
||||||
|
|
||||||
stats-locales:
|
|
||||||
zanata-cli -q stats --project-version `git branch | grep \* | cut -d ' ' -f2-`
|
|
||||||
|
|
||||||
push-trad-to-zanata:
|
|
||||||
scripts/push-trad-to-zanata.sh $(filter-out $@,$(MAKECMDGOALS))
|
|
||||||
|
|
||||||
add-key-locales:
|
|
||||||
scripts/locale-add-key.pl "$(subst ",\",$(filter-out $@,$(MAKECMDGOALS)))"
|
|
||||||
|
|
||||||
# empty targets to be able to use MAKECMDGOALS as arguments to scripts
|
|
||||||
%:
|
|
||||||
@:
|
|
13
README.md
13
README.md
@ -1,13 +0,0 @@
|
|||||||
# Funky-Framadate
|
|
||||||
|
|
||||||
Expérimentation d'une nouvelle façon de faire des sondage.
|
|
||||||
|
|
||||||
https://sketch.cloud/s/MMzYa/dRrDMZ
|
|
||||||
|
|
||||||
## Developpement
|
|
||||||
|
|
||||||
Si docker est disponible sur la machine :
|
|
||||||
|
|
||||||
`./dev`
|
|
||||||
|
|
||||||
Sinon, se placer dans le repertoire [public](public) et démarrer un serveur http. Pour le moment, il n'y à aucun échange de données avec un serveur.
|
|
@ -1,95 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
use Framadate\Message;
|
|
||||||
use Framadate\Services\InputService;
|
|
||||||
use Framadate\Services\LogService;
|
|
||||||
use Framadate\Services\MailService;
|
|
||||||
use Framadate\Services\NotificationService;
|
|
||||||
use Framadate\Services\PollService;
|
|
||||||
use Framadate\Services\SecurityService;
|
|
||||||
|
|
||||||
include_once __DIR__ . '/../app/inc/init.php';
|
|
||||||
|
|
||||||
/* Variables */
|
|
||||||
/* --------- */
|
|
||||||
|
|
||||||
$poll_id = null;
|
|
||||||
$poll = null;
|
|
||||||
$message = null;
|
|
||||||
$result = false;
|
|
||||||
$comments = [];
|
|
||||||
$is_admin = false;
|
|
||||||
|
|
||||||
/* Services */
|
|
||||||
/*----------*/
|
|
||||||
|
|
||||||
$logService = new LogService();
|
|
||||||
$pollService = new PollService($connect, $logService);
|
|
||||||
$inputService = new InputService();
|
|
||||||
$mailService = new MailService($config['use_smtp'], $config['smtp_options'], $config['use_sendmail']);
|
|
||||||
$notificationService = new NotificationService($mailService);
|
|
||||||
$securityService = new SecurityService();
|
|
||||||
|
|
||||||
/* PAGE */
|
|
||||||
/* ---- */
|
|
||||||
|
|
||||||
if (!empty($_POST['poll'])) {
|
|
||||||
$poll_id = filter_input(INPUT_POST, 'poll', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
|
|
||||||
$poll = $pollService->findById($poll_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($_POST['poll_admin'])) {
|
|
||||||
$admin_poll_id = filter_input(INPUT_POST, 'poll_admin', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
|
|
||||||
if (strlen($admin_poll_id) === 24) {
|
|
||||||
$is_admin = ($pollService->findByAdminId($admin_poll_id) !== null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$poll) {
|
|
||||||
$message = new Message('error', __('Error', "This poll doesn't exist!"));
|
|
||||||
} else if ($poll && !$securityService->canAccessPoll($poll) && !$is_admin) {
|
|
||||||
$message = new Message('error', __('Password', 'Wrong password'));
|
|
||||||
} else {
|
|
||||||
$name = $inputService->filterName($_POST['name']);
|
|
||||||
$comment = $inputService->filterComment($_POST['comment']);
|
|
||||||
|
|
||||||
if ($name === null) {
|
|
||||||
$message = new Message('danger', __('Error', 'The name is invalid.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($message === null) {
|
|
||||||
// Add comment
|
|
||||||
$result = $pollService->addComment($poll_id, $name, $comment);
|
|
||||||
if ($result) {
|
|
||||||
$message = new Message('success', __('Comments', 'Comment saved'));
|
|
||||||
$notificationService->sendUpdateNotification($poll, NotificationService::ADD_COMMENT, $name);
|
|
||||||
} else {
|
|
||||||
$message = new Message('danger', __('Error', 'Comment failed'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$comments = $pollService->allCommentsByPollId($poll_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
$smarty->error_reporting = E_ALL & ~E_NOTICE;
|
|
||||||
$smarty->assign('comments', $comments);
|
|
||||||
$comments_html = $smarty->fetch('part/comments_list.tpl');
|
|
||||||
|
|
||||||
$response = ['result' => $result, 'message' => $message, 'comments' => $comments_html];
|
|
||||||
|
|
||||||
echo json_encode($response);
|
|
@ -1,94 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
|
|
||||||
use Framadate\Message;
|
|
||||||
use Framadate\Services\LogService;
|
|
||||||
use Framadate\Services\MailService;
|
|
||||||
use Framadate\Services\PollService;
|
|
||||||
use Framadate\Services\SessionService;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
include_once __DIR__ . '/../app/inc/init.php';
|
|
||||||
|
|
||||||
$logService = new LogService();
|
|
||||||
$sessionService = new SessionService();
|
|
||||||
$mailService = new MailService($config['use_smtp'], $config['smtp_options'], $config['use_sendmail']);
|
|
||||||
$pollService = new PollService($connect, $logService);
|
|
||||||
|
|
||||||
$result = false;
|
|
||||||
$message = null;
|
|
||||||
$poll = null;
|
|
||||||
$poll_id = null;
|
|
||||||
$email = null;
|
|
||||||
|
|
||||||
if (!empty($_POST['poll'])) {
|
|
||||||
$poll_id = filter_input(INPUT_POST, 'poll', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
|
|
||||||
$poll = $pollService->findById($poll_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
$token = $sessionService->get("Common", SESSION_EDIT_LINK_TOKEN);
|
|
||||||
$token_form_value = empty($_POST['token']) ? null : $_POST['token'];
|
|
||||||
$editedVoteUniqueId = filter_input(INPUT_POST, 'editedVoteUniqueId', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
|
|
||||||
if (is_null($poll) || $config['use_smtp'] === false || is_null($token) || is_null($token_form_value)
|
|
||||||
|| !$token->check($token_form_value) || is_null($editedVoteUniqueId)) {
|
|
||||||
$message = new Message('error', __('Error', 'Something has gone wrong...'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_null($message)) {
|
|
||||||
$email = $mailService->isValidEmail($_POST['email']);
|
|
||||||
if (is_null($email)) {
|
|
||||||
$message = new Message('error', __('EditLink', 'The email address is not correct.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_null($message)) {
|
|
||||||
$time = $sessionService->get("Common", SESSION_EDIT_LINK_TIME);
|
|
||||||
|
|
||||||
if (!empty($time)) {
|
|
||||||
$remainingTime = TIME_EDIT_LINK_EMAIL - (time() - $time);
|
|
||||||
|
|
||||||
if ($remainingTime > 0) {
|
|
||||||
$message = new Message('error', __f('EditLink', 'Please wait %d seconds before we can send an email to you then try again.', $remainingTime));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_null($message)) {
|
|
||||||
$url = Utils::getUrlSondage($poll_id, false, $editedVoteUniqueId);
|
|
||||||
|
|
||||||
$smarty->assign('poll', $poll);
|
|
||||||
$smarty->assign('poll_id', $poll_id);
|
|
||||||
$smarty->assign('editedVoteUniqueId', $editedVoteUniqueId);
|
|
||||||
$body = $smarty->fetch('mail/remember_edit_link.tpl');
|
|
||||||
|
|
||||||
$subject = '[' . NOMAPPLICATION . '][' . __('EditLink', 'REMINDER') . '] ' . __f('EditLink', 'Edit link for poll "%s"', $poll->title);
|
|
||||||
|
|
||||||
$mailService->send($email, $subject, $body);
|
|
||||||
$sessionService->remove("Common", SESSION_EDIT_LINK_TOKEN);
|
|
||||||
$sessionService->set("Common", SESSION_EDIT_LINK_TIME, time());
|
|
||||||
|
|
||||||
$message = new Message('success', __('EditLink', 'Your reminder has been successfully sent!'));
|
|
||||||
$result = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$smarty->error_reporting = E_ALL & ~E_NOTICE;
|
|
||||||
|
|
||||||
$response = ['result' => $result, 'message' => $message];
|
|
||||||
|
|
||||||
echo json_encode($response);
|
|
@ -1 +0,0 @@
|
|||||||
admin:$apr1$BskOE5OK$zOMq.fKFNCHkKhBdA12mR/
|
|
230
admin/check.php
230
admin/check.php
@ -1,230 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
|
|
||||||
use Framadate\Message;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
define('ROOT_DIR', __DIR__ . '/../');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checking for missing vendors.
|
|
||||||
*/
|
|
||||||
if (!file_exists(ROOT_DIR . 'vendor/autoload.php') || !file_exists(ROOT_DIR . 'vendor/o80/i18n/src/shortcuts.php')) {
|
|
||||||
die ("ERROR: You should use <code>composer install</code> to fetch dependant libraries.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stripped ini sequence
|
|
||||||
*/
|
|
||||||
require_once ROOT_DIR . 'vendor/autoload.php';
|
|
||||||
require_once ROOT_DIR . 'vendor/o80/i18n/src/shortcuts.php';
|
|
||||||
require_once ROOT_DIR . 'app/inc/constants.php';
|
|
||||||
if (session_id() === '') {
|
|
||||||
session_start();
|
|
||||||
}
|
|
||||||
$ALLOWED_LANGUAGES = [
|
|
||||||
'fr' => 'Français',
|
|
||||||
'en' => 'English',
|
|
||||||
'oc' => 'Occitan',
|
|
||||||
'es' => 'Español',
|
|
||||||
'de' => 'Deutsch',
|
|
||||||
'it' => 'Italiano',
|
|
||||||
'br' => 'Brezhoneg',
|
|
||||||
];
|
|
||||||
const DEFAULT_LANGUAGE = 'en';
|
|
||||||
require_once ROOT_DIR . 'app/inc/i18n.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to sort messages by type (priorise errors on warning, warning on info, etc.)
|
|
||||||
*
|
|
||||||
* @param Message $a
|
|
||||||
* @param Message $b
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
function compareCheckMessage(Message $a, Message $b)
|
|
||||||
{
|
|
||||||
$values = [
|
|
||||||
'danger' => 0,
|
|
||||||
'warning' => 1,
|
|
||||||
'info' => 2,
|
|
||||||
'success' => 3
|
|
||||||
];
|
|
||||||
$vA = $values[$a->type];
|
|
||||||
$vB = $values[$b->type];
|
|
||||||
|
|
||||||
if ($vA === $vB) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return ($vA < $vB) ? -1 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Vars
|
|
||||||
*/
|
|
||||||
$messages = [];
|
|
||||||
$inc_directory = ROOT_DIR . 'app/inc/';
|
|
||||||
$conf_filename = $inc_directory . 'config.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Messages
|
|
||||||
*/
|
|
||||||
|
|
||||||
// PHP Version
|
|
||||||
if (version_compare(PHP_VERSION, PHP_NEEDED_VERSION) >= 0) {
|
|
||||||
$messages[] = new Message('info', __f('Check','PHP version %s is enough (needed at least PHP %s).', PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION, PHP_NEEDED_VERSION));
|
|
||||||
} else {
|
|
||||||
$messages[] = new Message('danger', __f('Check','Your PHP version (%s) is too old. This application needs at least PHP %s.', phpversion(), PHP_NEEDED_VERSION));
|
|
||||||
}
|
|
||||||
|
|
||||||
// INTL extension
|
|
||||||
if (extension_loaded('intl')) {
|
|
||||||
$messages[] = new Message('info', __('Check','PHP Intl extension is enabled.'));
|
|
||||||
} else {
|
|
||||||
$messages[] = new Message('danger', __('Check','You need to enable the PHP Intl extension.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is template compile dir exists and writable ?
|
|
||||||
if (!file_exists(ROOT_DIR . COMPILE_DIR)) {
|
|
||||||
$messages[] = new Message('danger', __f('Check','The template compile directory (%s) doesn\'t exist in "%s". Retry the installation process.', COMPILE_DIR, realpath(ROOT_DIR)));
|
|
||||||
} elseif (is_writable(ROOT_DIR . COMPILE_DIR)) {
|
|
||||||
$messages[] = new Message('info', __f('Check','The template compile directory (%s) is writable.', realpath(ROOT_DIR . COMPILE_DIR)));
|
|
||||||
} else {
|
|
||||||
$messages[] = new Message('danger', __f('Check','The template compile directory (%s) is not writable.', realpath(ROOT_DIR . COMPILE_DIR)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Does config.php exists or is writable ?
|
|
||||||
if (file_exists($conf_filename)) {
|
|
||||||
$messages[] = new Message('info', __('Check','The config file exists.'));
|
|
||||||
} elseif (is_writable($inc_directory)) {
|
|
||||||
$messages[] = new Message('info', __f('Check','The config file directory (%s) is writable.', $inc_directory));
|
|
||||||
} else {
|
|
||||||
$messages[] = new Message('danger', __f('Check','The config file directory (%s) is not writable and the config file (%s) does not exists.', $inc_directory, $conf_filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Security
|
|
||||||
if (extension_loaded('openssl')) {
|
|
||||||
$messages[] = new Message('info', __('Check','OpenSSL extension loaded.'));
|
|
||||||
} else {
|
|
||||||
$messages[] = new Message('warning', __('Check','Consider enabling the PHP extension OpenSSL for increased security.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ini_get('session.cookie_httponly') === '1') {
|
|
||||||
$messages[] = new Message('info', __('Check', 'Cookies are served from HTTP only.'));
|
|
||||||
} else {
|
|
||||||
$messages[] = new Message('warning', __('Check', "Consider setting « session.cookie_httponly = 1 » inside your php.ini or add « php_value session.cookie_httponly 1 » to your .htaccess so that cookies can't be accessed through Javascript."));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Datetime
|
|
||||||
$timezone = ini_get('date.timezone');
|
|
||||||
if (!empty($timezone)) {
|
|
||||||
$messages[] = new Message('info', __('Check','date.timezone is set.'));
|
|
||||||
} else {
|
|
||||||
$messages[] = new Message('warning', __('Check','Consider setting the date.timezone in php.ini.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// The percentage of steps needed to be ready to launch the application
|
|
||||||
$errors = 0;
|
|
||||||
$warnings = 0;
|
|
||||||
foreach ($messages as $message) {
|
|
||||||
if ($message->type === 'danger') {
|
|
||||||
$errors++;
|
|
||||||
} else if ($message->type === 'warning') {
|
|
||||||
$warnings++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$readyPercentage = round((count($messages)-$errors)*100/count($messages));
|
|
||||||
|
|
||||||
if ($errors > 0) {
|
|
||||||
$readyClass = 'danger';
|
|
||||||
} else if ($warnings > 0) {
|
|
||||||
$readyClass = 'warning';
|
|
||||||
} else {
|
|
||||||
$readyClass = 'success';
|
|
||||||
}
|
|
||||||
|
|
||||||
usort($messages, 'compareCheckMessage');
|
|
||||||
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="<?=$locale?>">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
|
|
||||||
<title><?=__('Check', 'Installation checking') ?></title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../css/bootstrap.min.css">
|
|
||||||
<link rel="stylesheet" href="../css/style.css">
|
|
||||||
<link rel="stylesheet" href="../css/frama.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container ombre">
|
|
||||||
<div class="row">
|
|
||||||
<form method="get" action="" class="hidden-print">
|
|
||||||
<div class="input-group input-group-sm pull-right col-xs-12 col-sm-2">
|
|
||||||
<select name="lang" class="form-control" title="<?=__('Language selector', 'Select language')?>" >
|
|
||||||
<?php foreach ($ALLOWED_LANGUAGES as $lang_key => $language) { ?>
|
|
||||||
<option lang="fr" <?php if (substr($lang_key, 0, 2)===$locale) { echo 'selected';} ?> value="<?=substr($lang_key, 0, 2)?>"><?=$language?></option>
|
|
||||||
<?php } ?>
|
|
||||||
</select>
|
|
||||||
<span class="input-group-btn">
|
|
||||||
<button type="submit" class="btn btn-default btn-sm" title="<?=__('Language selector', 'Select language')?>">OK</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-12">
|
|
||||||
<h1><?=__('Check', 'Installation checking') ?></h1>
|
|
||||||
<div>
|
|
||||||
<div class="progress">
|
|
||||||
<div class="progress-bar progress-bar-<?= $readyClass ?>" role="progressbar" aria-valuenow="<?= $readyPercentage ?>" aria-valuemin="0" aria-valuemax="100" style="width: <?= $readyPercentage ?>%;">
|
|
||||||
<?= $readyPercentage ?>%
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<?php
|
|
||||||
foreach ($messages as $message) {
|
|
||||||
echo '<div class="alert alert-' . $message->type . '" role="alert">';
|
|
||||||
echo Utils::htmlEscape($message->message);
|
|
||||||
echo '<span class="sr-only">' . $message->type . '</span>';
|
|
||||||
echo '</div>';
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<a class="btn btn-info" role="button" href=""><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> <?= __('Check', 'Check again') ?></a>
|
|
||||||
<?php
|
|
||||||
if (!is_file($conf_filename)) {
|
|
||||||
if ($errors === 0) {
|
|
||||||
?>
|
|
||||||
<a class="btn btn-primary" role="button" href="<?= Utils::get_server_name() . 'admin/install.php' ?>"><span class=" glyphicon glyphicon-arrow-right" aria-hidden="true"></span> <?= __('Check', 'Continue the installation') ?></a>
|
|
||||||
<?php
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
?>
|
|
||||||
<a class="btn btn-primary" role="button" href="<?= Utils::get_server_name() . 'admin/'?>"><span class=" glyphicon glyphicon-arrow-left" aria-hidden="true"></span> <?= __('Admin', 'Back to administration') ?></a>
|
|
||||||
<?php
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
@ -1,29 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
|
|
||||||
use Framadate\Services\LogService;
|
|
||||||
use Framadate\Services\PurgeService;
|
|
||||||
|
|
||||||
include_once __DIR__ . '/../app/inc/init.php';
|
|
||||||
|
|
||||||
$logService = new LogService();
|
|
||||||
$purgeService = new PurgeService($connect, $logService);
|
|
||||||
|
|
||||||
$purgeService->cleanDemoPoll();
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once '../app/inc/init.php';
|
|
||||||
|
|
||||||
$smarty->assign('title', __('Admin', 'Administration'));
|
|
||||||
$smarty->assign('logsAreReadable', is_readable('../' . LOG_FILE));
|
|
||||||
$smarty->display('admin/index.tpl');
|
|
@ -1,50 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
|
|
||||||
use Framadate\Services\InstallService;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
require_once '../app/inc/init.php';
|
|
||||||
|
|
||||||
if (is_file(CONF_FILENAME)) {
|
|
||||||
header(('Location: ' . Utils::get_server_name()));
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$error = null;
|
|
||||||
$result['details'] = null;
|
|
||||||
$installService = new InstallService();
|
|
||||||
|
|
||||||
if (!empty($_POST)) {
|
|
||||||
$installService->updateFields($_POST);
|
|
||||||
$result = $installService->install($smarty);
|
|
||||||
|
|
||||||
if ($result['status'] === 'OK') {
|
|
||||||
header(('Location: ' . Utils::get_server_name() . 'admin/migration.php'));
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$error = __('Error', $result['code']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$smarty->assign('error', $error);
|
|
||||||
$smarty->assign('error_details', $result['details']);
|
|
||||||
$smarty->assign('title', __('Admin', 'Installation'));
|
|
||||||
$smarty->assign('fields', $installService->getFields());
|
|
||||||
$smarty->display('admin/install.tpl');
|
|
@ -1,29 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once '../app/inc/init.php';
|
|
||||||
|
|
||||||
ob_start();
|
|
||||||
is_readable('../' . LOG_FILE) ? readfile('../' . LOG_FILE) : null;
|
|
||||||
$content = ob_get_clean();
|
|
||||||
|
|
||||||
$smarty->assign('logs', $content);
|
|
||||||
$smarty->assign('title', __('Admin', 'Logs'));
|
|
||||||
|
|
||||||
$smarty->display('admin/logs.tpl');
|
|
@ -1,80 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Migrations\Configuration\Configuration;
|
|
||||||
use Doctrine\DBAL\Migrations\Migration;
|
|
||||||
use Doctrine\DBAL\Migrations\OutputWriter;
|
|
||||||
use Doctrine\DBAL\Migrations\Tools\Console\Helper\MigrationStatusInfosHelper;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../app/inc/init.php';
|
|
||||||
|
|
||||||
class MigrationLogger {
|
|
||||||
private $log;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$this->log = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addLine($message)
|
|
||||||
{
|
|
||||||
$this->log .= $message . "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLog()
|
|
||||||
{
|
|
||||||
return $this->log;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$executing = false;
|
|
||||||
$migration = null;
|
|
||||||
$output = '';
|
|
||||||
|
|
||||||
if (isset($_POST['execute'])) {
|
|
||||||
$executing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$migrationsDirectory = __DIR__ . '/../app/classes/Framadate/Migrations';
|
|
||||||
$log = new MigrationLogger();
|
|
||||||
|
|
||||||
$configuration = new Configuration($connect, new OutputWriter(function ($message) use ($log) {
|
|
||||||
$log->addLine($message);
|
|
||||||
}));
|
|
||||||
$configuration->setMigrationsTableName(Utils::table(MIGRATION_TABLE) . '_new');
|
|
||||||
$configuration->setMigrationsDirectory($migrationsDirectory);
|
|
||||||
$configuration->setMigrationsNamespace('DoctrineMigrations');
|
|
||||||
$configuration->registerMigrationsFromDirectory($migrationsDirectory);
|
|
||||||
|
|
||||||
if ($executing) {
|
|
||||||
$migration = new Migration($configuration);
|
|
||||||
$migration->migrate();
|
|
||||||
$output = trim(strip_tags($log->getLog()));
|
|
||||||
}
|
|
||||||
$infos = (new MigrationStatusInfosHelper($configuration))->getMigrationsInfos();
|
|
||||||
|
|
||||||
$smarty->assign('countTotal', $infos['Available Migrations']);
|
|
||||||
$smarty->assign('countExecuted', $infos['Executed Migrations']);
|
|
||||||
$smarty->assign('countWaiting', $infos['New Migrations']);
|
|
||||||
$smarty->assign('executing', $executing);
|
|
||||||
$smarty->assign('title', __('Admin', 'Migration'));
|
|
||||||
$smarty->assign('output', $output);
|
|
||||||
$smarty->assign('time', round((microtime(true)-$_SERVER['REQUEST_TIME_FLOAT']), 4));
|
|
||||||
$smarty->display('admin/migration.tpl');
|
|
101
admin/polls.php
101
admin/polls.php
@ -1,101 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
|
|
||||||
use Framadate\Services\AdminPollService;
|
|
||||||
use Framadate\Services\LogService;
|
|
||||||
use Framadate\Services\PollService;
|
|
||||||
use Framadate\Services\SecurityService;
|
|
||||||
use Framadate\Services\SuperAdminService;
|
|
||||||
|
|
||||||
include_once __DIR__ . '/../app/inc/init.php';
|
|
||||||
include_once __DIR__ . '/../bandeaux.php';
|
|
||||||
|
|
||||||
const POLLS_PER_PAGE = 30;
|
|
||||||
|
|
||||||
/* Functions */
|
|
||||||
|
|
||||||
function buildSearchQuery($search) {
|
|
||||||
$query = '';
|
|
||||||
foreach ($search as $key => $value) {
|
|
||||||
$query .= $key . '=' . urlencode($value) . '&';
|
|
||||||
}
|
|
||||||
return substr($query, 0, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --------- */
|
|
||||||
|
|
||||||
/* Variables */
|
|
||||||
/* --------- */
|
|
||||||
|
|
||||||
$polls = null;
|
|
||||||
$poll_to_delete = null;
|
|
||||||
|
|
||||||
/* Services */
|
|
||||||
/*----------*/
|
|
||||||
|
|
||||||
$logService = new LogService();
|
|
||||||
$pollService = new PollService($connect, $logService);
|
|
||||||
$adminPollService = new AdminPollService($connect, $pollService, $logService);
|
|
||||||
$superAdminService = new SuperAdminService();
|
|
||||||
$securityService = new SecurityService();
|
|
||||||
|
|
||||||
/* GET */
|
|
||||||
/*-----*/
|
|
||||||
$page = (int)filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT);
|
|
||||||
$page = ($page >= 1) ? $page : 1;
|
|
||||||
|
|
||||||
// Search
|
|
||||||
$search['poll'] = filter_input(INPUT_GET, 'poll', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
|
|
||||||
$search['title'] = filter_input(INPUT_GET, 'title', FILTER_SANITIZE_STRING);
|
|
||||||
$search['name'] = filter_input(INPUT_GET, 'name', FILTER_SANITIZE_STRING);
|
|
||||||
$search['mail'] = filter_input(INPUT_GET, 'mail', FILTER_SANITIZE_STRING);
|
|
||||||
|
|
||||||
/* 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($search, $page - 1, POLLS_PER_PAGE);
|
|
||||||
$polls = $found['polls'];
|
|
||||||
$count = $found['count'];
|
|
||||||
$total = $found['total'];
|
|
||||||
|
|
||||||
// Assign data to template
|
|
||||||
$smarty->assign('polls', $polls);
|
|
||||||
$smarty->assign('count', $count);
|
|
||||||
$smarty->assign('total', $total);
|
|
||||||
$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->assign('search', $search);
|
|
||||||
$smarty->assign('search_query', buildSearchQuery($search));
|
|
||||||
|
|
||||||
$smarty->assign('title', __('Admin', 'Polls'));
|
|
||||||
|
|
||||||
$smarty->display('admin/polls.tpl');
|
|
@ -1,60 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
|
|
||||||
use Framadate\Services\InputService;
|
|
||||||
use Framadate\Services\LogService;
|
|
||||||
use Framadate\Services\PurgeService;
|
|
||||||
use Framadate\Services\SecurityService;
|
|
||||||
|
|
||||||
include_once __DIR__ . '/../app/inc/init.php';
|
|
||||||
include_once __DIR__ . '/../bandeaux.php';
|
|
||||||
|
|
||||||
/* Variables */
|
|
||||||
/* --------- */
|
|
||||||
|
|
||||||
$message = null;
|
|
||||||
|
|
||||||
/* Services */
|
|
||||||
/*----------*/
|
|
||||||
|
|
||||||
$logService = new LogService();
|
|
||||||
$purgeService = new PurgeService($connect, $logService);
|
|
||||||
$securityService = new SecurityService();
|
|
||||||
$inputService = new InputService();
|
|
||||||
|
|
||||||
/* POST */
|
|
||||||
/*-----*/
|
|
||||||
|
|
||||||
$action = $inputService->filterName(isset($_POST['action']) ? $_POST['action'] : null);
|
|
||||||
|
|
||||||
/* PAGE */
|
|
||||||
/* ---- */
|
|
||||||
|
|
||||||
if ($action === 'purge' && $securityService->checkCsrf('admin', $_POST['csrf'])) {
|
|
||||||
$count = $purgeService->purgeOldPolls();
|
|
||||||
$message = __('Admin', 'Purged:') . ' ' . $count;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assign data to template
|
|
||||||
$smarty->assign('message', $message);
|
|
||||||
$smarty->assign('crsf', $securityService->getToken('admin'));
|
|
||||||
|
|
||||||
$smarty->assign('title', __('Admin', 'Purge'));
|
|
||||||
|
|
||||||
$smarty->display('admin/purge.tpl');
|
|
510
adminstuds.php
510
adminstuds.php
@ -1,510 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
use Framadate\Editable;
|
|
||||||
use Framadate\Exception\AlreadyExistsException;
|
|
||||||
use Framadate\Exception\ConcurrentEditionException;
|
|
||||||
use Framadate\Exception\ConcurrentVoteException;
|
|
||||||
use Framadate\Exception\MomentAlreadyExistsException;
|
|
||||||
use Framadate\Message;
|
|
||||||
use Framadate\Security\PasswordHasher;
|
|
||||||
use Framadate\Services\AdminPollService;
|
|
||||||
use Framadate\Services\InputService;
|
|
||||||
use Framadate\Services\LogService;
|
|
||||||
use Framadate\Services\MailService;
|
|
||||||
use Framadate\Services\NotificationService;
|
|
||||||
use Framadate\Services\PollService;
|
|
||||||
use Framadate\Services\SessionService;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
include_once __DIR__ . '/app/inc/init.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();
|
|
||||||
$mailService = new MailService($config['use_smtp'], $config['smtp_options'], $config['use_sendmail']);
|
|
||||||
$notificationService = new NotificationService($mailService);
|
|
||||||
$sessionService = new SessionService();
|
|
||||||
|
|
||||||
/* PAGE */
|
|
||||||
/* ---- */
|
|
||||||
|
|
||||||
if (!empty($_GET['poll'])) {
|
|
||||||
$admin_poll_id = filter_input(INPUT_GET, 'poll', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
|
|
||||||
if (strlen($admin_poll_id) === 24) {
|
|
||||||
$poll = $pollService->findByAdminId($admin_poll_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($poll) {
|
|
||||||
$poll_id = $poll->id;
|
|
||||||
} else {
|
|
||||||
$smarty->assign('error', __('Error', "This poll doesn't exist!"));
|
|
||||||
$smarty->display('error.tpl');
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------
|
|
||||||
// creation message
|
|
||||||
// -------------------------------
|
|
||||||
|
|
||||||
$messagePollCreated = $sessionService->get("Framadate", "messagePollCreated", FALSE);
|
|
||||||
|
|
||||||
if ($messagePollCreated) {
|
|
||||||
$sessionService->remove("Framadate", "messagePollCreated");
|
|
||||||
|
|
||||||
$message = new Message('success', __('adminstuds', 'The poll was created.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------
|
|
||||||
// Update poll info
|
|
||||||
// -------------------------------
|
|
||||||
|
|
||||||
if (isset($_POST['update_poll_info'])) {
|
|
||||||
$updated = false;
|
|
||||||
$field = $inputService->filterAllowedValues($_POST['update_poll_info'], ['title', 'admin_mail', 'description',
|
|
||||||
'rules', 'expiration_date', 'name', 'hidden', 'removePassword', 'password']);
|
|
||||||
|
|
||||||
// Update the right poll field
|
|
||||||
if ($field === 'title') {
|
|
||||||
$title = $inputService->filterTitle($_POST['title']);
|
|
||||||
if ($title) {
|
|
||||||
$poll->title = $title;
|
|
||||||
$updated = true;
|
|
||||||
}
|
|
||||||
} elseif ($field === 'admin_mail') {
|
|
||||||
$admin_mail = $inputService->filterMail($_POST['admin_mail']);
|
|
||||||
if ($admin_mail) {
|
|
||||||
$poll->admin_mail = $admin_mail;
|
|
||||||
$updated = true;
|
|
||||||
}
|
|
||||||
} elseif ($field === 'description') {
|
|
||||||
$description = $inputService->filterDescription($_POST['description']);
|
|
||||||
if ($description) {
|
|
||||||
$poll->description = $description;
|
|
||||||
$updated = true;
|
|
||||||
}
|
|
||||||
} elseif ($field === 'rules') {
|
|
||||||
$rules = strip_tags($_POST['rules']);
|
|
||||||
switch ($rules) {
|
|
||||||
case 0:
|
|
||||||
$poll->active = false;
|
|
||||||
$poll->editable = Editable::NOT_EDITABLE;
|
|
||||||
$updated = true;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
$poll->active = true;
|
|
||||||
$poll->editable = Editable::NOT_EDITABLE;
|
|
||||||
$updated = true;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
$poll->active = true;
|
|
||||||
$poll->editable = Editable::EDITABLE_BY_ALL;
|
|
||||||
$updated = true;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
$poll->active = true;
|
|
||||||
$poll->editable = Editable::EDITABLE_BY_OWN;
|
|
||||||
$updated = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} elseif ($field === 'expiration_date') {
|
|
||||||
$expiration_date = $inputService->filterDate($_POST['expiration_date']);
|
|
||||||
if ($expiration_date) {
|
|
||||||
$poll->end_date = $expiration_date;
|
|
||||||
$updated = true;
|
|
||||||
}
|
|
||||||
} elseif ($field === 'name') {
|
|
||||||
$admin_name = $inputService->filterName($_POST['name']);
|
|
||||||
if ($admin_name) {
|
|
||||||
$poll->admin_name = $admin_name;
|
|
||||||
$updated = true;
|
|
||||||
}
|
|
||||||
} elseif ($field === 'hidden') {
|
|
||||||
$hidden = isset($_POST['hidden']) ? $inputService->filterBoolean($_POST['hidden']) : false;
|
|
||||||
if ($hidden !== $poll->hidden) {
|
|
||||||
$poll->hidden = $hidden;
|
|
||||||
$poll->results_publicly_visible = false;
|
|
||||||
$updated = true;
|
|
||||||
}
|
|
||||||
} elseif ($field === 'removePassword') {
|
|
||||||
$removePassword = isset($_POST['removePassword']) ? $inputService->filterBoolean($_POST['removePassword']) : false;
|
|
||||||
if ($removePassword) {
|
|
||||||
$poll->results_publicly_visible = false;
|
|
||||||
$poll->password_hash = null;
|
|
||||||
$updated = true;
|
|
||||||
}
|
|
||||||
} elseif ($field === 'password') {
|
|
||||||
$password = isset($_POST['password']) ? $_POST['password'] : null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Did the user choose results to be publicly visible ?
|
|
||||||
*/
|
|
||||||
$resultsPubliclyVisible = isset($_POST['resultsPubliclyVisible']) ? $inputService->filterBoolean($_POST['resultsPubliclyVisible']) : false;
|
|
||||||
/**
|
|
||||||
* If there's one, save the password
|
|
||||||
*/
|
|
||||||
if (!empty($password)) {
|
|
||||||
$poll->password_hash = PasswordHasher::hash($password);
|
|
||||||
$updated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If not pasword was set and the poll should be hidden, hide the results
|
|
||||||
*/
|
|
||||||
if ($poll->password_hash === null || $poll->hidden === true) {
|
|
||||||
$poll->results_publicly_visible = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We don't have a password, the poll is hidden and we change the results public visibility
|
|
||||||
*/
|
|
||||||
if ($resultsPubliclyVisible !== $poll->results_publicly_visible && $poll->password_hash !== null && $poll->hidden === false) {
|
|
||||||
$poll->results_publicly_visible = $resultsPubliclyVisible;
|
|
||||||
$updated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update poll in database
|
|
||||||
if ($updated && $adminPollService->updatePoll($poll)) {
|
|
||||||
$message = new Message('success', __('adminstuds', 'Poll saved'));
|
|
||||||
$notificationService->sendUpdateNotification($poll, NotificationService::UPDATE_POLL);
|
|
||||||
} else {
|
|
||||||
$message = new Message('danger', __('Error', 'Failed to save poll'));
|
|
||||||
$poll = $pollService->findById($poll_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------
|
|
||||||
// A vote is going to be edited
|
|
||||||
// -------------------------------
|
|
||||||
|
|
||||||
if (!empty($_GET['vote'])) {
|
|
||||||
$editingVoteId = filter_input(INPUT_GET, 'vote', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------
|
|
||||||
// Something to save (edit or add)
|
|
||||||
// -------------------------------
|
|
||||||
|
|
||||||
$selectedNewVotes = [];
|
|
||||||
|
|
||||||
if (!empty($_POST['save'])) { // Save edition of an old vote
|
|
||||||
$name = $inputService->filterName($_POST['name']);
|
|
||||||
if(empty($_POST['mail']) || $inputService->filterMail($_POST['mail'])===false) {
|
|
||||||
$mail = null;
|
|
||||||
} else {
|
|
||||||
$mail = $inputService->filterMail($_POST['mail']);
|
|
||||||
}
|
|
||||||
$editedVote = filter_input(INPUT_POST, 'save', FILTER_VALIDATE_INT);
|
|
||||||
$choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]);
|
|
||||||
$slots_hash = $inputService->filterMD5($_POST['control']);
|
|
||||||
|
|
||||||
if (empty($editedVote)) {
|
|
||||||
$message = new Message('danger', __('Error', 'Something has gone wrong...'));
|
|
||||||
}
|
|
||||||
if (count($choices) !== count($_POST['choices'])) {
|
|
||||||
$message = new Message('danger', __('Error', 'There is a problem with your choices'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($message === null) {
|
|
||||||
// Update vote
|
|
||||||
try {
|
|
||||||
$result = $pollService->updateVote($poll_id, $editedVote, $name, $choices, $slots_hash, $mail);
|
|
||||||
if ($result) {
|
|
||||||
$message = new Message('success', __('adminstuds', 'Vote updated'));
|
|
||||||
} else {
|
|
||||||
$message = new Message('danger', __('Error', 'Update vote failed'));
|
|
||||||
}
|
|
||||||
} catch (AlreadyExistsException $aee) {
|
|
||||||
$message = new Message('danger', __('Error', "The name you've chosen already exists in this poll!"));
|
|
||||||
} catch (ConcurrentEditionException $cee) {
|
|
||||||
$message = new Message('danger', __('Error', 'Poll has been updated before you vote'));
|
|
||||||
} catch (ConcurrentVoteException $cve) {
|
|
||||||
$message = new Message('danger', __('Error', "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} elseif (isset($_POST['save'])) { // Add a new vote
|
|
||||||
$name = $inputService->filterName($_POST['name']);
|
|
||||||
if(empty($_POST['mail']) || $inputService->filterMail($_POST['mail'])===false) {
|
|
||||||
$mail = null;
|
|
||||||
} else {
|
|
||||||
$mail = $inputService->filterMail($_POST['mail']);
|
|
||||||
}
|
|
||||||
$choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]);
|
|
||||||
$slots_hash = $inputService->filterMD5($_POST['control']);
|
|
||||||
|
|
||||||
if ($name === null) {
|
|
||||||
$message = new Message('danger', __('Error', 'The name is invalid.'));
|
|
||||||
}
|
|
||||||
if (count($choices) !== count($_POST['choices'])) {
|
|
||||||
$message = new Message('danger', __('Error', 'There is a problem with your choices'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($message === null) {
|
|
||||||
// Add vote
|
|
||||||
try {
|
|
||||||
$result = $pollService->addVote($poll_id, $name, $choices, $slots_hash, $mail);
|
|
||||||
if ($result) {
|
|
||||||
$message = new Message('success', __('adminstuds', 'Vote added'));
|
|
||||||
} else {
|
|
||||||
$message = new Message('danger', __('Error', 'Adding vote failed'));
|
|
||||||
}
|
|
||||||
} catch (AlreadyExistsException $aee) {
|
|
||||||
$message = new Message('danger', __('Error', 'You already voted'));
|
|
||||||
$selectedNewVotes = $choices;
|
|
||||||
} catch (ConcurrentEditionException $cee) {
|
|
||||||
$message = new Message('danger', __('Error', 'Poll has been updated before you vote'));
|
|
||||||
} catch (ConcurrentVoteException $cve) {
|
|
||||||
$message = new Message('danger', __('Error', "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------
|
|
||||||
// Delete a votes
|
|
||||||
// -------------------------------
|
|
||||||
|
|
||||||
if (!empty($_GET['delete_vote'])) {
|
|
||||||
$vote_id = filter_input(INPUT_GET, 'delete_vote', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BASE64_REGEX]]);
|
|
||||||
$vote_id = Utils::base64url_decode($vote_id);
|
|
||||||
if ($vote_id && $adminPollService->deleteVote($poll_id, $vote_id)) {
|
|
||||||
$message = new Message('success', __('adminstuds', 'Vote deleted'));
|
|
||||||
} else {
|
|
||||||
$message = new Message('danger', __('Error', 'Failed to delete the vote!'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------
|
|
||||||
// Remove all votes
|
|
||||||
// -------------------------------
|
|
||||||
|
|
||||||
if (isset($_POST['remove_all_votes'])) {
|
|
||||||
$smarty->assign('poll_id', $poll_id);
|
|
||||||
$smarty->assign('admin_poll_id', $admin_poll_id);
|
|
||||||
$smarty->assign('title', __('Generic', 'Poll') . ' - ' . $poll->title);
|
|
||||||
$smarty->display('confirm/delete_votes.tpl');
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
if (isset($_POST['confirm_remove_all_votes'])) {
|
|
||||||
if ($adminPollService->cleanVotes($poll_id)) {
|
|
||||||
$message = new Message('success', __('adminstuds', 'All votes deleted'));
|
|
||||||
} else {
|
|
||||||
$message = new Message('danger', __('Error', 'Failed to delete all votes'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------
|
|
||||||
// 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', __('adminstuds', 'Comment deleted'));
|
|
||||||
} else {
|
|
||||||
$message = new Message('danger', __('Error', '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', __('Generic', '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', __('adminstuds', 'All comments deleted'));
|
|
||||||
} else {
|
|
||||||
$message = new Message('danger', __('Error', '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', __('Generic', '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', __('adminstuds', 'Poll fully deleted'));
|
|
||||||
$notificationService->sendUpdateNotification($poll, NotificationService::DELETED_POLL);
|
|
||||||
} else {
|
|
||||||
$message = new Message('danger', __('Error', 'Failed to delete the poll'));
|
|
||||||
}
|
|
||||||
$smarty->assign('poll_id', $poll_id);
|
|
||||||
$smarty->assign('admin_poll_id', $admin_poll_id);
|
|
||||||
$smarty->assign('title', __('Generic', 'Poll') . ' - ' . $poll->title);
|
|
||||||
$smarty->assign('message', $message);
|
|
||||||
$smarty->display('poll_deleted.tpl');
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------
|
|
||||||
// Delete a slot
|
|
||||||
// -------------------------------
|
|
||||||
|
|
||||||
if (isset($_GET['delete_column'])) {
|
|
||||||
$column = filter_input(INPUT_GET, 'delete_column', FILTER_DEFAULT);
|
|
||||||
$column = Utils::base64url_decode($column);
|
|
||||||
|
|
||||||
if ($poll->format === 'D') {
|
|
||||||
$ex = explode('@', $column);
|
|
||||||
|
|
||||||
$slot = new stdClass();
|
|
||||||
$slot->title = $ex[0];
|
|
||||||
$slot->moment = $ex[1];
|
|
||||||
|
|
||||||
$result = $adminPollService->deleteDateSlot($poll, $slot);
|
|
||||||
} else {
|
|
||||||
$result = $adminPollService->deleteClassicSlot($poll, $column);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($result) {
|
|
||||||
$message = new Message('success', __('adminstuds', 'Column deleted'));
|
|
||||||
} else {
|
|
||||||
$message = new Message('danger', __('Error', 'Failed to delete column'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------
|
|
||||||
// Collect the mails of a column
|
|
||||||
// -------------------------------
|
|
||||||
|
|
||||||
if (isset($_GET['collect_mail'])) {
|
|
||||||
$column_str = strval(filter_input(INPUT_GET, 'collect_mail', FILTER_DEFAULT));
|
|
||||||
$column_str = strval(Utils::base64url_decode($column_str));
|
|
||||||
$column = intval($column_str);
|
|
||||||
$votes = $pollService->splitVotes($pollService->allVotesByPollId($poll_id));
|
|
||||||
$mails_yes = $mails_ifneedbe = $mails_no = [];
|
|
||||||
foreach ($votes as $vote) {
|
|
||||||
if (intval($vote->choices[$column]) === 2 && $vote->mail !== NULL) {
|
|
||||||
$mails_yes[] = $vote->mail;
|
|
||||||
} elseif (intval($vote->choices[$column]) === 1 && $vote->mail !== NULL) {
|
|
||||||
$mails_ifneedbe[] = $vote->mail;
|
|
||||||
} elseif($vote->mail !== NULL) {
|
|
||||||
$mails_no[] = $vote->mail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$smarty->assign('poll_id', $poll_id);
|
|
||||||
$smarty->assign('admin_poll_id', $admin_poll_id);
|
|
||||||
$smarty->assign('admin', true);
|
|
||||||
$smarty->assign('title', __('Generic', 'Poll') . ' - ' . $poll->title . ' - ' . __('adminstuds', 'Collect the emails of the polled users for the choice'));
|
|
||||||
$smarty->assign('mails_yes', $mails_yes);
|
|
||||||
$smarty->assign('mails_ifneedbe', $mails_ifneedbe);
|
|
||||||
$smarty->assign('mails_no', $mails_no);
|
|
||||||
$smarty->display('display_mails.tpl');
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------
|
|
||||||
// Add a slot
|
|
||||||
// -------------------------------
|
|
||||||
|
|
||||||
function exit_displaying_add_column($message = null) {
|
|
||||||
global $smarty, $poll_id, $admin_poll_id, $poll;
|
|
||||||
$smarty->assign('poll_id', $poll_id);
|
|
||||||
$smarty->assign('admin_poll_id', $admin_poll_id);
|
|
||||||
$smarty->assign('format', $poll->format);
|
|
||||||
$smarty->assign('title', __('Generic', 'Poll') . ' - ' . $poll->title);
|
|
||||||
$smarty->assign('message', $message);
|
|
||||||
$smarty->display('add_column.tpl');
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($_GET['add_column'])) {
|
|
||||||
exit_displaying_add_column();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($_POST['confirm_add_column'])) {
|
|
||||||
try {
|
|
||||||
if (($poll->format === 'D' && empty($_POST['newdate']))
|
|
||||||
|| ($poll->format === 'A' && empty($_POST['choice']))) {
|
|
||||||
exit_displaying_add_column(new Message('danger', __('Error', "Can't create an empty column.")));
|
|
||||||
}
|
|
||||||
if ($poll->format === 'D') {
|
|
||||||
$date = DateTime::createFromFormat(__('Date', 'Y-m-d'), $_POST['newdate'])->setTime(0, 0, 0);
|
|
||||||
$time = $date->getTimestamp();
|
|
||||||
$newmoment = str_replace(',', '-', strip_tags($_POST['newmoment']));
|
|
||||||
$adminPollService->addDateSlot($poll_id, $time, $newmoment);
|
|
||||||
} else {
|
|
||||||
$newslot = str_replace(',', '-', strip_tags($_POST['choice']));
|
|
||||||
$adminPollService->addClassicSlot($poll_id, $newslot);
|
|
||||||
}
|
|
||||||
|
|
||||||
$message = new Message('success', __('adminstuds', 'Choice added'));
|
|
||||||
} catch (MomentAlreadyExistsException $e) {
|
|
||||||
exit_displaying_add_column(new Message('danger', __('Error', 'The column already exists')));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve data
|
|
||||||
$slots = $pollService->allSlotsByPoll($poll);
|
|
||||||
$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', __('Generic', 'Poll') . ' - ' . $poll->title);
|
|
||||||
$smarty->assign('expired', strtotime($poll->end_date) < time());
|
|
||||||
$smarty->assign('deletion_date', strtotime($poll->end_date) + PURGE_DELAY * 86400);
|
|
||||||
$smarty->assign('slots', $poll->format === 'D' ? $pollService->splitSlots($slots) : $slots);
|
|
||||||
$smarty->assign('slots_hash', $pollService->hashSlots($slots));
|
|
||||||
$smarty->assign('votes', $pollService->splitVotes($votes));
|
|
||||||
$smarty->assign('best_choices', $pollService->computeBestChoices($votes, $poll));
|
|
||||||
$smarty->assign('comments', $comments);
|
|
||||||
$smarty->assign('editingVoteId', $editingVoteId);
|
|
||||||
$smarty->assign('message', $message);
|
|
||||||
$smarty->assign('admin', true);
|
|
||||||
$smarty->assign('hidden', false);
|
|
||||||
$smarty->assign('accessGranted', true);
|
|
||||||
$smarty->assign('resultPubliclyVisible', true);
|
|
||||||
$smarty->assign('editedVoteUniqueId', '');
|
|
||||||
$smarty->assign('default_to_marldown_editor', $config['markdown_editor_by_default']);
|
|
||||||
$smarty->assign('selectedNewVotes', $selectedNewVotes);
|
|
||||||
|
|
||||||
$smarty->display('studs.tpl');
|
|
@ -1,54 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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 Doctrine\DBAL\Migrations\AbstractMigration as DoctrineAbstractMigration;
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
|
|
||||||
abstract class AbstractMigration extends DoctrineAbstractMigration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @param $class
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function legacyCheck(Schema $schema, $class)
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* If there's no legacy table, we can go on
|
|
||||||
*/
|
|
||||||
if (!$schema->hasTable(Utils::table(MIGRATION_TABLE))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$migration_table = $schema->getTable(Utils::table(MIGRATION_TABLE));
|
|
||||||
/**
|
|
||||||
* We check the migration table
|
|
||||||
*/
|
|
||||||
if ($migration_table->hasColumn('name')) {
|
|
||||||
/** @var $stmt \Doctrine\DBAL\Driver\Statement */
|
|
||||||
$stmt = $this->connection->prepare('SELECT * FROM ' . Utils::table(MIGRATION_TABLE) . ' WHERE name = ?');
|
|
||||||
$stmt->execute([$class]);
|
|
||||||
return $stmt->rowCount() > 0;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
class Choice
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Name of the Choice
|
|
||||||
*/
|
|
||||||
private $name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* All availables slots for this Choice.
|
|
||||||
*/
|
|
||||||
private $slots;
|
|
||||||
|
|
||||||
public function __construct($name='')
|
|
||||||
{
|
|
||||||
$this->name = $name;
|
|
||||||
$this->slots = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class CollectMail
|
|
||||||
*
|
|
||||||
* Is used to specify the poll's edition permissions.
|
|
||||||
* @TODO : wait to use the SplEnum
|
|
||||||
*
|
|
||||||
* @package Framadate
|
|
||||||
*/
|
|
||||||
class CollectMail { // extends SplEnum
|
|
||||||
const NO_COLLECT = 0;
|
|
||||||
const COLLECT = 1;
|
|
||||||
const COLLECT_REQUIRED = 2;
|
|
||||||
const COLLECT_REQUIRED_VERIFIED = 3;
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class Editable
|
|
||||||
*
|
|
||||||
* Is used to specify the poll's edition permissions.
|
|
||||||
* @TODO : wait to use the SplEnum
|
|
||||||
*
|
|
||||||
* @package Framadate
|
|
||||||
*/
|
|
||||||
class Editable { // extends SplEnum
|
|
||||||
const __default = self::EDITABLE_BY_ALL;
|
|
||||||
|
|
||||||
const NOT_EDITABLE = 0;
|
|
||||||
const EDITABLE_BY_ALL = 1;
|
|
||||||
const EDITABLE_BY_OWN = 2;
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Framadate\Exception;
|
|
||||||
|
|
||||||
class AlreadyExistsException extends \Exception {
|
|
||||||
function __construct() {
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Framadate\Exception;
|
|
||||||
|
|
||||||
class ConcurrentEditionException extends \Exception {
|
|
||||||
function __construct() {
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Framadate\Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class ConcurrentVoteException
|
|
||||||
*
|
|
||||||
* Thrown when a poll has a maximum votes constraint for options, and a vote happened since the poll was rendered
|
|
||||||
*/
|
|
||||||
class ConcurrentVoteException extends \Exception {
|
|
||||||
function __construct() {
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Framadate\Exception;
|
|
||||||
|
|
||||||
class MomentAlreadyExistsException extends \Exception {
|
|
||||||
function __construct() {
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,121 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
class Form
|
|
||||||
{
|
|
||||||
public $title;
|
|
||||||
public $id;
|
|
||||||
public $description;
|
|
||||||
public $admin_name;
|
|
||||||
public $admin_mail;
|
|
||||||
public $format;
|
|
||||||
public $end_date;
|
|
||||||
public $choix_sondage;
|
|
||||||
public $ValueMax;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tells if users can modify their choices.
|
|
||||||
* @var \Framadate\Editable
|
|
||||||
*/
|
|
||||||
public $editable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If true, notify poll administrator when new vote is made.
|
|
||||||
*/
|
|
||||||
public $receiveNewVotes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If true, notify poll administrator when new comment is posted.
|
|
||||||
*/
|
|
||||||
public $receiveNewComments;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If true, only the poll maker can see the poll's results
|
|
||||||
* @var boolean
|
|
||||||
*/
|
|
||||||
public $use_ValueMax;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* if true, there will be a limit of voters per option
|
|
||||||
* @var boolean
|
|
||||||
*/
|
|
||||||
public $hidden;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If true, the author want to customize the URL
|
|
||||||
* @var boolean
|
|
||||||
*/
|
|
||||||
public $use_customized_url;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If true, a password will be needed to access the poll
|
|
||||||
* @var boolean
|
|
||||||
*/
|
|
||||||
public $use_password;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The password needed to access the poll, hashed. Only used if $use_password is set to true
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public $password_hash;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If true, the polls results will be also visible for those without password
|
|
||||||
* @var boolean
|
|
||||||
*/
|
|
||||||
public $results_publicly_visible;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tells if voters email addresses are collected or not.
|
|
||||||
* @var \Framadate\CollectMail
|
|
||||||
*/
|
|
||||||
public $collect_users_mail;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of available choices
|
|
||||||
*/
|
|
||||||
private $choices;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$this->editable = Editable::EDITABLE_BY_ALL;
|
|
||||||
$this->collect_users_mail = CollectMail::NO_COLLECT;
|
|
||||||
$this->clearChoices();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function clearChoices() {
|
|
||||||
$this->choices = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addChoice(Choice $choice)
|
|
||||||
{
|
|
||||||
$this->choices[] = $choice;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getChoices()
|
|
||||||
{
|
|
||||||
return $this->choices;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function sortChoices()
|
|
||||||
{
|
|
||||||
usort($this->choices, ['Framadate\Choice', 'compare']);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
class Message {
|
|
||||||
var $type;
|
|
||||||
var $message;
|
|
||||||
var $link;
|
|
||||||
var $linkTitle;
|
|
||||||
var $linkIcon;
|
|
||||||
var $includeTemplate;
|
|
||||||
|
|
||||||
function __construct($type, $message, $link=null, $linkTitle=null, $linkIcon=null, $includeTemplate=null) {
|
|
||||||
$this->type = $type;
|
|
||||||
$this->message = $message;
|
|
||||||
$this->link = $link;
|
|
||||||
$this->linkTitle = $linkTitle;
|
|
||||||
$this->linkIcon = $linkIcon;
|
|
||||||
$this->includeTemplate = $includeTemplate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Framadate\AbstractMigration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class From_0_0_to_0_8_Migration
|
|
||||||
*
|
|
||||||
* @package Framadate\Migration
|
|
||||||
* @version 0.8
|
|
||||||
*/
|
|
||||||
class Version20150101000000 extends AbstractMigration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method should describe in english what is the purpose of the migration class.
|
|
||||||
*
|
|
||||||
* @return string The description of the migration class
|
|
||||||
*/
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
return 'First installation of the Framadate application (v0.8)';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called only one time in the migration page.
|
|
||||||
*
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @throws \Doctrine\DBAL\Migrations\SkipMigrationException
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
* @return void true is the execution succeeded
|
|
||||||
*/
|
|
||||||
public function up(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->skipIf($this->legacyCheck($schema,'Framadate\Migration\From_0_0_to_0_8_Migration'), 'Migration has been executed in an earlier database migration system');
|
|
||||||
$sondage = $schema->createTable('sondage');
|
|
||||||
$sondage->addColumn('id_sondage', 'string');
|
|
||||||
$sondage->addColumn('commentaires', 'text');
|
|
||||||
$sondage->addColumn('mail_admin', 'string', ['notnull' => false]);
|
|
||||||
$sondage->addColumn('nom_admin', 'string', ['notnull' => false]);
|
|
||||||
$sondage->addColumn('titre', 'text');
|
|
||||||
$sondage->addColumn('id_sondage_admin', 'string', ['notnull' => false]);
|
|
||||||
$sondage->addColumn('date_creation', 'datetime', ['default' => (new \DateTime())->format('Y-m-d H:i:s')]);
|
|
||||||
$sondage->addColumn('date_fin', 'datetime', ['notnull' => false]);
|
|
||||||
$sondage->addColumn('format', 'string', ['notnull' => false]);
|
|
||||||
$sondage->addColumn('mailsonde', 'boolean', ['default' => false]);
|
|
||||||
$sondage->addColumn('statut', 'integer', ['default' => '1']);
|
|
||||||
$sondage->addUniqueIndex(['id_sondage'], 'sondage_index_id_sondage');
|
|
||||||
|
|
||||||
$sujetStuds = $schema->createTable('sujet_studs');
|
|
||||||
$sujetStuds->addColumn('id_sondage', 'string');
|
|
||||||
$sujetStuds->addColumn('sujet', 'text');
|
|
||||||
$sujetStuds->addIndex(['id_sondage'], 'sujet_studs_index_id_sondage');
|
|
||||||
|
|
||||||
$comments = $schema->createTable('comments');
|
|
||||||
$schema->createSequence('comments_seq');
|
|
||||||
$comments->addColumn('id_comment', 'integer', ['autoincrement' => true]);
|
|
||||||
$comments->addColumn('id_sondage', 'string');
|
|
||||||
$comments->addColumn('comment', 'text');
|
|
||||||
$comments->addColumn('usercomment', 'text', ['notnull' => false]);
|
|
||||||
$comments->addUniqueIndex(['id_comment'], 'comments_index_id_comment');
|
|
||||||
$comments->addIndex(['id_sondage'], 'comments_index_id_sondage');
|
|
||||||
|
|
||||||
$userStuds = $schema->createTable('user_studs');
|
|
||||||
$schema->createSequence('user_studs_seq');
|
|
||||||
$userStuds->addColumn('id_users', 'integer', ['autoincrement' => true]);
|
|
||||||
$userStuds->addColumn('nom', 'string');
|
|
||||||
$userStuds->addColumn('id_sondage', 'string');
|
|
||||||
$userStuds->addColumn('reponses', 'text');
|
|
||||||
$userStuds->addUniqueIndex(['id_users'], 'user_studs_index_id_users');
|
|
||||||
$userStuds->addIndex(['id_sondage'], 'user_studs_index_id_sondage');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->addSql('DROP TABLE sondage');
|
|
||||||
$this->addSql('DROP TABLE sujet_studs');
|
|
||||||
$this->addSql('DROP TABLE comments');
|
|
||||||
$this->addSql('DROP TABLE user_studs');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,160 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Framadate\AbstractMigration;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class executes the aciton in database to migrate data from version 0.8 to 0.9.
|
|
||||||
*
|
|
||||||
* @package Framadate\Migration
|
|
||||||
* @version 0.9
|
|
||||||
*/
|
|
||||||
class Version20150102000000 extends AbstractMigration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method should describe in english what is the purpose of the migration class.
|
|
||||||
*
|
|
||||||
* @return string The description of the migration class
|
|
||||||
*/
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
return 'From 0.8 to 0.9 first part';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @throws \Doctrine\DBAL\Migrations\SkipMigrationException
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
*/
|
|
||||||
public function up(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->skipIf($this->legacyCheck($schema,'Framadate\Migration\From_0_8_to_0_9_Migration'), 'Migration has been executed in an earlier database migration system');
|
|
||||||
foreach (['sondage', 'sujet_studs', 'comments', 'user_studs'] as $table) {
|
|
||||||
$this->skipIf(!$schema->hasTable($table), 'Missing table ' . $table);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->createPollTable($schema);
|
|
||||||
$this->createCommentTable($schema);
|
|
||||||
$this->createSlotTable($schema);
|
|
||||||
$this->createVoteTable($schema);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema)
|
|
||||||
{
|
|
||||||
$sondage = $schema->createTable('sondage');
|
|
||||||
$sondage->addColumn('id_sondage', 'string');
|
|
||||||
$sondage->addColumn('commentaires', 'text');
|
|
||||||
$sondage->addColumn('mail_admin', 'string', ['notnull' => false]);
|
|
||||||
$sondage->addColumn('nom_admin', 'string', ['notnull' => false]);
|
|
||||||
$sondage->addColumn('titre', 'text');
|
|
||||||
$sondage->addColumn('id_sondage_admin', 'string', ['notnull' => false]);
|
|
||||||
$sondage->addColumn('date_creation', 'datetime', ['default' => (new \DateTime())->format('Y-m-d H:i:s')]);
|
|
||||||
$sondage->addColumn('date_fin', 'datetime', ['notnull' => false]);
|
|
||||||
$sondage->addColumn('format', 'string', ['notnull' => false]);
|
|
||||||
$sondage->addColumn('mailsonde', 'boolean', ['default' => false]);
|
|
||||||
$sondage->addColumn('statut', 'integer', ['default' => '1']);
|
|
||||||
$sondage->addUniqueIndex(['id_sondage'], 'sondage_index_id_sondage');
|
|
||||||
|
|
||||||
$sujetStuds = $schema->createTable('sujet_studs');
|
|
||||||
$sujetStuds->addColumn('id_sondage', 'string');
|
|
||||||
$sujetStuds->addColumn('sujet', 'text');
|
|
||||||
$sujetStuds->addIndex(['id_sondage'], 'sujet_studs_index_id_sondage');
|
|
||||||
|
|
||||||
$comments = $schema->createTable('comments');
|
|
||||||
$schema->createSequence('comments_seq');
|
|
||||||
$comments->addColumn('id_comment', 'integer', ['autoincrement' => true]);
|
|
||||||
$comments->addColumn('id_sondage', 'string');
|
|
||||||
$comments->addColumn('comment', 'text');
|
|
||||||
$comments->addColumn('usercomment', 'text', ['notnull' => false]);
|
|
||||||
$comments->addUniqueIndex(['id_comment'], 'comments_index_id_comment');
|
|
||||||
$comments->addIndex(['id_sondage'], 'comments_index_id_sondage');
|
|
||||||
|
|
||||||
$userStuds = $schema->createTable('user_studs');
|
|
||||||
$schema->createSequence('user_studs_seq');
|
|
||||||
$userStuds->addColumn('id_users', 'integer', ['autoincrement' => true]);
|
|
||||||
$userStuds->addColumn('nom', 'string');
|
|
||||||
$userStuds->addColumn('id_sondage', 'string');
|
|
||||||
$userStuds->addColumn('reponses', 'text');
|
|
||||||
$userStuds->addUniqueIndex(['id_users'], 'user_studs_index_id_users');
|
|
||||||
$userStuds->addIndex(['id_sondage'], 'user_studs_index_id_sondage');
|
|
||||||
|
|
||||||
$schema->dropTable(Utils::table('poll'));
|
|
||||||
$schema->dropTable(Utils::table('comment'));
|
|
||||||
$schema->dropTable(Utils::table('vote'));
|
|
||||||
$schema->dropTable(Utils::table('slot'));
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createPollTable(Schema $schema)
|
|
||||||
{
|
|
||||||
$poll = $schema->createTable(Utils::table('poll'));
|
|
||||||
$poll->addColumn('id', 'string');
|
|
||||||
$poll->addColumn('admin_id', 'string');
|
|
||||||
$poll->addColumn('title', 'text');
|
|
||||||
$poll->addColumn('description', 'text', ['notnull' => false]);
|
|
||||||
$poll->addColumn('admin_name', 'string');
|
|
||||||
$poll->addColumn('admin_mail', 'string', ['notnull' => false]);
|
|
||||||
$poll->addColumn('creation_date', 'datetime', ['default' => (new \DateTime())->format('Y-m-d H:i:s')]);
|
|
||||||
$poll->addColumn('end_date', 'datetime', ['notnull' => false]);
|
|
||||||
$poll->addColumn('format', 'string', ['default' => null, 'notnull' => false]);
|
|
||||||
$poll->addColumn('editable', 'integer', ['default' => 0]);
|
|
||||||
$poll->addColumn('receiveNewVotes', 'boolean', ['default' => false]);
|
|
||||||
$poll->addColumn('active', 'boolean', ['default' => true]);
|
|
||||||
$poll->addUniqueIndex(['id'], 'poll_index_id');
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createSlotTable(Schema $schema)
|
|
||||||
{
|
|
||||||
$slot = $schema->createTable(Utils::table('slot'));
|
|
||||||
$schema->createSequence('slot_seq');
|
|
||||||
$slot->addColumn('id', 'integer', ['autoincrement' => true]);
|
|
||||||
$slot->addColumn('poll_id', 'string');
|
|
||||||
$slot->addColumn('title', 'text');
|
|
||||||
$slot->addColumn('moments', 'text', ['notnull' => false]);
|
|
||||||
$slot->addUniqueIndex(['id'], 'slot_index_id');
|
|
||||||
$slot->addIndex(['poll_id'], 'slot_index_poll_id');
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createCommentTable(Schema $schema)
|
|
||||||
{
|
|
||||||
$comment = $schema->createTable(Utils::table('comment'));
|
|
||||||
$schema->createSequence('comment_seq');
|
|
||||||
$comment->addColumn('id', 'integer', ['autoincrement' => true]);
|
|
||||||
$comment->addColumn('poll_id', 'string');
|
|
||||||
$comment->addColumn('name', 'text', ['notnull' => false]);
|
|
||||||
$comment->addColumn('comment', 'text');
|
|
||||||
$comment->addUniqueIndex(['id'], 'comment_index_id');
|
|
||||||
$comment->addIndex(['poll_id'], 'comment_index_poll_id');
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createVoteTable(Schema $schema)
|
|
||||||
{
|
|
||||||
$vote = $schema->createTable(Utils::table('vote'));
|
|
||||||
$schema->createSequence('vote_seq');
|
|
||||||
$vote->addColumn('id', 'integer', ['autoincrement' => true]);
|
|
||||||
$vote->addColumn('poll_id', 'string');
|
|
||||||
$vote->addColumn('name', 'string');
|
|
||||||
$vote->addColumn('choices', 'string');
|
|
||||||
$vote->addUniqueIndex(['id'], 'vote_index_id');
|
|
||||||
$vote->addIndex(['poll_id'], 'vote_index_poll_id');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,263 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Framadate\AbstractMigration;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class executes the aciton in database to migrate data from version 0.8 to 0.9.
|
|
||||||
*
|
|
||||||
* @package Framadate\Migration
|
|
||||||
* @version 0.9
|
|
||||||
*/
|
|
||||||
class Version20150102100000 extends AbstractMigration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method should describe in english what is the purpose of the migration class.
|
|
||||||
*
|
|
||||||
* @return string The description of the migration class
|
|
||||||
*/
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
return 'From 0.8 to 0.9 second part';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @throws \Doctrine\DBAL\Migrations\SkipMigrationException
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
*/
|
|
||||||
public function up(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->skipIf($this->legacyCheck($schema,'Framadate\Migration\From_0_8_to_0_9_Migration'), 'Migration has been executed in an earlier database migration system');
|
|
||||||
foreach ([Utils::table('poll'), Utils::table('comment'), Utils::table('slot'), Utils::table('vote')] as $table) {
|
|
||||||
$this->skipIf(!$schema->hasTable($table), 'Missing table ' . $table);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->migrateFromSondageToPoll();
|
|
||||||
$this->migrateFromCommentsToComment();
|
|
||||||
$this->migrateFromSujetStudsToSlot();
|
|
||||||
//$this->migrateFromUserStudsToVote();
|
|
||||||
|
|
||||||
$this->dropOldTables($schema);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema)
|
|
||||||
{
|
|
||||||
$sondage = $schema->createTable('sondage');
|
|
||||||
$sondage->addColumn('id_sondage', 'string');
|
|
||||||
$sondage->addColumn('commentaires', 'text');
|
|
||||||
$sondage->addColumn('mail_admin', 'string', ['notnull' => false]);
|
|
||||||
$sondage->addColumn('nom_admin', 'string', ['notnull' => false]);
|
|
||||||
$sondage->addColumn('titre', 'text');
|
|
||||||
$sondage->addColumn('id_sondage_admin', 'string', ['notnull' => false]);
|
|
||||||
$sondage->addColumn('date_creation', 'datetime', ['default' => (new \DateTime())->format('Y-m-d H:i:s')]);
|
|
||||||
$sondage->addColumn('date_fin', 'datetime', ['notnull' => false]);
|
|
||||||
$sondage->addColumn('format', 'string', ['notnull' => false]);
|
|
||||||
$sondage->addColumn('mailsonde', 'boolean', ['default' => false]);
|
|
||||||
$sondage->addColumn('statut', 'integer', ['default' => '1']);
|
|
||||||
$sondage->addUniqueIndex(['id_sondage'], 'sondage_index_id_sondage');
|
|
||||||
|
|
||||||
$sujetStuds = $schema->createTable('sujet_studs');
|
|
||||||
$sujetStuds->addColumn('id_sondage', 'string');
|
|
||||||
$sujetStuds->addColumn('sujet', 'text');
|
|
||||||
$sujetStuds->addIndex(['id_sondage'], 'sujet_studs_index_id_sondage');
|
|
||||||
|
|
||||||
$comments = $schema->createTable('comments');
|
|
||||||
$schema->createSequence('comments_seq');
|
|
||||||
$comments->addColumn('id_comment', 'integer', ['autoincrement' => true]);
|
|
||||||
$comments->addColumn('id_sondage', 'string');
|
|
||||||
$comments->addColumn('comment', 'text');
|
|
||||||
$comments->addColumn('usercomment', 'text', ['notnull' => false]);
|
|
||||||
$comments->addUniqueIndex(['id_comment'], 'comments_index_id_comment');
|
|
||||||
$comments->addIndex(['id_sondage'], 'comments_index_id_sondage');
|
|
||||||
|
|
||||||
$userStuds = $schema->createTable('user_studs');
|
|
||||||
$schema->createSequence('user_studs_seq');
|
|
||||||
$userStuds->addColumn('id_users', 'integer', ['autoincrement' => true]);
|
|
||||||
$userStuds->addColumn('nom', 'string');
|
|
||||||
$userStuds->addColumn('id_sondage', 'string');
|
|
||||||
$userStuds->addColumn('reponses', 'text');
|
|
||||||
$userStuds->addUniqueIndex(['id_users'], 'user_studs_index_id_users');
|
|
||||||
$userStuds->addIndex(['id_sondage'], 'user_studs_index_id_sondage');
|
|
||||||
|
|
||||||
$schema->dropTable(Utils::table('poll'));
|
|
||||||
$schema->dropTable(Utils::table('comment'));
|
|
||||||
$schema->dropTable(Utils::table('vote'));
|
|
||||||
$schema->dropTable(Utils::table('slot'));
|
|
||||||
}
|
|
||||||
|
|
||||||
private function migrateFromSondageToPoll()
|
|
||||||
{
|
|
||||||
$select = $this->connection->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 = $this->connection->prepare('
|
|
||||||
INSERT INTO ' . Utils::table('poll') . '
|
|
||||||
(id, admin_id, title, description, admin_name, admin_mail, creation_date, end_date, format, editable, receiveNewVotes, active)
|
|
||||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)');
|
|
||||||
|
|
||||||
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 migrateFromSujetStudsToSlot()
|
|
||||||
{
|
|
||||||
$stmt = $this->connection->query('SELECT * FROM sujet_studs');
|
|
||||||
$sujets = $stmt->fetchAll();
|
|
||||||
$slots = [];
|
|
||||||
|
|
||||||
foreach ($sujets as $sujet) {
|
|
||||||
$newSlots = $this->transformSujetToSlot($sujet);
|
|
||||||
foreach ($newSlots as $newSlot) {
|
|
||||||
$slots[] = $newSlot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$prepared = $this->connection->prepare('INSERT INTO ' . Utils::table('slot') . ' (poll_id, title, moments) VALUES (?,?,?)');
|
|
||||||
foreach ($slots as $slot) {
|
|
||||||
$prepared->execute([
|
|
||||||
$slot->poll_id,
|
|
||||||
$this->unescape($slot->title),
|
|
||||||
!empty($slot->moments) ? $this->unescape($slot->moments) : null
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function migrateFromCommentsToComment()
|
|
||||||
{
|
|
||||||
$select = $this->connection->query('
|
|
||||||
SELECT
|
|
||||||
id_sondage,
|
|
||||||
usercomment,
|
|
||||||
comment
|
|
||||||
FROM comments');
|
|
||||||
|
|
||||||
$insert = $this->connection->prepare('
|
|
||||||
INSERT INTO ' . Utils::table('comment') . ' (poll_id, name, comment)
|
|
||||||
VALUES (?,?,?)');
|
|
||||||
|
|
||||||
while ($row = $select->fetch(\PDO::FETCH_OBJ)) {
|
|
||||||
$insert->execute([
|
|
||||||
$row->id_sondage,
|
|
||||||
$this->unescape($row->usercomment),
|
|
||||||
$this->unescape($row->comment)
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function migrateFromUserStudsToVote()
|
|
||||||
{
|
|
||||||
$select = $this->connection->query('
|
|
||||||
SELECT
|
|
||||||
id_sondage,
|
|
||||||
nom,
|
|
||||||
REPLACE(REPLACE(REPLACE(reponses, 1, \'X\'), 2, 1), \'X\', 2) reponses
|
|
||||||
FROM user_studs');
|
|
||||||
|
|
||||||
$insert = $this->connection->prepare('
|
|
||||||
INSERT INTO ' . Utils::table('vote') . ' (poll_id, name, choices)
|
|
||||||
VALUES (?,?,?)');
|
|
||||||
|
|
||||||
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(Schema $schema)
|
|
||||||
{
|
|
||||||
$schema->dropTable('comments');
|
|
||||||
$schema->dropTable('sujet_studs');
|
|
||||||
$schema->dropTable('user_studs');
|
|
||||||
$schema->dropTable('sondage');
|
|
||||||
}
|
|
||||||
|
|
||||||
private function unescape($value)
|
|
||||||
{
|
|
||||||
return stripslashes(html_entity_decode($value, ENT_QUOTES));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,70 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Framadate\AbstractMigration;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This migration adds the field receiveNewComments on the poll table.
|
|
||||||
*
|
|
||||||
* @package Framadate\Migration
|
|
||||||
* @version 0.9
|
|
||||||
*/
|
|
||||||
class Version20150117000000 extends AbstractMigration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method should describe in english what is the purpose of the migration class.
|
|
||||||
*
|
|
||||||
* @return string The description of the migration class
|
|
||||||
*/
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
return 'Add column "receiveNewComments" for version 0.9';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Migrations\SkipMigrationException
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
*/
|
|
||||||
public function up(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->skipIf($this->legacyCheck($schema,'Framadate\Migration\AddColumn_receiveNewComments_For_0_9'), 'Migration has been executed in an earlier database migration system');
|
|
||||||
foreach ([Utils::table('poll'), Utils::table('slot'), Utils::table('vote'), Utils::table('comment')] as $table) {
|
|
||||||
$this->skipIf(!$schema->hasTable($table), 'Missing table ' . $table);
|
|
||||||
}
|
|
||||||
$pollTable = $schema->getTable(Utils::table('poll'));
|
|
||||||
$this->skipIf($pollTable->hasColumn('receiveNewComments'), 'Column receiveNewComments already exists');
|
|
||||||
|
|
||||||
$pollTable->addColumn('receiveNewComments', 'boolean', ['default' => false]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
*/
|
|
||||||
public function down(Schema $schema)
|
|
||||||
{
|
|
||||||
$pollTable = $schema->getTable(Utils::table('poll'));
|
|
||||||
$pollTable->dropColumn('receiveNewComments');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Framadate\AbstractMigration;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This migration adds the field uniqId on the vote table.
|
|
||||||
*
|
|
||||||
* @package Framadate\Migration
|
|
||||||
* @version 0.9
|
|
||||||
*/
|
|
||||||
class Version20150402000000 extends AbstractMigration
|
|
||||||
{
|
|
||||||
private $indexUniqIdName = 'IDX_vote_uniqId';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method should describe in english what is the purpose of the migration class.
|
|
||||||
*
|
|
||||||
* @return string The description of the migration class
|
|
||||||
*/
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
return 'Add column "uniqId" in table "vote" for version 0.9';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Migrations\SkipMigrationException
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
*/
|
|
||||||
public function up(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->skipIf($this->legacyCheck($schema, 'Framadate\Migration\AddColumn_uniqId_In_vote_For_0_9'), 'Migration has been executed in an earlier database migration system');
|
|
||||||
foreach ([Utils::table('poll'), Utils::table('slot'), Utils::table('vote'), Utils::table('comment')] as $table) {
|
|
||||||
$this->skipIf(!$schema->hasTable($table), 'Missing table ' . $table);
|
|
||||||
}
|
|
||||||
$voteTable = $schema->getTable(Utils::table('vote'));
|
|
||||||
|
|
||||||
$this->skipIf($voteTable->hasColumn('uniqId'), 'Column uniqId already existing');
|
|
||||||
|
|
||||||
$voteTable->addColumn('uniqId', 'string', ['length' => 16]);
|
|
||||||
$voteTable->addIndex(['uniqId'], $this->indexUniqIdName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
*/
|
|
||||||
public function down(Schema $schema)
|
|
||||||
{
|
|
||||||
$voteTable = $schema->getTable(Utils::table('vote'));
|
|
||||||
|
|
||||||
$voteTable->dropIndex($this->indexUniqIdName);
|
|
||||||
$voteTable->dropColumn('uniqId');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Framadate\AbstractMigration;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This migration adds the field hidden on the poll table.
|
|
||||||
*
|
|
||||||
* @package Framadate\Migration
|
|
||||||
* @version 0.9
|
|
||||||
*/
|
|
||||||
class Version20150405000000 extends AbstractMigration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method should describe in english what is the purpose of the migration class.
|
|
||||||
*
|
|
||||||
* @return string The description of the migration class
|
|
||||||
*/
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
return 'Add column "hidden" in table "vote" for version 0.9';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Migrations\SkipMigrationException
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
*/
|
|
||||||
public function up(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->skipIf($this->legacyCheck($schema, 'Framadate\Migration\AddColumn_hidden_In_poll_For_0_9'), 'Migration has been executed in an earlier database migration system');
|
|
||||||
foreach ([Utils::table('poll'), Utils::table('slot'), Utils::table('vote'), Utils::table('comment')] as $table) {
|
|
||||||
$this->skipIf(!$schema->hasTable($table), 'Missing table ' . $table);
|
|
||||||
}
|
|
||||||
$pollTable = $schema->getTable(Utils::table('poll'));
|
|
||||||
|
|
||||||
$this->skipIf($pollTable->hasColumn('hidden'), 'Column hidden already existing in table poll');
|
|
||||||
|
|
||||||
$pollTable->addColumn('hidden', 'boolean', ['default' => false, 'notnull' => true]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
*/
|
|
||||||
public function down(Schema $schema)
|
|
||||||
{
|
|
||||||
$pollTable = $schema->getTable(Utils::table('poll'));
|
|
||||||
|
|
||||||
$pollTable->dropColumn('hidden');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Framadate\AbstractMigration;
|
|
||||||
use Framadate\Security\Token;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This migration generate uniqId for all legacy votes.
|
|
||||||
*
|
|
||||||
* @package Framadate\Migration
|
|
||||||
* @version 0.9
|
|
||||||
*/
|
|
||||||
class Version20150624000000 extends AbstractMigration
|
|
||||||
{
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
return 'Generate "uniqId" in "vote" table for all legacy votes';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @throws \Doctrine\DBAL\Migrations\SkipMigrationException
|
|
||||||
*/
|
|
||||||
public function up(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->skipIf($this->legacyCheck($schema, 'Framadate\Migration\Generate_uniqId_for_old_votes'), 'Migration has been executed in an earlier database migration system');
|
|
||||||
foreach ([Utils::table('poll'), Utils::table('slot'), Utils::table('vote'), Utils::table('comment')] as $table) {
|
|
||||||
$this->skipIf(!$schema->hasTable($table), 'Missing table ' . $table);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->connection->beginTransaction();
|
|
||||||
|
|
||||||
$select = $this->connection->query('
|
|
||||||
SELECT id
|
|
||||||
FROM ' . Utils::table('vote') . '
|
|
||||||
WHERE uniqid = \'\'');
|
|
||||||
|
|
||||||
$update = $this->connection->prepare('
|
|
||||||
UPDATE ' . Utils::table('vote') . '
|
|
||||||
SET uniqid = :uniqid
|
|
||||||
WHERE id = :id');
|
|
||||||
|
|
||||||
while ($row = $select->fetch(\PDO::FETCH_OBJ)) {
|
|
||||||
$token = Token::getToken(16);
|
|
||||||
$update->execute([
|
|
||||||
'uniqid' => $token,
|
|
||||||
'id' => $row->id
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->connection->commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema)
|
|
||||||
{
|
|
||||||
// TODO: Implement down() method.
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,102 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Rapha<EFBFBD>l DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* Ce logiciel est r<EFBFBD>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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Rapha<EFBFBD>l DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Framadate\AbstractMigration;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This migration RPad votes from version 0.8.
|
|
||||||
* Because some votes does not have enough values for their poll.
|
|
||||||
*
|
|
||||||
* @package Framadate\Migration
|
|
||||||
* @version 0.9
|
|
||||||
*/
|
|
||||||
class Version20150918000000 extends AbstractMigration
|
|
||||||
{
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
return 'RPad votes from version 0.8.';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @throws \Doctrine\DBAL\Migrations\SkipMigrationException
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
*/
|
|
||||||
public function up(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->skipIf(
|
|
||||||
$this->legacyCheck($schema, 'Framadate\Migration\RPadVotes_from_0_8'),
|
|
||||||
'Migration has been executed in an earlier database migration system'
|
|
||||||
);
|
|
||||||
foreach ([Utils::table('poll'), Utils::table('slot'), Utils::table('vote'), Utils::table(
|
|
||||||
'comment'
|
|
||||||
)] as $table) {
|
|
||||||
$this->skipIf(!$schema->hasTable($table), 'Missing table ' . $table);
|
|
||||||
}
|
|
||||||
|
|
||||||
$driver_name = $this->connection->getDatabasePlatform()->getName();
|
|
||||||
switch ($driver_name) {
|
|
||||||
case 'mysql':
|
|
||||||
$this->addSql(
|
|
||||||
'UPDATE ' . Utils::table('vote') . ' fv
|
|
||||||
INNER JOIN (
|
|
||||||
SELECT v.id, RPAD(v.choices, inn.slots_count, \'0\') new_choices
|
|
||||||
FROM ' . Utils::table('vote') . ' v
|
|
||||||
INNER JOIN
|
|
||||||
(SELECT s.poll_id, SUM(IFNULL(LENGTH(s.moments) - LENGTH(REPLACE(s.moments, \',\', \'\')) + 1, 1)) slots_count
|
|
||||||
FROM ' . Utils::table('slot') . ' s
|
|
||||||
GROUP BY s.poll_id
|
|
||||||
ORDER BY s.poll_id) inn ON inn.poll_id = v.poll_id
|
|
||||||
WHERE LENGTH(v.choices) != inn.slots_count
|
|
||||||
) computed ON fv.id = computed.id
|
|
||||||
SET fv.choices = computed.new_choices'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'postgresql':
|
|
||||||
$this->addSql(
|
|
||||||
"UPDATE " . Utils::table('vote') . " fv
|
|
||||||
SET choices = computed.new_choices
|
|
||||||
FROM (
|
|
||||||
SELECT v.id, RPAD(v.choices::text, inn.slots_count::int, '0') new_choices
|
|
||||||
FROM " . Utils::table('vote') . " v
|
|
||||||
INNER JOIN
|
|
||||||
(SELECT s.poll_id, SUM(coalesce(LENGTH(s.moments) - LENGTH(REPLACE(s.moments, ',', '')) + 1, 1)) slots_count
|
|
||||||
FROM " . Utils::table('slot') . " s
|
|
||||||
GROUP BY s.poll_id
|
|
||||||
ORDER BY s.poll_id) inn ON inn.poll_id = v.poll_id
|
|
||||||
WHERE LENGTH(v.choices) != inn.slots_count
|
|
||||||
) computed WHERE fv.id = computed.id"
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$this->skipIf(true, "Not on MySQL or PostgreSQL");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema)
|
|
||||||
{
|
|
||||||
// TODO: Implement down() method.
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Doctrine\DBAL\Types\Type;
|
|
||||||
use Framadate\AbstractMigration;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This migration alter the comment table to set a length to the name column.
|
|
||||||
*
|
|
||||||
* @package Framadate\Migration
|
|
||||||
* @version 1.0
|
|
||||||
*/
|
|
||||||
class Version20151012075900 extends AbstractMigration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method should describe in english what is the purpose of the migration class.
|
|
||||||
*
|
|
||||||
* @return string The description of the migration class
|
|
||||||
*/
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
return 'Alter the comment table to set a length to the name column.';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @throws \Doctrine\DBAL\Migrations\SkipMigrationException
|
|
||||||
*/
|
|
||||||
public function up(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->skipIf($this->legacyCheck($schema, 'Framadate\Migration\Alter_Comment_table_for_name_length'), 'Migration has been executed in an earlier database migration system');
|
|
||||||
$commentTable = $schema->getTable(Utils::table('comment'));
|
|
||||||
|
|
||||||
$commentTable->changeColumn('name', ['default' => null, 'notnull' => false]);
|
|
||||||
|
|
||||||
$commentTable->changeColumn('name', ['type' => Type::getType('string'), 'length' => 64, 'notnull' => true]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
*/
|
|
||||||
public function down(Schema $schema)
|
|
||||||
{
|
|
||||||
$commentTable = $schema->getTable(Utils::table('comment'));
|
|
||||||
|
|
||||||
$commentTable->changeColumn('name', ['type' => Type::getType('string')]);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Framadate\AbstractMigration;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This migration alter the comment table to add a date column.
|
|
||||||
*
|
|
||||||
* @package Framadate\Migration
|
|
||||||
* @version 1.0
|
|
||||||
*/
|
|
||||||
class Version20151012082600 extends AbstractMigration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method should describe in english what is the purpose of the migration class.
|
|
||||||
*
|
|
||||||
* @return string The description of the migration class
|
|
||||||
*/
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
return 'Alter the comment table to add a date column.';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Migrations\SkipMigrationException
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
*/
|
|
||||||
public function up(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->skipIf($this->legacyCheck($schema, 'Framadate\Migration\Alter_Comment_table_adding_date'), 'Migration has been executed in an earlier database migration system');
|
|
||||||
$commentTable = $schema->getTable(Utils::table('comment'));
|
|
||||||
|
|
||||||
$this->skipIf($commentTable->hasColumn('date'), 'Column date in comment table already exists');
|
|
||||||
|
|
||||||
$commentTable->addColumn('date', 'datetime', ['default' => 0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
*/
|
|
||||||
public function down(Schema $schema)
|
|
||||||
{
|
|
||||||
$commentTable = $schema->getTable(Utils::table('comment'));
|
|
||||||
|
|
||||||
$commentTable->dropColumn('comment');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Framadate\AbstractMigration;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This migration adds the fields password_hash and results_publicly_visible on the poll table.
|
|
||||||
*
|
|
||||||
* @package Framadate\Migration
|
|
||||||
* @version 0.9
|
|
||||||
*/
|
|
||||||
class Version20151028000000 extends AbstractMigration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method should describe in english what is the purpose of the migration class.
|
|
||||||
*
|
|
||||||
* @return string The description of the migration class
|
|
||||||
*/
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
return 'Add columns "password_hash" and "results_publicly_visible" in table "vote" for version 0.9';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Migrations\SkipMigrationException
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
*/
|
|
||||||
public function up(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->skipIf($this->legacyCheck($schema, 'Framadate\Migration\AddColumns_password_hash_And_results_publicly_visible_In_poll_For_0_9'), 'Migration has been executed in an earlier database migration system');
|
|
||||||
$pollTable = $schema->getTable(Utils::table('poll'));
|
|
||||||
|
|
||||||
$this->skipIf($pollTable->hasColumn('password_hash'), 'Column password_hash in table poll already exists');
|
|
||||||
$this->skipIf($pollTable->hasColumn('results_publicly_visible'), 'Column results_publicly_visible in table poll already exists');
|
|
||||||
|
|
||||||
$pollTable->addColumn('password_hash', 'string', ['notnull' => false]);
|
|
||||||
$pollTable->addColumn('results_publicly_visible', 'boolean', ['notnull' => false]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
*/
|
|
||||||
public function down(Schema $schema)
|
|
||||||
{
|
|
||||||
$pollTable = $schema->getTable(Utils::table('poll'));
|
|
||||||
|
|
||||||
$pollTable->dropColumn('password_hash');
|
|
||||||
$pollTable->dropColumn('results_publicly_visible');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Doctrine\DBAL\Types\Type;
|
|
||||||
use Framadate\AbstractMigration;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
class Version20151205000000 extends AbstractMigration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method should describe in english what is the purpose of the migration class.
|
|
||||||
*
|
|
||||||
* @return string The description of the migration class
|
|
||||||
*/
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
return 'Increase the size of id column in poll table';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @throws \Doctrine\DBAL\Migrations\SkipMigrationException
|
|
||||||
*/
|
|
||||||
public function up(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->skipIf($this->legacyCheck($schema, 'Framadate\Migration\Increase_pollId_size'), 'Migration has been executed in an earlier database migration system');
|
|
||||||
$commentTable = $schema->getTable(Utils::table('comment'));
|
|
||||||
|
|
||||||
$commentTable->changeColumn('poll_id', ['type' => Type::getType('string'), 'length' => 64, 'notnull' => true]);
|
|
||||||
|
|
||||||
$pollTable = $schema->getTable(Utils::table('poll'));
|
|
||||||
|
|
||||||
$pollTable->changeColumn('id', ['type' => Type::getType('string'), 'length' => 64, 'notnull' => true]);
|
|
||||||
|
|
||||||
$slotTable = $schema->getTable(Utils::table('slot'));
|
|
||||||
|
|
||||||
$slotTable->changeColumn('poll_id', ['type' => Type::getType('string'), 'length' => 64, 'notnull' => true]);
|
|
||||||
|
|
||||||
$voteTable = $schema->getTable(Utils::table('vote'));
|
|
||||||
|
|
||||||
$voteTable->changeColumn('poll_id', ['type' => Type::getType('string'), 'length' => 64, 'notnull' => true]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema)
|
|
||||||
{
|
|
||||||
// TODO: Implement down() method.
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Framadate\AbstractMigration;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This migration adds the field Value_Max on the poll table.
|
|
||||||
*
|
|
||||||
* @package Framadate\Migration
|
|
||||||
* @version 0.9
|
|
||||||
*/
|
|
||||||
class Version20180220000000 extends AbstractMigration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method should describe in english what is the purpose of the migration class.
|
|
||||||
*
|
|
||||||
* @return string The description of the migration class
|
|
||||||
*/
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
return 'Add column "ValueMax" in table "vote" for version 0.9';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
* @throws \Doctrine\DBAL\Migrations\SkipMigrationException
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
*/
|
|
||||||
public function up(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->skipIf($this->legacyCheck($schema, 'Framadate\Migration\AddColumn_ValueMax_In_poll_For_1_1'), 'Migration has been executed in an earlier database migration system');
|
|
||||||
$pollTable = $schema->getTable(Utils::table('poll'));
|
|
||||||
$pollTable->addColumn('ValueMax', 'smallint', ['default' => null, 'notnull' => false]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
*/
|
|
||||||
public function down(Schema $schema)
|
|
||||||
{
|
|
||||||
$pollTable = $schema->getTable(Utils::table('poll'));
|
|
||||||
$pollTable->dropColumn('ValueMax');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Connection;
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Framadate\AbstractMigration;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This migration sets Poll.end_date to NULL by default
|
|
||||||
*
|
|
||||||
* @package Framadate\Migration
|
|
||||||
* @version 1.1
|
|
||||||
*/
|
|
||||||
class Version20180411000000 extends AbstractMigration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method should describe in english what is the purpose of the migration class.
|
|
||||||
*
|
|
||||||
* @return string The description of the migration class
|
|
||||||
*/
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
return 'Sets Poll end_date to NULL by default (work around MySQL NO_ZERO_DATE)';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method could check if the execute method should be called.
|
|
||||||
* It is called before the execute method.
|
|
||||||
*
|
|
||||||
* @param Connection|\PDO $connection The connection to database
|
|
||||||
* @return bool true if the Migration should be executed.
|
|
||||||
*/
|
|
||||||
public function preCondition(Connection $connection)
|
|
||||||
{
|
|
||||||
$driver_name = $connection->getWrappedConnection()->getAttribute(\PDO::ATTR_DRIVER_NAME);
|
|
||||||
|
|
||||||
if ($driver_name === 'mysql') {
|
|
||||||
$stmt = $connection->prepare(
|
|
||||||
"SELECT Column_Default from Information_Schema.Columns where Table_Name = ? AND Column_Name = ?;"
|
|
||||||
);
|
|
||||||
$stmt->bindValue(1, Utils::table('poll'));
|
|
||||||
$stmt->bindValue(2, 'end_date');
|
|
||||||
$stmt->execute();
|
|
||||||
$default = $stmt->fetch(\PDO::FETCH_COLUMN);
|
|
||||||
|
|
||||||
return $default === null;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
* @throws \Doctrine\DBAL\Migrations\SkipMigrationException
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
*/
|
|
||||||
public function up(Schema $schema)
|
|
||||||
{
|
|
||||||
// We don't disable this migration even if legacy because it wasn't working correctly before
|
|
||||||
// $this->skipIf($this->legacyCheck($schema, 'Framadate\Migration\Fix_MySQL_No_Zero_Date'), 'Migration has been executed in an earlier database migration system');
|
|
||||||
$this->skipIf($this->preCondition($this->connection), "Database server isn't MySQL or poll end_date default value was already NULL");
|
|
||||||
$poll = $schema->getTable(Utils::table('poll'));
|
|
||||||
$poll->changeColumn('end_date', ['default' => null, 'notnull' => false]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema)
|
|
||||||
{
|
|
||||||
// nothing
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Framadate\AbstractMigration;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This migration adds the column collect_users_mail in the poll table
|
|
||||||
*
|
|
||||||
* @package Framadate\Migration
|
|
||||||
* @version 1.2
|
|
||||||
*/
|
|
||||||
class Version20180419170000 extends AbstractMigration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method should describe in english what is the purpose of the migration class.
|
|
||||||
*
|
|
||||||
* @return string The description of the migration class
|
|
||||||
*/
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
return 'Add column collect_users_mail in table poll';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
* @throws \Doctrine\DBAL\Migrations\SkipMigrationException
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
*/
|
|
||||||
public function up(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->skipIf($this->legacyCheck($schema, 'Framadate\Migration\AddColumn_collect_mail_In_poll'), 'Migration has been executed in an earlier database migration system');
|
|
||||||
$poll = $schema->getTable(Utils::table('poll'));
|
|
||||||
$poll->addColumn('collect_users_mail', 'boolean', ['default' => false]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
*/
|
|
||||||
public function down(Schema $schema)
|
|
||||||
{
|
|
||||||
$poll = $schema->getTable(Utils::table('poll'));
|
|
||||||
$poll->dropColumn('collect_users_mail');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Framadate\AbstractMigration;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This migration adds the column mail in the vote table
|
|
||||||
*
|
|
||||||
* @package Framadate\Migration
|
|
||||||
* @version 1.2
|
|
||||||
*/
|
|
||||||
class Version20180419180000 extends AbstractMigration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method should describe in english what is the purpose of the migration class.
|
|
||||||
*
|
|
||||||
* @return string The description of the migration class
|
|
||||||
*/
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
return 'Add column mail in table vote';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
* @throws \Doctrine\DBAL\Migrations\SkipMigrationException
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
*/
|
|
||||||
public function up(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->skipIf($this->legacyCheck($schema, 'Framadate\Migration\AddColumn_collect_mail_In_poll'), 'Migration has been executed in an earlier database migration system');
|
|
||||||
$vote = $schema->getTable(Utils::table('vote'));
|
|
||||||
$vote->addColumn('mail', 'string', ['default' => null, 'notnull' => false]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
*/
|
|
||||||
public function down(Schema $schema)
|
|
||||||
{
|
|
||||||
$vote = $schema->getTable(Utils::table('vote'));
|
|
||||||
$vote->dropColumn('mail');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Framadate\AbstractMigration;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This migration adds the column mail in the vote table
|
|
||||||
*
|
|
||||||
* @package Framadate\Migration
|
|
||||||
* @version 1.2
|
|
||||||
*/
|
|
||||||
class Version20180419190000 extends AbstractMigration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method should describe in english what is the purpose of the migration class.
|
|
||||||
*
|
|
||||||
* @return string The description of the migration class
|
|
||||||
*/
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
return 'Remove the old migration table';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Migrations\SkipMigrationException
|
|
||||||
*/
|
|
||||||
public function up(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->skipIf(!$schema->hasTable(Utils::table(MIGRATION_TABLE)), "The old migration table wasn't created, no need to delete it.");
|
|
||||||
$schema->dropTable(Utils::table(MIGRATION_TABLE));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
*/
|
|
||||||
public function down(Schema $schema)
|
|
||||||
{
|
|
||||||
// No need to recreate legacy migration table
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Framadate\AbstractMigration;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This migration adds the column collect_users_mail in the poll table
|
|
||||||
*
|
|
||||||
* @package Framadate\Migration
|
|
||||||
* @version 1.2
|
|
||||||
*/
|
|
||||||
class Version20180525110000 extends AbstractMigration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method should describe in english what is the purpose of the migration class.
|
|
||||||
*
|
|
||||||
* @return string The description of the migration class
|
|
||||||
*/
|
|
||||||
public function description()
|
|
||||||
{
|
|
||||||
return 'Change column collect_users_mail in table poll from boolean to smallint';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
*/
|
|
||||||
public function up(Schema $schema)
|
|
||||||
{
|
|
||||||
$poll = $schema->getTable(Utils::table('poll'));
|
|
||||||
$poll->addColumn('collect_users_mail_integer', 'smallint', ['default' => 0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
*/
|
|
||||||
public function postUp(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->addSql('UPDATE ' . Utils::table('poll') . ' SET collect_users_mail_integer = collect_users_mail');
|
|
||||||
$this->addSql('ALTER TABLE ' . Utils::table('poll') . ' DROP COLUMN collect_users_mail');
|
|
||||||
if ($this->connection->getDatabasePlatform()->getName() === 'mysql') {
|
|
||||||
$this->addSql(
|
|
||||||
'ALTER TABLE ' . Utils::table('poll') . ' CHANGE collect_users_mail_integer collect_users_mail SMALLINT'
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$this->addSql(
|
|
||||||
'ALTER TABLE ' . Utils::table('poll') . ' RENAME COLUMN collect_users_mail_integer to collect_users_mail'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
* @throws \Doctrine\DBAL\Schema\SchemaException
|
|
||||||
*/
|
|
||||||
public function down(Schema $schema)
|
|
||||||
{
|
|
||||||
$poll = $schema->getTable(Utils::table('poll'));
|
|
||||||
$poll->addColumn('collect_users_mail_boolean', 'boolean', ['default' => false]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Schema $schema
|
|
||||||
*/
|
|
||||||
public function postDown(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->addSql('UPDATE ' . Utils::table('poll') . ' SET collect_users_mail_boolean = collect_users_mail > 0');
|
|
||||||
$this->addSql('ALTER TABLE ' . Utils::table('poll') . ' DROP COLUMN collect_users_mail');
|
|
||||||
|
|
||||||
if ($this->connection->getDatabasePlatform()->getName() === 'mysql') {
|
|
||||||
$this->addSql(
|
|
||||||
'ALTER TABLE ' . Utils::table('poll') . ' CHANGE collect_users_mail_boolean collect_users_mail SMALLINT'
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$this->addSql(
|
|
||||||
'ALTER TABLE ' . Utils::table('poll') . ' RENAME COLUMN collect_users_mail_boolean to collect_users_mail'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Framadate\Repositories;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Connection;
|
|
||||||
|
|
||||||
abstract class AbstractRepository {
|
|
||||||
/**
|
|
||||||
* @var Connection
|
|
||||||
*/
|
|
||||||
protected $connect;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PollRepository constructor.
|
|
||||||
* @param Connection $connect
|
|
||||||
*/
|
|
||||||
public function __construct(Connection $connect) {
|
|
||||||
$this->connect = $connect;
|
|
||||||
$this->connect->setFetchMode(\PDO::FETCH_OBJ);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function beginTransaction()
|
|
||||||
{
|
|
||||||
$this->connect->beginTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws \Doctrine\DBAL\ConnectionException
|
|
||||||
*/
|
|
||||||
public function commit()
|
|
||||||
{
|
|
||||||
$this->connect->commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws \Doctrine\DBAL\ConnectionException
|
|
||||||
*/
|
|
||||||
public function rollback()
|
|
||||||
{
|
|
||||||
$this->connect->rollback();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $sql
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return bool|\Doctrine\DBAL\Driver\Statement|\PDOStatement
|
|
||||||
*/
|
|
||||||
public function prepare($sql)
|
|
||||||
{
|
|
||||||
return $this->connect->prepare($sql);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $sql
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return bool|\Doctrine\DBAL\Driver\Statement|\PDOStatement
|
|
||||||
*/
|
|
||||||
public function query($sql)
|
|
||||||
{
|
|
||||||
return $this->connect->query($sql);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function lastInsertId()
|
|
||||||
{
|
|
||||||
return $this->connect->lastInsertId();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Framadate\Repositories;
|
|
||||||
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
class CommentRepository extends AbstractRepository {
|
|
||||||
/**
|
|
||||||
* @param $poll_id
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function findAllByPollId($poll_id) {
|
|
||||||
$prepared = $this->prepare('SELECT * FROM ' . Utils::table('comment') . ' WHERE poll_id = ? ORDER BY id');
|
|
||||||
$prepared->execute([$poll_id]);
|
|
||||||
|
|
||||||
return $prepared->fetchAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert a new comment.
|
|
||||||
*
|
|
||||||
* @param $poll_id
|
|
||||||
* @param $name
|
|
||||||
* @param $comment
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function insert($poll_id, $name, $comment)
|
|
||||||
{
|
|
||||||
return $this->connect->insert(Utils::table('comment'), ['poll_id' => $poll_id, 'name' => $name, 'comment' => $comment]) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $poll_id
|
|
||||||
* @param $comment_id
|
|
||||||
* @throws \Doctrine\DBAL\Exception\InvalidArgumentException
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function deleteById($poll_id, $comment_id)
|
|
||||||
{
|
|
||||||
return $this->connect->delete(Utils::table('comment'), ['poll_id' => $poll_id, 'id' => $comment_id]) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete all comments of a given poll.
|
|
||||||
*
|
|
||||||
* @param $poll_id int The ID of the given poll.
|
|
||||||
* @throws \Doctrine\DBAL\Exception\InvalidArgumentException
|
|
||||||
* @return bool true if action succeeded.
|
|
||||||
*/
|
|
||||||
function deleteByPollId($poll_id)
|
|
||||||
{
|
|
||||||
return $this->connect->delete(Utils::table('comment'), ['poll_id' => $poll_id]) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $poll_id
|
|
||||||
* @param $name
|
|
||||||
* @param $comment
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function exists($poll_id, $name, $comment)
|
|
||||||
{
|
|
||||||
$prepared = $this->prepare('SELECT 1 FROM ' . Utils::table('comment') . ' WHERE poll_id = ? AND name = ? AND comment = ?');
|
|
||||||
$prepared->execute([$poll_id, $name, $comment]);
|
|
||||||
|
|
||||||
return $prepared->rowCount() > 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,241 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Framadate\Repositories;
|
|
||||||
|
|
||||||
use Framadate\Utils;
|
|
||||||
use PDO;
|
|
||||||
|
|
||||||
class PollRepository extends AbstractRepository {
|
|
||||||
/**
|
|
||||||
* @param $poll_id
|
|
||||||
* @param $admin_poll_id
|
|
||||||
* @param $form
|
|
||||||
*/
|
|
||||||
public function insertPoll($poll_id, $admin_poll_id, $form)
|
|
||||||
{
|
|
||||||
$this->connect->insert(Utils::table('poll'), [
|
|
||||||
'id' => $poll_id,
|
|
||||||
'admin_id' => $admin_poll_id,
|
|
||||||
'title' => $form->title,
|
|
||||||
'description' => $form->description,
|
|
||||||
'admin_name' => $form->admin_name,
|
|
||||||
'admin_mail' => $form->admin_mail,
|
|
||||||
'end_date' => (new \DateTime)->setTimestamp($form->end_date)->format('Y-m-d H:i:s'),
|
|
||||||
'format' => $form->format,
|
|
||||||
'editable' => ($form->editable>=0 && $form->editable<=2) ? $form->editable : 0,
|
|
||||||
'receiveNewVotes' => $form->receiveNewVotes ? 1 : 0,
|
|
||||||
'receiveNewComments' => $form->receiveNewComments ? 1 : 0,
|
|
||||||
'hidden' => $form->hidden ? 1 : 0,
|
|
||||||
'password_hash' => $form->password_hash,
|
|
||||||
'results_publicly_visible' => $form->results_publicly_visible ? 1 : 0,
|
|
||||||
'ValueMax' => $form->ValueMax,
|
|
||||||
'collect_users_mail' => ($form->collect_users_mail >= 0 && $form->collect_users_mail <= 3) ? $form->collect_users_mail : 0,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $poll_id
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function findById($poll_id)
|
|
||||||
{
|
|
||||||
$prepared = $this->connect->executeQuery('SELECT * FROM ' . Utils::table('poll') . ' WHERE id = ?', [$poll_id]);
|
|
||||||
|
|
||||||
$poll = $prepared->fetch();
|
|
||||||
$prepared->closeCursor();
|
|
||||||
|
|
||||||
return $poll;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $admin_poll_id
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function findByAdminId($admin_poll_id) {
|
|
||||||
$prepared = $this->connect->executeQuery('SELECT * FROM ' . Utils::table('poll') . ' WHERE admin_id = ?', [$admin_poll_id]);
|
|
||||||
|
|
||||||
$poll = $prepared->fetch();
|
|
||||||
$prepared->closeCursor();
|
|
||||||
|
|
||||||
return $poll;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $poll_id
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function existsById($poll_id) {
|
|
||||||
$prepared = $this->prepare('SELECT 1 FROM ' . Utils::table('poll') . ' WHERE id = ?');
|
|
||||||
|
|
||||||
$prepared->execute([$poll_id]);
|
|
||||||
|
|
||||||
return $prepared->rowCount() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $admin_poll_id
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function existsByAdminId($admin_poll_id) {
|
|
||||||
$prepared = $this->prepare('SELECT 1 FROM ' . Utils::table('poll') . ' WHERE admin_id = ?');
|
|
||||||
|
|
||||||
$prepared->execute([$admin_poll_id]);
|
|
||||||
|
|
||||||
return $prepared->rowCount() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $poll
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function update($poll)
|
|
||||||
{
|
|
||||||
return $this->connect->update(Utils::table('poll'), [
|
|
||||||
'title' => $poll->title,
|
|
||||||
'admin_name' => $poll->admin_name,
|
|
||||||
'admin_mail' => $poll->admin_mail,
|
|
||||||
'description' => $poll->description,
|
|
||||||
'end_date' => $poll->end_date, # TODO : Harmonize dates between here and insert
|
|
||||||
'active' => $poll->active,
|
|
||||||
'editable' => $poll->editable >= 0 && $poll->editable <= 2 ? $poll->editable : 0,
|
|
||||||
'hidden' => $poll->hidden ? 1 : 0,
|
|
||||||
'password_hash' => $poll->password_hash,
|
|
||||||
'results_publicly_visible' => $poll->results_publicly_visible ? 1 : 0
|
|
||||||
], [
|
|
||||||
'id' => $poll->id
|
|
||||||
]) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $poll_id
|
|
||||||
* @throws \Doctrine\DBAL\Exception\InvalidArgumentException
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function deleteById($poll_id)
|
|
||||||
{
|
|
||||||
return $this->connect->delete(Utils::table('poll'), ['id' => $poll_id]) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find old polls. Limit: 20.
|
|
||||||
*
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return array Array of old polls
|
|
||||||
*/
|
|
||||||
public function findOldPolls()
|
|
||||||
{
|
|
||||||
$prepared = $this->connect->executeQuery('SELECT * FROM ' . Utils::table('poll') . ' WHERE DATE_ADD(end_date, INTERVAL ? DAY) < NOW() AND end_date != 0 LIMIT 20', [PURGE_DELAY]);
|
|
||||||
|
|
||||||
return $prepared->fetchAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search polls in database.
|
|
||||||
*
|
|
||||||
* @param array $search Array of search : ['id'=>..., 'title'=>..., 'name'=>..., 'mail'=>...]
|
|
||||||
* @param int $start The number of first entry to select
|
|
||||||
* @param int $limit The number of entries to find
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return array The found polls
|
|
||||||
*/
|
|
||||||
public function findAll($search, $start, $limit) {
|
|
||||||
// Polls
|
|
||||||
|
|
||||||
$request = "";
|
|
||||||
$request .= "SELECT p.*,";
|
|
||||||
$request .= " (SELECT count(1) FROM " . Utils::table('vote') . " v WHERE p.id=v.poll_id) votes";
|
|
||||||
$request .= " FROM " . Utils::table('poll') . " p";
|
|
||||||
$request .= " WHERE 1";
|
|
||||||
|
|
||||||
$values = [];
|
|
||||||
|
|
||||||
if (!empty($search["poll"])) {
|
|
||||||
$request .= " AND p.id LIKE :poll";
|
|
||||||
$values["poll"] = "{$search["poll"]}%";
|
|
||||||
}
|
|
||||||
|
|
||||||
$fields = [
|
|
||||||
// key of $search => column name
|
|
||||||
"title" => "title",
|
|
||||||
"name" => "admin_name",
|
|
||||||
"mail" => "admin_mail",
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($fields as $searchKey => $columnName) {
|
|
||||||
if (empty($search[$searchKey])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$request .= " AND p.$columnName LIKE :$searchKey";
|
|
||||||
$values[$searchKey] = "%{$search[$searchKey]}%";
|
|
||||||
}
|
|
||||||
|
|
||||||
$request .= " ORDER BY p.title ASC";
|
|
||||||
$request .= " LIMIT :start, :limit";
|
|
||||||
|
|
||||||
$prepared = $this->prepare($request);
|
|
||||||
|
|
||||||
foreach ($values as $searchKey => $value) {
|
|
||||||
$prepared->bindParam(":$searchKey", $value, PDO::PARAM_STR);
|
|
||||||
}
|
|
||||||
|
|
||||||
$prepared->bindParam(':start', $start, PDO::PARAM_INT);
|
|
||||||
$prepared->bindParam(':limit', $limit, PDO::PARAM_INT);
|
|
||||||
|
|
||||||
$prepared->execute();
|
|
||||||
|
|
||||||
return $prepared->fetchAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find all polls that are created with the given admin mail.
|
|
||||||
*
|
|
||||||
* @param string $mail Email address of the poll admin
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return array The list of matching polls
|
|
||||||
*/
|
|
||||||
public function findAllByAdminMail($mail) {
|
|
||||||
$prepared = $this->prepare('SELECT * FROM ' . Utils::table('poll') . ' WHERE admin_mail = :admin_mail');
|
|
||||||
$prepared->execute(['admin_mail' => $mail]);
|
|
||||||
|
|
||||||
return $prepared->fetchAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the total number of polls in database.
|
|
||||||
*
|
|
||||||
* @param array $search Array of search : ['id'=>..., 'title'=>..., 'name'=>...]
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return int The number of polls
|
|
||||||
*/
|
|
||||||
public function count($search = null) {
|
|
||||||
// Total count
|
|
||||||
$prepared = $this->prepare('
|
|
||||||
SELECT count(1) nb
|
|
||||||
FROM ' . Utils::table('poll') . ' p
|
|
||||||
WHERE (:id = "" OR p.id LIKE :id)
|
|
||||||
AND (:title = "" OR p.title LIKE :title)
|
|
||||||
AND (:name = "" OR p.admin_name LIKE :name)
|
|
||||||
ORDER BY p.title ASC');
|
|
||||||
|
|
||||||
$poll = $search === null ? '' : $search['poll'] . '%';
|
|
||||||
$title = $search === null ? '' : '%' . $search['title'] . '%';
|
|
||||||
$name = $search === null ? '' : '%' . $search['name'] . '%';
|
|
||||||
$prepared->bindParam(':id', $poll, PDO::PARAM_STR);
|
|
||||||
$prepared->bindParam(':title', $title, PDO::PARAM_STR);
|
|
||||||
$prepared->bindParam(':name', $name, PDO::PARAM_STR);
|
|
||||||
|
|
||||||
$prepared->execute();
|
|
||||||
$count = $prepared->fetch();
|
|
||||||
|
|
||||||
/*echo '---';
|
|
||||||
print_r($count);
|
|
||||||
echo '---';
|
|
||||||
exit;*/
|
|
||||||
|
|
||||||
return $count->nb;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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\Repositories;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Connection;
|
|
||||||
|
|
||||||
class RepositoryFactory {
|
|
||||||
private static $connect;
|
|
||||||
|
|
||||||
private static $pollRepository;
|
|
||||||
private static $slotRepository;
|
|
||||||
private static $voteRepository;
|
|
||||||
private static $commentRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Connection $connect
|
|
||||||
*/
|
|
||||||
static function init(Connection $connect) {
|
|
||||||
self::$connect = $connect;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return PollRepository The singleton of PollRepository
|
|
||||||
*/
|
|
||||||
static function pollRepository() {
|
|
||||||
if (self::$pollRepository === null) {
|
|
||||||
self::$pollRepository = new PollRepository(self::$connect);
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::$pollRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return SlotRepository The singleton of SlotRepository
|
|
||||||
*/
|
|
||||||
static function slotRepository() {
|
|
||||||
if (self::$slotRepository === null) {
|
|
||||||
self::$slotRepository = new SlotRepository(self::$connect);
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::$slotRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return VoteRepository The singleton of VoteRepository
|
|
||||||
*/
|
|
||||||
static function voteRepository() {
|
|
||||||
if (self::$voteRepository === null) {
|
|
||||||
self::$voteRepository = new VoteRepository(self::$connect);
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::$voteRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return CommentRepository The singleton of CommentRepository
|
|
||||||
*/
|
|
||||||
static function commentRepository() {
|
|
||||||
if (self::$commentRepository === null) {
|
|
||||||
self::$commentRepository = new CommentRepository(self::$connect);
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::$commentRepository;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,134 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Rapha<EFBFBD>l DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* Ce logiciel est r<EFBFBD>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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Rapha<EFBFBD>l DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
namespace Framadate\Repositories;
|
|
||||||
|
|
||||||
use Framadate\Choice;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
class SlotRepository extends AbstractRepository {
|
|
||||||
/**
|
|
||||||
* Insert a bulk of slots.
|
|
||||||
*
|
|
||||||
* @param int $poll_id
|
|
||||||
* @param array $choices
|
|
||||||
*/
|
|
||||||
public function insertSlots($poll_id, $choices) {
|
|
||||||
foreach ($choices as $choice) {
|
|
||||||
/** @var Choice $choice */
|
|
||||||
// We prepared the slots (joined by comas)
|
|
||||||
$joinedSlots = null;
|
|
||||||
$first = true;
|
|
||||||
foreach ($choice->getSlots() as $slot) {
|
|
||||||
if ($first) {
|
|
||||||
$joinedSlots = $slot;
|
|
||||||
$first = false;
|
|
||||||
} else {
|
|
||||||
$joinedSlots .= ',' . $slot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We execute the insertion
|
|
||||||
$this->connect->insert(Utils::table('slot'), [
|
|
||||||
'poll_id' => $poll_id,
|
|
||||||
'title' => $choice->getName(),
|
|
||||||
'moments' => $joinedSlots
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $poll_id
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function listByPollId($poll_id)
|
|
||||||
{
|
|
||||||
$prepared = $this->prepare('SELECT * FROM ' . Utils::table('slot') . ' WHERE poll_id = ? ORDER BY id');
|
|
||||||
$prepared->execute([$poll_id]);
|
|
||||||
|
|
||||||
return $prepared->fetchAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return mixed Object The slot found, or null
|
|
||||||
*/
|
|
||||||
function findByPollIdAndDatetime($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 insert($poll_id, $title, $moments)
|
|
||||||
{
|
|
||||||
return $this->connect->insert(Utils::table('slot'), ['poll_id' => $poll_id, 'title' => $title, 'moments' => $moments]) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 update($poll_id, $datetime, $newMoments)
|
|
||||||
{
|
|
||||||
return $this->connect->update(Utils::table('slot'), ['moments' => $newMoments], ['poll_id' => $poll_id, 'title' => $datetime]) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a entire slot from a poll.
|
|
||||||
*
|
|
||||||
* @param $poll_id int The ID of the poll
|
|
||||||
* @param $datetime mixed The datetime of the slot
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function deleteByDateTime($poll_id, $datetime)
|
|
||||||
{
|
|
||||||
return $this->connect->delete(Utils::table('slot'), ['poll_id' => $poll_id, 'title' => $datetime]) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $poll_id
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function deleteByPollId($poll_id)
|
|
||||||
{
|
|
||||||
return $this->connect->delete(Utils::table('slot'), ['poll_id' => $poll_id]) > 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,140 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Framadate\Repositories;
|
|
||||||
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
class VoteRepository extends AbstractRepository {
|
|
||||||
/**
|
|
||||||
* @param $poll_id
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function allUserVotesByPollId($poll_id)
|
|
||||||
{
|
|
||||||
$prepared = $this->prepare('SELECT * FROM ' . Utils::table('vote') . ' WHERE poll_id = ? ORDER BY id');
|
|
||||||
$prepared->execute([$poll_id]);
|
|
||||||
|
|
||||||
return $prepared->fetchAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $poll_id
|
|
||||||
* @param $insert_position
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function insertDefault($poll_id, $insert_position)
|
|
||||||
{
|
|
||||||
# TODO : Handle this on PHP's side
|
|
||||||
$prepared = $this->prepare('UPDATE ' . Utils::table('vote') . ' SET choices = CONCAT(SUBSTRING(choices, 1, ?), " ", SUBSTRING(choices, ?)) WHERE poll_id = ?'); //#51 : default value for unselected vote
|
|
||||||
|
|
||||||
return $prepared->execute([$insert_position, $insert_position + 1, $poll_id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function insert($poll_id, $name, $choices, $token, $mail) {
|
|
||||||
$this->connect->insert(Utils::table('vote'), ['poll_id' => $poll_id, 'name' => $name, 'choices' => $choices, 'uniqId' => $token, 'mail' => $mail]);
|
|
||||||
|
|
||||||
$newVote = new \stdClass();
|
|
||||||
$newVote->poll_id = $poll_id;
|
|
||||||
$newVote->id = $this->lastInsertId();
|
|
||||||
$newVote->name = $name;
|
|
||||||
$newVote->choices = $choices;
|
|
||||||
$newVote->uniqId = $token;
|
|
||||||
$newVote->mail=$mail;
|
|
||||||
|
|
||||||
return $newVote;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $poll_id
|
|
||||||
* @param $vote_id
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function deleteById($poll_id, $vote_id)
|
|
||||||
{
|
|
||||||
return $this->connect->delete(Utils::table('vote'), ['poll_id' => $poll_id, 'id' => $vote_id]) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function deleteOldVotesByPollId($poll_id, $votesToDelete) {
|
|
||||||
$prepared = $this->prepare('DELETE FROM `' . Utils::table('vote') . '` WHERE poll_id = ? ORDER BY `poll_id` ASC LIMIT ' . $votesToDelete);
|
|
||||||
|
|
||||||
return $prepared->execute([$poll_id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete all votes of a given poll.
|
|
||||||
*
|
|
||||||
* @param $poll_id int The ID of the given poll.
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return bool|null true if action succeeded.
|
|
||||||
*/
|
|
||||||
public function deleteByPollId($poll_id)
|
|
||||||
{
|
|
||||||
return $this->connect->delete(Utils::table('vote'), ['poll_id' => $poll_id]) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return bool|null true if action succeeded.
|
|
||||||
*/
|
|
||||||
public function deleteByIndex($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]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $poll_id
|
|
||||||
* @param $vote_id
|
|
||||||
* @param $name
|
|
||||||
* @param $choices
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function update($poll_id, $vote_id, $name, $choices, $mail)
|
|
||||||
{
|
|
||||||
return $this->connect->update(Utils::table('vote'), [
|
|
||||||
'choices' => $choices,
|
|
||||||
'name' => $name,
|
|
||||||
'mail' => $mail,
|
|
||||||
], [
|
|
||||||
'poll_id' => $poll_id,
|
|
||||||
'id' => $vote_id,
|
|
||||||
]) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if name is already used for the given poll.
|
|
||||||
*
|
|
||||||
* @param int $poll_id ID of the poll
|
|
||||||
* @param string $name Name of the vote
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return bool true if vote already exists
|
|
||||||
*/
|
|
||||||
public function existsByPollIdAndName($poll_id, $name) {
|
|
||||||
$prepared = $this->prepare('SELECT 1 FROM ' . Utils::table('vote') . ' WHERE poll_id = ? AND name = ?');
|
|
||||||
$prepared->execute([$poll_id, $name]);
|
|
||||||
return $prepared->rowCount() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if name is already used for the given poll and another vote.
|
|
||||||
*
|
|
||||||
* @param int $poll_id ID of the poll
|
|
||||||
* @param string $name Name of the vote
|
|
||||||
* @param int $vote_id ID of the current vote
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
* @return bool true if vote already exists
|
|
||||||
*/
|
|
||||||
public function existsByPollIdAndNameAndVoteId($poll_id, $name, $vote_id) {
|
|
||||||
$prepared = $this->prepare('SELECT 1 FROM ' . Utils::table('vote') . ' WHERE poll_id = ? AND name = ? AND id != ?');
|
|
||||||
$prepared->execute([$poll_id, $name, $vote_id]);
|
|
||||||
return $prepared->rowCount() > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
|
|
||||||
namespace Framadate\Security;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class PasswordHasher
|
|
||||||
*
|
|
||||||
* Used to abstract the password hash logic
|
|
||||||
*
|
|
||||||
* @package Framadate\Security
|
|
||||||
*/
|
|
||||||
class PasswordHasher {
|
|
||||||
/**
|
|
||||||
* Hash a password
|
|
||||||
*
|
|
||||||
* @param string $password the password to hash.
|
|
||||||
* @return false|string the hashed password, or false on failure. The used algorithm, cost and salt are returned as part of the hash.
|
|
||||||
*/
|
|
||||||
public static function hash($password) {
|
|
||||||
return password_hash($password, PASSWORD_DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify a password with a hash
|
|
||||||
*
|
|
||||||
* @param string $password the password to verify
|
|
||||||
* @param string $hash the hash to compare.
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function verify($password, $hash) {
|
|
||||||
return password_verify($password, $hash);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,90 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Framadate\Security;
|
|
||||||
|
|
||||||
class Token {
|
|
||||||
const DEFAULT_LENGTH = 64;
|
|
||||||
private $time;
|
|
||||||
private $value;
|
|
||||||
private $length;
|
|
||||||
private static $codeAlphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789';
|
|
||||||
|
|
||||||
function __construct($length = self::DEFAULT_LENGTH) {
|
|
||||||
$this->length = $length;
|
|
||||||
$this->time = time() + TOKEN_TIME;
|
|
||||||
$this->value = $this->generate();
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a secure token if possible, or a less secure one if not.
|
|
||||||
*
|
|
||||||
* @param int $length The token length
|
|
||||||
* @param bool $crypto_strong If passed, tells if the token is "cryptographically strong" or not.
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public static function getToken($length = self::DEFAULT_LENGTH, &$crypto_strong = false) {
|
|
||||||
if (function_exists('openssl_random_pseudo_bytes')) {
|
|
||||||
openssl_random_pseudo_bytes(1, $crypto_strong); // Fake use to see if the algorithm used was "cryptographically strong"
|
|
||||||
return self::getSecureToken($length);
|
|
||||||
}
|
|
||||||
return self::getUnsecureToken($length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getUnsecureToken($length) {
|
|
||||||
$string = '';
|
|
||||||
mt_srand();
|
|
||||||
for ($i = 0; $i < $length; $i++) {
|
|
||||||
$string .= self::$codeAlphabet[mt_rand() % strlen(self::$codeAlphabet)];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author http://stackoverflow.com/a/13733588
|
|
||||||
*/
|
|
||||||
public static function getSecureToken($length){
|
|
||||||
$token = "";
|
|
||||||
for($i=0;$i<$length;$i++){
|
|
||||||
$token .= self::$codeAlphabet[self::crypto_rand_secure(0,strlen(self::$codeAlphabet))];
|
|
||||||
}
|
|
||||||
return $token;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function generate() {
|
|
||||||
return self::getToken($this->length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322
|
|
||||||
*/
|
|
||||||
private static function crypto_rand_secure($min, $max) {
|
|
||||||
$range = $max - $min;
|
|
||||||
if ($range < 0) return $min; // not so random...
|
|
||||||
$log = log($range, 2);
|
|
||||||
$bytes = (int) ($log / 8) + 1; // length in bytes
|
|
||||||
$bits = (int) $log + 1; // length in bits
|
|
||||||
$filter = (int) (1 << $bits) - 1; // set all lower bits to 1
|
|
||||||
do {
|
|
||||||
$rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
|
|
||||||
$rnd = $rnd & $filter; // discard irrelevant bits
|
|
||||||
} while ($rnd >= $range);
|
|
||||||
return $min + $rnd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,316 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Framadate\Services;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Connection;
|
|
||||||
use Doctrine\DBAL\DBALException;
|
|
||||||
use Framadate\Exception\MomentAlreadyExistsException;
|
|
||||||
use Framadate\Repositories\RepositoryFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class AdminPollService
|
|
||||||
*
|
|
||||||
* @package Framadate\Services
|
|
||||||
*/
|
|
||||||
class AdminPollService {
|
|
||||||
private $connect;
|
|
||||||
private $pollService;
|
|
||||||
private $logService;
|
|
||||||
|
|
||||||
private $pollRepository;
|
|
||||||
private $slotRepository;
|
|
||||||
private $voteRepository;
|
|
||||||
private $commentRepository;
|
|
||||||
|
|
||||||
function __construct(Connection $connect, PollService $pollService, LogService $logService) {
|
|
||||||
$this->connect = $connect;
|
|
||||||
$this->pollService = $pollService;
|
|
||||||
$this->logService = $logService;
|
|
||||||
$this->pollRepository = RepositoryFactory::pollRepository();
|
|
||||||
$this->slotRepository = RepositoryFactory::slotRepository();
|
|
||||||
$this->voteRepository = RepositoryFactory::voteRepository();
|
|
||||||
$this->commentRepository = RepositoryFactory::commentRepository();
|
|
||||||
}
|
|
||||||
|
|
||||||
function updatePoll($poll) {
|
|
||||||
global $config;
|
|
||||||
if ($poll->end_date > $poll->creation_date) {
|
|
||||||
return $this->pollRepository->update($poll);
|
|
||||||
}
|
|
||||||
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->commentRepository->deleteById($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->commentRepository->deleteByPollId($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->voteRepository->deleteById($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->voteRepository->deleteByPollId($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->pollRepository->findById($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->voteRepository->deleteByPollId($poll_id);
|
|
||||||
$this->commentRepository->deleteByPollId($poll_id);
|
|
||||||
$this->slotRepository->deleteByPollId($poll_id);
|
|
||||||
$this->pollRepository->deleteById($poll_id);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a slot from a poll.
|
|
||||||
*
|
|
||||||
* @param object $poll The ID of the poll
|
|
||||||
* @param object $slot The slot informations (datetime + moment)
|
|
||||||
* @return bool true if action succeeded
|
|
||||||
*/
|
|
||||||
public function deleteDateSlot($poll, $slot) {
|
|
||||||
$this->logService->log('DELETE_SLOT', 'id:' . $poll->id . ', slot:' . json_encode($slot));
|
|
||||||
|
|
||||||
$datetime = $slot->title;
|
|
||||||
$moment = $slot->moment;
|
|
||||||
|
|
||||||
$slots = $this->pollService->allSlotsByPoll($poll);
|
|
||||||
|
|
||||||
// We can't delete the last slot
|
|
||||||
if ($poll->format === 'D' && count($slots) === 1 && strpos($slots[0]->moments, ',') === false) {
|
|
||||||
return false;
|
|
||||||
} elseif ($poll->format === 'A' && count($slots) === 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$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->voteRepository->deleteByIndex($poll->id, $indexToDelete);
|
|
||||||
if (count($newMoments) > 0) {
|
|
||||||
$this->slotRepository->update($poll->id, $datetime, implode(',', $newMoments));
|
|
||||||
} else {
|
|
||||||
$this->slotRepository->deleteByDateTime($poll->id, $datetime);
|
|
||||||
}
|
|
||||||
$this->connect->commit();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function deleteClassicSlot($poll, $slot_title) {
|
|
||||||
$this->logService->log('DELETE_SLOT', 'id:' . $poll->id . ', slot:' . $slot_title);
|
|
||||||
|
|
||||||
$slots = $this->pollService->allSlotsByPoll($poll);
|
|
||||||
|
|
||||||
if (count($slots) === 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$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->voteRepository->deleteByIndex($poll->id, $indexToDelete);
|
|
||||||
$this->slotRepository->deleteByDateTime($poll->id, $slot_title);
|
|
||||||
$this->connect->commit();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a new slot to a date poll. And insert default values for user's votes.
|
|
||||||
* <ul>
|
|
||||||
* <li>Create a new slot if no one exists for the given date</li>
|
|
||||||
* <li>Create a new moment if a slot already exists for the given date</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param $poll_id int The ID of the poll
|
|
||||||
* @param $datetime int The datetime
|
|
||||||
* @param $new_moment string The moment's name
|
|
||||||
* @throws MomentAlreadyExistsException When the moment to add already exists in database
|
|
||||||
* @throws \Doctrine\DBAL\ConnectionException
|
|
||||||
*/
|
|
||||||
public function addDateSlot($poll_id, $datetime, $new_moment) {
|
|
||||||
$this->logService->log('ADD_COLUMN', 'id:' . $poll_id . ', datetime:' . $datetime . ', moment:' . $new_moment);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$slots = $this->slotRepository->listByPollId($poll_id);
|
|
||||||
$result = $this->findInsertPosition($slots, $datetime);
|
|
||||||
} catch (DBALException $e) {
|
|
||||||
$this->logService->log('ERROR', "Database error, couldn't find slot insert position" . $e->getMessage());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Begin transaction
|
|
||||||
$this->connect->beginTransaction();
|
|
||||||
|
|
||||||
if ($result->slot !== null) {
|
|
||||||
$slot = $result->slot;
|
|
||||||
$moments = explode(',', $slot->moments);
|
|
||||||
|
|
||||||
// Check if moment already exists (maybe not necessary)
|
|
||||||
if (in_array($new_moment, $moments, true)) {
|
|
||||||
throw new MomentAlreadyExistsException();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update found slot
|
|
||||||
$moments[] = $new_moment;
|
|
||||||
$this->slotRepository->update($poll_id, $datetime, implode(',', $moments));
|
|
||||||
} else {
|
|
||||||
$this->slotRepository->insert($poll_id, $datetime, $new_moment);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->voteRepository->insertDefault($poll_id, $result->insert);
|
|
||||||
|
|
||||||
// Commit transaction
|
|
||||||
$this->connect->commit();
|
|
||||||
} catch (DBALException $e) {
|
|
||||||
$this->connect->rollBack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a new slot to a classic poll. And insert default values for user's votes.
|
|
||||||
* <ul>
|
|
||||||
* <li>Create a new slot if no one exists for the given title</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param $poll_id int The ID of the poll
|
|
||||||
* @param $title int The title
|
|
||||||
* @throws MomentAlreadyExistsException When the moment to add already exists in database
|
|
||||||
* @throws \Doctrine\DBAL\ConnectionException
|
|
||||||
* @throws \Doctrine\DBAL\DBALException
|
|
||||||
*/
|
|
||||||
public function addClassicSlot($poll_id, $title) {
|
|
||||||
$this->logService->log('ADD_COLUMN', 'id:' . $poll_id . ', title:' . $title);
|
|
||||||
|
|
||||||
$slots = $this->slotRepository->listByPollId($poll_id);
|
|
||||||
|
|
||||||
// Check if slot already exists
|
|
||||||
$titles = array_map(function ($slot) {
|
|
||||||
return $slot->title;
|
|
||||||
}, $slots);
|
|
||||||
if (in_array($title, $titles, true)) {
|
|
||||||
// The moment already exists
|
|
||||||
throw new MomentAlreadyExistsException();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Begin transaction
|
|
||||||
$this->connect->beginTransaction();
|
|
||||||
|
|
||||||
// New slot
|
|
||||||
$this->slotRepository->insert($poll_id, $title, null);
|
|
||||||
// Set default votes
|
|
||||||
$this->voteRepository->insertDefault($poll_id, count($slots));
|
|
||||||
|
|
||||||
// Commit transaction
|
|
||||||
$this->connect->commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method find where to insert a datatime+moment into a list of slots.<br/>
|
|
||||||
* 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
|
|
||||||
* @return \stdClass An object like this one: {insert:X, slot:Y} where Y can be null.
|
|
||||||
*/
|
|
||||||
private function findInsertPosition($slots, $datetime) {
|
|
||||||
$result = new \stdClass();
|
|
||||||
$result->slot = null;
|
|
||||||
$result->insert = 0;
|
|
||||||
|
|
||||||
// Sort slots before searching where to insert
|
|
||||||
$this->pollService->sortSlorts($slots);
|
|
||||||
|
|
||||||
// Search where to insert new column
|
|
||||||
foreach ($slots as $k=>$slot) {
|
|
||||||
$rowDatetime = $slot->title;
|
|
||||||
$moments = explode(',', $slot->moments);
|
|
||||||
|
|
||||||
if ($datetime === $rowDatetime) {
|
|
||||||
// Here we have to insert at the end of a slot
|
|
||||||
$result->insert += count($moments);
|
|
||||||
$result->slot = $slot;
|
|
||||||
break;
|
|
||||||
} elseif ($datetime < $rowDatetime) {
|
|
||||||
// We have to insert before this slot
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$result->insert += count($moments);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,148 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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\Services;
|
|
||||||
use DateTime;
|
|
||||||
use Egulias\EmailValidator\EmailValidator;
|
|
||||||
use Egulias\EmailValidator\Validation\RFCValidation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class helps to clean all inputs from the users or external services.
|
|
||||||
*/
|
|
||||||
class InputService {
|
|
||||||
function __construct() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method filter an array calling "filter_var" on each items.
|
|
||||||
* Only items validated are added at their own indexes, the others are not returned.
|
|
||||||
* @param array $arr The array to filter
|
|
||||||
* @param int $type The type of filter to apply
|
|
||||||
* @param array|null $options The associative array of options
|
|
||||||
* @return array The filtered array
|
|
||||||
*/
|
|
||||||
function filterArray(array $arr, $type, $options = null) {
|
|
||||||
$newArr = [];
|
|
||||||
|
|
||||||
foreach($arr as $id=>$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;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filterTitle($title) {
|
|
||||||
return $this->returnIfNotBlank($title);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filterId($id) {
|
|
||||||
$filtered = filter_var($id, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
|
|
||||||
return $filtered ? substr($filtered, 0, 64) : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filterName($name) {
|
|
||||||
$filtered = trim($name);
|
|
||||||
return $this->returnIfNotBlank($filtered);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filterMail($mail) {
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// formatting
|
|
||||||
|
|
||||||
$mail = trim($mail);
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// e-mail validation
|
|
||||||
|
|
||||||
$resultat = FALSE;
|
|
||||||
|
|
||||||
$validator = new EmailValidator();
|
|
||||||
|
|
||||||
if ($validator->isValid($mail, new RFCValidation())) {
|
|
||||||
$resultat = $mail;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// return
|
|
||||||
|
|
||||||
return $resultat;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filterDescription($description) {
|
|
||||||
$description = str_replace("\r\n", "\n", $description);
|
|
||||||
return $description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filterMD5($control) {
|
|
||||||
return filter_var($control, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => MD5_REGEX]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filterInteger($int) {
|
|
||||||
return filter_var($int, FILTER_VALIDATE_INT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filterValueMax($int)
|
|
||||||
{
|
|
||||||
return $this->filterInteger($int) >= 1 ? $this->filterInteger($int) : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filterBoolean($boolean) {
|
|
||||||
return !!filter_var($boolean, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_TRUE_REGEX]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filterEditable($editable) {
|
|
||||||
return filter_var($editable, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => EDITABLE_CHOICE_REGEX]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filterCollectMail($collectMail) {
|
|
||||||
return filter_var($collectMail, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => COLLECT_MAIL_CHOICE_REGEX]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filterComment($comment) {
|
|
||||||
$comment = str_replace("\r\n", "\n", $comment);
|
|
||||||
return $this->returnIfNotBlank($comment);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filterDate($date) {
|
|
||||||
$dDate = DateTime::createFromFormat(__('Date', 'Y-m-d'), $date)->setTime(0, 0, 0);
|
|
||||||
return $dDate->format('Y-m-d H:i:s');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the value if it's not blank.
|
|
||||||
*
|
|
||||||
* @param string $filtered The value
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
private function returnIfNotBlank($filtered) {
|
|
||||||
if ($filtered) {
|
|
||||||
$withoutSpaces = str_replace(' ', '', $filtered);
|
|
||||||
if (!empty($withoutSpaces)) {
|
|
||||||
return $filtered;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,143 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Rapha<EFBFBD>l DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Rapha<EFBFBD>l DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
namespace Framadate\Services;
|
|
||||||
use Doctrine\DBAL\Configuration;
|
|
||||||
use Doctrine\DBAL\DBALException;
|
|
||||||
use Doctrine\DBAL\DriverManager;
|
|
||||||
use Framadate\Utils;
|
|
||||||
use Smarty;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class helps to clean all inputs from the users or external services.
|
|
||||||
*/
|
|
||||||
class InstallService {
|
|
||||||
private $fields = [
|
|
||||||
// General
|
|
||||||
'appName' => 'Framadate',
|
|
||||||
'appMail' => '',
|
|
||||||
'responseMail' => '',
|
|
||||||
'defaultLanguage' => 'fr',
|
|
||||||
'cleanUrl' => true,
|
|
||||||
|
|
||||||
// Database configuration
|
|
||||||
'dbName' => 'framadate',
|
|
||||||
'dbPort' => 3306,
|
|
||||||
'dbHost' => 'localhost',
|
|
||||||
'dbUser' => 'root',
|
|
||||||
'dbPassword' => '',
|
|
||||||
'dbPrefix' => 'fd_',
|
|
||||||
'migrationTable' => 'framadate_migration'
|
|
||||||
];
|
|
||||||
|
|
||||||
function __construct() {}
|
|
||||||
|
|
||||||
public function updateFields($data) {
|
|
||||||
foreach ($data as $field => $value) {
|
|
||||||
$this->fields[$field] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function install(Smarty &$smarty) {
|
|
||||||
// Check values are present
|
|
||||||
if (empty($this->fields['appName']) || empty($this->fields['appMail']) || empty($this->fields['defaultLanguage']) || empty($this->fields['dbName']) || empty($this->fields['dbHost']) || empty($this->fields['dbPort']) || empty($this->fields['dbUser'])) {
|
|
||||||
return $this->error('Missing values');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect to database
|
|
||||||
try {
|
|
||||||
$connect = $this->connectTo($this->fields);
|
|
||||||
} catch(\Doctrine\DBAL\DBALException $e) {
|
|
||||||
return $this->error('Unable to connect to database', $e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write configuration to conf.php file
|
|
||||||
if ($this->writeConfiguration($smarty) === false) {
|
|
||||||
return $this->error(__f('Error', "Can't create the config.php file in '%s'.", CONF_FILENAME));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $fields
|
|
||||||
* @return \Doctrine\DBAL\Connection|null
|
|
||||||
*/
|
|
||||||
function connectTo($fields) {
|
|
||||||
$doctrineConfig = new Configuration();
|
|
||||||
$connectionParams = [
|
|
||||||
'dbname' => $fields['dbName'],
|
|
||||||
'user' => $fields['dbUser'],
|
|
||||||
'password' => $fields['dbPassword'],
|
|
||||||
'host' => $fields['dbHost'],
|
|
||||||
'driver' => $fields['dbDriver'],
|
|
||||||
'charset' => $fields['dbDriver'] === 'pdo_mysql' ? 'utf8mb4' : 'utf8',
|
|
||||||
];
|
|
||||||
try {
|
|
||||||
return DriverManager::getConnection($connectionParams, $doctrineConfig);
|
|
||||||
} catch (DBALException $e) {
|
|
||||||
$logger = new LogService();
|
|
||||||
$logger->log('ERROR', $e->getMessage());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function writeConfiguration(Smarty &$smarty) {
|
|
||||||
foreach($this->fields as $field=>$value) {
|
|
||||||
$smarty->assign($field, $value);
|
|
||||||
}
|
|
||||||
|
|
||||||
$content = $smarty->fetch('admin/config.tpl');
|
|
||||||
|
|
||||||
return $this->writeToFile($content);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $content
|
|
||||||
* @return bool|int
|
|
||||||
*/
|
|
||||||
function writeToFile($content) {
|
|
||||||
return @file_put_contents(CONF_FILENAME, $content);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
function ok() {
|
|
||||||
return [
|
|
||||||
'status' => 'OK',
|
|
||||||
'msg' => __f('Installation', 'Ended', Utils::get_server_name())
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $msg
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
function error($msg, $details = '') {
|
|
||||||
return [
|
|
||||||
'status' => 'ERROR',
|
|
||||||
'code' => $msg,
|
|
||||||
'details' => $details,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFields() {
|
|
||||||
return $this->fields;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Framadate\Services;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This service provides a standard way to log some informations.
|
|
||||||
*
|
|
||||||
* @package Framadate\Services
|
|
||||||
*/
|
|
||||||
class LogService {
|
|
||||||
function __construct() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Log a message to the log file.
|
|
||||||
*
|
|
||||||
* @param $tag string A tag is used to quickly found a message when reading log file
|
|
||||||
* @param $message string some message
|
|
||||||
*/
|
|
||||||
function log($tag, $message) {
|
|
||||||
error_log(date('Ymd His') . ' [' . $tag . '] ' . $message . "\n", 3, ROOT_DIR . LOG_FILE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,127 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Framadate\Services;
|
|
||||||
|
|
||||||
use PHPMailer\PHPMailer\PHPMailer;
|
|
||||||
|
|
||||||
class MailService {
|
|
||||||
const DELAY_BEFORE_RESEND = 300;
|
|
||||||
|
|
||||||
const MAILSERVICE_KEY = 'mailservice';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
private $smtp_allowed;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $smtp_options = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
private $use_sendmail;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var LogService
|
|
||||||
*/
|
|
||||||
private $logService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MailService constructor.
|
|
||||||
* @param $smtp_allowed
|
|
||||||
* @param array $smtp_options
|
|
||||||
* @param bool $use_sendmail
|
|
||||||
*/
|
|
||||||
public function __construct($smtp_allowed, $smtp_options = [], $use_sendmail = false) {
|
|
||||||
$this->logService = new LogService();
|
|
||||||
$this->smtp_allowed = $smtp_allowed;
|
|
||||||
if (true === is_array($smtp_options)) {
|
|
||||||
$this->smtp_options = $smtp_options;
|
|
||||||
}
|
|
||||||
$this->use_sendmail = $use_sendmail;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isValidEmail($email) {
|
|
||||||
return filter_var($email, FILTER_VALIDATE_EMAIL);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function send($to, $subject, $body, $msgKey = null) {
|
|
||||||
if ($this->smtp_allowed === true && $this->canSendMsg($msgKey)) {
|
|
||||||
$mail = new PHPMailer(true);
|
|
||||||
$this->configureMailer($mail);
|
|
||||||
|
|
||||||
// From
|
|
||||||
$mail->FromName = NOMAPPLICATION;
|
|
||||||
$mail->From = ADRESSEMAILADMIN;
|
|
||||||
if ($this->isValidEmail(ADRESSEMAILREPONSEAUTO)) {
|
|
||||||
$mail->addReplyTo(ADRESSEMAILREPONSEAUTO);
|
|
||||||
}
|
|
||||||
|
|
||||||
// To
|
|
||||||
$mail->addAddress($to);
|
|
||||||
|
|
||||||
// Subject
|
|
||||||
$mail->Subject = $subject;
|
|
||||||
|
|
||||||
// Bodies
|
|
||||||
$body = $body . ' <br/><br/>' . __('Mail', 'Thank you for your trust.') . ' <br/>' . NOMAPPLICATION . ' <hr/>' . __('Mail', "\"The road is long, but the way is clear…\"<br/>Framasoft lives only by your donations.<br/>Thank you in advance for your support https://soutenir.framasoft.org");
|
|
||||||
$mail->isHTML(true);
|
|
||||||
$mail->msgHTML($body, ROOT_DIR, true);
|
|
||||||
|
|
||||||
// Build headers
|
|
||||||
$mail->CharSet = 'UTF-8';
|
|
||||||
$mail->addCustomHeader('Auto-Submitted', 'auto-generated');
|
|
||||||
$mail->addCustomHeader('Return-Path', '<>');
|
|
||||||
|
|
||||||
// Send mail
|
|
||||||
$mail->send();
|
|
||||||
|
|
||||||
// Log
|
|
||||||
$this->logService->log('MAIL', 'Mail sent to: ' . $to . ', key: ' . $msgKey);
|
|
||||||
|
|
||||||
// Store the mail sending date
|
|
||||||
$_SESSION[self::MAILSERVICE_KEY][$msgKey] = time();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function canSendMsg($msgKey) {
|
|
||||||
if ($msgKey === null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($_SESSION[self::MAILSERVICE_KEY])) {
|
|
||||||
$_SESSION[self::MAILSERVICE_KEY] = [];
|
|
||||||
}
|
|
||||||
return !isset($_SESSION[self::MAILSERVICE_KEY][$msgKey]) || time() - $_SESSION[self::MAILSERVICE_KEY][$msgKey] > self::DELAY_BEFORE_RESEND;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configure the mailer with the options
|
|
||||||
*
|
|
||||||
* @param PHPMailer $mailer
|
|
||||||
*/
|
|
||||||
private function configureMailer(PHPMailer $mailer) {
|
|
||||||
if ($this->use_sendmail) {
|
|
||||||
$mailer->isSendmail();
|
|
||||||
} else {
|
|
||||||
$mailer->isSMTP();
|
|
||||||
}
|
|
||||||
|
|
||||||
$available_options = [
|
|
||||||
'host' => 'Host',
|
|
||||||
'auth' => 'SMTPAuth',
|
|
||||||
'username' => 'Username',
|
|
||||||
'password' => 'Password',
|
|
||||||
'secure' => 'SMTPSecure',
|
|
||||||
'port' => 'Port',
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($available_options as $config_option => $mailer_option) {
|
|
||||||
if (true === isset($this->smtp_options[$config_option]) && false === empty($this->smtp_options[$config_option])) {
|
|
||||||
$mailer->{$mailer_option} = $this->smtp_options[$config_option];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,86 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
|
|
||||||
namespace Framadate\Services;
|
|
||||||
|
|
||||||
use \stdClass;
|
|
||||||
use Framadate\Services\MailService;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
class NotificationService {
|
|
||||||
const UPDATE_VOTE = 1;
|
|
||||||
const ADD_VOTE = 2;
|
|
||||||
const ADD_COMMENT = 3;
|
|
||||||
const UPDATE_POLL = 10;
|
|
||||||
const DELETED_POLL = 11;
|
|
||||||
|
|
||||||
private $mailService;
|
|
||||||
|
|
||||||
function __construct(MailService $mailService) {
|
|
||||||
$this->mailService = $mailService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a notification to the poll admin to notify him about an update.
|
|
||||||
*
|
|
||||||
* @param $poll stdClass The poll
|
|
||||||
* @param $name string The name user who triggered the notification
|
|
||||||
* @param $type int cf: Constants on the top of this page
|
|
||||||
*/
|
|
||||||
function sendUpdateNotification(stdClass $poll, $type, $name='') {
|
|
||||||
if (!isset($_SESSION['mail_sent'])) {
|
|
||||||
$_SESSION['mail_sent'] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$isVoteAndCanSendIt = ($type === self::UPDATE_VOTE || $type === self::ADD_VOTE) && $poll->receiveNewVotes;
|
|
||||||
$isCommentAndCanSendIt = $type === self::ADD_COMMENT && $poll->receiveNewComments;
|
|
||||||
$isOtherType = $type !== self::UPDATE_VOTE && $type !== self::ADD_VOTE && $type !== self::ADD_COMMENT;
|
|
||||||
|
|
||||||
if ($isVoteAndCanSendIt || $isCommentAndCanSendIt || $isOtherType) {
|
|
||||||
if (self::isParticipation($type)) {
|
|
||||||
$translationString = 'Poll participation: %s';
|
|
||||||
} else {
|
|
||||||
$translationString = 'Notification of poll: %s';
|
|
||||||
}
|
|
||||||
|
|
||||||
$subject = '[' . NOMAPPLICATION . '] ' . __f('Mail', $translationString, $poll->title);
|
|
||||||
|
|
||||||
$message = '';
|
|
||||||
|
|
||||||
$urlSondage = Utils::getUrlSondage($poll->admin_id, true);
|
|
||||||
$link = '<a href="' . $urlSondage . '">' . $urlSondage . '</a>' . "\n\n";
|
|
||||||
|
|
||||||
switch ($type) {
|
|
||||||
case self::UPDATE_VOTE:
|
|
||||||
$message .= $name . ' ';
|
|
||||||
$message .= __('Mail', "updated a vote.<br/>You can visit your poll at the link") . " :\n\n";
|
|
||||||
$message .= $link;
|
|
||||||
break;
|
|
||||||
case self::ADD_VOTE:
|
|
||||||
$message .= $name . ' ';
|
|
||||||
$message .= __('Mail', "added a vote.<br/>You can visit your poll at the link") . " :\n\n";
|
|
||||||
$message .= $link;
|
|
||||||
break;
|
|
||||||
case self::ADD_COMMENT:
|
|
||||||
$message .= $name . ' ';
|
|
||||||
$message .= __('Mail', "wrote a comment.<br/>You can visit your poll at the link") . " :\n\n";
|
|
||||||
$message .= $link;
|
|
||||||
break;
|
|
||||||
case self::UPDATE_POLL:
|
|
||||||
$message = __f('Mail', 'Someone just changed your poll at the following link <a href=\"%1$s\">%1$s</a>.', Utils::getUrlSondage($poll->admin_id, true)) . "\n\n";
|
|
||||||
break;
|
|
||||||
case self::DELETED_POLL:
|
|
||||||
$message = __f('Mail', 'Someone just deleted your poll "%s".', Utils::htmlEscape($poll->title)) . "\n\n";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$messageTypeKey = $type . '-' . $poll->id;
|
|
||||||
$this->mailService->send($poll->admin_mail, $subject, $message, $messageTypeKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isParticipation($type)
|
|
||||||
{
|
|
||||||
return $type >= self::UPDATE_POLL;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,398 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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\Services;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Connection;
|
|
||||||
use Doctrine\DBAL\ConnectionException;
|
|
||||||
use Doctrine\DBAL\DBALException;
|
|
||||||
use Framadate\Exception\AlreadyExistsException;
|
|
||||||
use Framadate\Exception\ConcurrentEditionException;
|
|
||||||
use Framadate\Exception\ConcurrentVoteException;
|
|
||||||
use Framadate\Form;
|
|
||||||
use Framadate\Repositories\RepositoryFactory;
|
|
||||||
use Framadate\Security\Token;
|
|
||||||
|
|
||||||
class PollService {
|
|
||||||
private $connect;
|
|
||||||
private $logService;
|
|
||||||
|
|
||||||
private $pollRepository;
|
|
||||||
private $slotRepository;
|
|
||||||
private $voteRepository;
|
|
||||||
private $commentRepository;
|
|
||||||
|
|
||||||
function __construct(Connection $connect, LogService $logService) {
|
|
||||||
$this->connect = $connect;
|
|
||||||
$this->logService = $logService;
|
|
||||||
$this->pollRepository = RepositoryFactory::pollRepository();
|
|
||||||
$this->slotRepository = RepositoryFactory::slotRepository();
|
|
||||||
$this->voteRepository = RepositoryFactory::voteRepository();
|
|
||||||
$this->commentRepository = RepositoryFactory::commentRepository();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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) {
|
|
||||||
try {
|
|
||||||
if (preg_match(POLL_REGEX, $poll_id)) {
|
|
||||||
return $this->pollRepository->findById($poll_id);
|
|
||||||
}
|
|
||||||
} catch (DBALException $e) {
|
|
||||||
$this->logService->log('ERROR', 'Database error : ' . $e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $admin_poll_id
|
|
||||||
* @return mixed|null
|
|
||||||
*/
|
|
||||||
public function findByAdminId($admin_poll_id) {
|
|
||||||
try {
|
|
||||||
if (preg_match(ADMIN_POLL_REGEX, $admin_poll_id)) {
|
|
||||||
return $this->pollRepository->findByAdminId($admin_poll_id);
|
|
||||||
}
|
|
||||||
} catch (DBALException $e) {
|
|
||||||
$this->logService->log('ERROR', 'Database error : ' . $e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $poll_id
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function allCommentsByPollId($poll_id)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return $this->commentRepository->findAllByPollId($poll_id);
|
|
||||||
} catch (DBALException $e) {
|
|
||||||
$this->logService->log('error', $e->getMessage());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function allVotesByPollId($poll_id) {
|
|
||||||
return $this->voteRepository->allUserVotesByPollId($poll_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
function allSlotsByPoll($poll) {
|
|
||||||
$slots = $this->slotRepository->listByPollId($poll->id);
|
|
||||||
if ($poll->format === 'D') {
|
|
||||||
$this->sortSlorts($slots);
|
|
||||||
}
|
|
||||||
return $slots;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $poll_id
|
|
||||||
* @param $vote_id
|
|
||||||
* @param $name
|
|
||||||
* @param $choices
|
|
||||||
* @param $slots_hash
|
|
||||||
* @param string $mail
|
|
||||||
* @throws AlreadyExistsException
|
|
||||||
* @throws ConcurrentEditionException
|
|
||||||
* @throws ConcurrentVoteException
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function updateVote($poll_id, $vote_id, $name, $choices, $slots_hash, $mail) {
|
|
||||||
$this->checkVoteConstraints($choices, $poll_id, $slots_hash, $name, $vote_id);
|
|
||||||
|
|
||||||
// Update vote
|
|
||||||
$choices = implode($choices);
|
|
||||||
return $this->voteRepository->update($poll_id, $vote_id, $name, $choices, $mail);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $poll_id
|
|
||||||
* @param $name
|
|
||||||
* @param $choices
|
|
||||||
* @param $slots_hash
|
|
||||||
* @param string $mail
|
|
||||||
* @throws AlreadyExistsException
|
|
||||||
* @throws ConcurrentEditionException
|
|
||||||
* @throws ConcurrentVoteException
|
|
||||||
* @return \stdClass
|
|
||||||
*/
|
|
||||||
function addVote($poll_id, $name, $choices, $slots_hash, $mail) {
|
|
||||||
$this->checkVoteConstraints($choices, $poll_id, $slots_hash, $name);
|
|
||||||
|
|
||||||
// Insert new vote
|
|
||||||
$choices = implode($choices);
|
|
||||||
$token = $this->random(16);
|
|
||||||
return $this->voteRepository->insert($poll_id, $name, $choices, $token, $mail);
|
|
||||||
}
|
|
||||||
|
|
||||||
function addComment($poll_id, $name, $comment) {
|
|
||||||
if ($this->commentRepository->exists($poll_id, $name, $comment)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->commentRepository->insert($poll_id, $name, $comment);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Form $form
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
function createPoll(Form $form) {
|
|
||||||
// Generate poll IDs, loop while poll ID already exists
|
|
||||||
|
|
||||||
$this->pollRepository->beginTransaction();
|
|
||||||
try {
|
|
||||||
if (empty($form->id)) { // User want us to generate an id for him
|
|
||||||
do {
|
|
||||||
$poll_id = $this->random(16);
|
|
||||||
} while ($this->pollRepository->existsById($poll_id));
|
|
||||||
$admin_poll_id = $poll_id . $this->random(8);
|
|
||||||
} else { // User have choosen the poll id
|
|
||||||
$poll_id = $form->id;
|
|
||||||
do {
|
|
||||||
$admin_poll_id = $this->random(24);
|
|
||||||
} while ($this->pollRepository->existsByAdminId($admin_poll_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert poll + slots
|
|
||||||
$this->pollRepository->insertPoll($poll_id, $admin_poll_id, $form);
|
|
||||||
$this->slotRepository->insertSlots($poll_id, $form->getChoices());
|
|
||||||
$this->pollRepository->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];
|
|
||||||
} catch (DBALException $e) {
|
|
||||||
$this->pollRepository->rollback();
|
|
||||||
$this->logService->log('ERROR', "Poll couldn't be saved : " . $e->getMessage());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function findAllByAdminMail($mail) {
|
|
||||||
return $this->pollRepository->findAllByAdminMail($mail);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $votes
|
|
||||||
* @param \stdClass $poll
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function computeBestChoices($votes, $poll) {
|
|
||||||
if (0 === count($votes)) {
|
|
||||||
return $this->computeEmptyBestChoices($poll);
|
|
||||||
}
|
|
||||||
$result = ['y' => [], 'inb' => []];
|
|
||||||
|
|
||||||
// if there are votes
|
|
||||||
foreach ($votes as $vote) {
|
|
||||||
$choices = str_split($vote->choices);
|
|
||||||
foreach ($choices as $i => $choice) {
|
|
||||||
if (!isset($result['y'][$i])) {
|
|
||||||
$result['inb'][$i] = 0;
|
|
||||||
$result['y'][$i] = 0;
|
|
||||||
}
|
|
||||||
if ($choice === "1") {
|
|
||||||
$result['inb'][$i]++;
|
|
||||||
}
|
|
||||||
if ($choice === "2") {
|
|
||||||
$result['y'][$i]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function splitSlots($slots) {
|
|
||||||
$splitted = [];
|
|
||||||
foreach ($slots as $slot) {
|
|
||||||
$obj = new \stdClass();
|
|
||||||
$obj->day = $slot->title;
|
|
||||||
$obj->moments = explode(',', $slot->moments);
|
|
||||||
|
|
||||||
$splitted[] = $obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $splitted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $slots array The slots to hash
|
|
||||||
* @return string The hash
|
|
||||||
*/
|
|
||||||
public function hashSlots($slots) {
|
|
||||||
return md5(array_reduce($slots, function($carry, $item) {
|
|
||||||
return $carry . $item->id . '@' . $item->moments . ';';
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
function splitVotes($votes) {
|
|
||||||
$splitted = [];
|
|
||||||
foreach ($votes as $vote) {
|
|
||||||
$obj = new \stdClass();
|
|
||||||
$obj->id = $vote->id;
|
|
||||||
$obj->name = $vote->name;
|
|
||||||
$obj->uniqId = $vote->uniqId;
|
|
||||||
$obj->choices = str_split($vote->choices);
|
|
||||||
$obj->mail = $vote->mail;
|
|
||||||
|
|
||||||
$splitted[] = $obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $splitted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int The max timestamp allowed for expiry date
|
|
||||||
*/
|
|
||||||
public function maxExpiryDate() {
|
|
||||||
global $config;
|
|
||||||
return time() + (86400 * $config['default_poll_duration']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int The min timestamp allowed for expiry date
|
|
||||||
*/
|
|
||||||
public function minExpiryDate() {
|
|
||||||
return time() + 86400;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function sortSlorts(&$slots) {
|
|
||||||
uasort($slots, function ($a, $b) {
|
|
||||||
return $a->title > $b->title;
|
|
||||||
});
|
|
||||||
return $slots;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \stdClass $poll
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function computeEmptyBestChoices($poll)
|
|
||||||
{
|
|
||||||
$result = ['y' => [], 'inb' => []];
|
|
||||||
// if there is no votes, calculates the number of slot
|
|
||||||
|
|
||||||
$slots = $this->allSlotsByPoll($poll);
|
|
||||||
|
|
||||||
if ($poll->format === 'A') {
|
|
||||||
// poll format classic
|
|
||||||
|
|
||||||
for ($i = 0; $i < count($slots); $i++) {
|
|
||||||
$result['y'][] = 0;
|
|
||||||
$result['inb'][] = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// poll format date
|
|
||||||
|
|
||||||
$slots = $this->splitSlots($slots);
|
|
||||||
|
|
||||||
foreach ($slots as $slot) {
|
|
||||||
for ($i = 0; $i < count($slot->moments); $i++) {
|
|
||||||
$result['y'][] = 0;
|
|
||||||
$result['inb'][] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function random($length) {
|
|
||||||
return Token::getToken($length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $choices
|
|
||||||
* @param $poll_id
|
|
||||||
* @param $slots_hash
|
|
||||||
* @param $name
|
|
||||||
* @param string $vote_id
|
|
||||||
* @throws AlreadyExistsException
|
|
||||||
* @throws ConcurrentVoteException
|
|
||||||
* @throws ConcurrentEditionException
|
|
||||||
*/
|
|
||||||
private function checkVoteConstraints($choices, $poll_id, $slots_hash, $name, $vote_id = FALSE) {
|
|
||||||
// Check if vote already exists with the same name
|
|
||||||
if (FALSE === $vote_id) {
|
|
||||||
$exists = $this->voteRepository->existsByPollIdAndName($poll_id, $name);
|
|
||||||
} else {
|
|
||||||
$exists = $this->voteRepository->existsByPollIdAndNameAndVoteId($poll_id, $name, $vote_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($exists) {
|
|
||||||
throw new AlreadyExistsException();
|
|
||||||
}
|
|
||||||
|
|
||||||
$poll = $this->findById($poll_id);
|
|
||||||
|
|
||||||
// Check that no-one voted in the meantime and it conflicts the maximum votes constraint
|
|
||||||
$this->checkMaxVotes($choices, $poll, $poll_id);
|
|
||||||
|
|
||||||
// Check if slots are still the same
|
|
||||||
$this->checkThatSlotsDidntChanged($poll, $slots_hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method checks if the hash send by the user is the same as the computed hash.
|
|
||||||
*
|
|
||||||
* @param $poll /stdClass The poll
|
|
||||||
* @param $slots_hash string The hash sent by the user
|
|
||||||
* @throws ConcurrentEditionException Thrown when hashes are differents
|
|
||||||
*/
|
|
||||||
private function checkThatSlotsDidntChanged($poll, $slots_hash) {
|
|
||||||
$slots = $this->allSlotsByPoll($poll);
|
|
||||||
if ($slots_hash !== $this->hashSlots($slots)) {
|
|
||||||
throw new ConcurrentEditionException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method checks if the votes doesn't conflicts the maximum votes constraint
|
|
||||||
*
|
|
||||||
* @param $user_choice
|
|
||||||
* @param \stdClass $poll
|
|
||||||
* @param string $poll_id
|
|
||||||
* @throws ConcurrentVoteException
|
|
||||||
*/
|
|
||||||
private function checkMaxVotes($user_choice, $poll, $poll_id) {
|
|
||||||
$votes = $this->allVotesByPollId($poll_id);
|
|
||||||
if (count($votes) <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$best_choices = $this->computeBestChoices($votes, $poll);
|
|
||||||
foreach ($best_choices['y'] as $i => $nb_choice) {
|
|
||||||
// if for this option we have reached maximum value and user wants to add itself too
|
|
||||||
if ($poll->ValueMax !== null && $nb_choice >= $poll->ValueMax && $user_choice[$i] === "2") {
|
|
||||||
throw new ConcurrentVoteException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,114 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Framadate\Services;
|
|
||||||
use Doctrine\DBAL\Connection;
|
|
||||||
use Doctrine\DBAL\DBALException;
|
|
||||||
use Framadate\Repositories\RepositoryFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This service helps to purge data.
|
|
||||||
*
|
|
||||||
* @package Framadate\Services
|
|
||||||
*/
|
|
||||||
class PurgeService {
|
|
||||||
private $logService;
|
|
||||||
private $pollRepository;
|
|
||||||
private $slotRepository;
|
|
||||||
private $voteRepository;
|
|
||||||
private $commentRepository;
|
|
||||||
|
|
||||||
function __construct(Connection $connect, LogService $logService) {
|
|
||||||
$this->logService = $logService;
|
|
||||||
$this->pollRepository = RepositoryFactory::pollRepository();
|
|
||||||
$this->slotRepository = RepositoryFactory::slotRepository();
|
|
||||||
$this->voteRepository = RepositoryFactory::voteRepository();
|
|
||||||
$this->commentRepository = RepositoryFactory::commentRepository();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function repeatedCleanings() {
|
|
||||||
$this->purgeOldPolls();
|
|
||||||
|
|
||||||
if (0 === time() % 10) {
|
|
||||||
$this->cleanDemoPoll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This methode purges all old polls (the ones with end_date in past).
|
|
||||||
*
|
|
||||||
* @return bool true is action succeeded
|
|
||||||
*/
|
|
||||||
public function purgeOldPolls() {
|
|
||||||
try {
|
|
||||||
$oldPolls = $this->pollRepository->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;
|
|
||||||
} catch (DBALException $e) {
|
|
||||||
$this->logService->log('ERROR', $e->getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function cleanDemoPoll() {
|
|
||||||
if (!defined("DEMO_POLL_ID") || !defined("DEMO_POLL_NUMBER_VOTES")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->voteRepository->beginTransaction();
|
|
||||||
|
|
||||||
$demoVotes = $this->voteRepository->allUserVotesByPollId(DEMO_POLL_ID);
|
|
||||||
$votesToDelete = count($demoVotes) - DEMO_POLL_NUMBER_VOTES;
|
|
||||||
|
|
||||||
if ($votesToDelete > 0) {
|
|
||||||
$this->voteRepository->deleteOldVotesByPollId(DEMO_POLL_ID, $votesToDelete);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->voteRepository->commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This methode delete all data about a poll.
|
|
||||||
*
|
|
||||||
* @param $poll_id int The ID of the poll
|
|
||||||
* @return bool true is action succeeded
|
|
||||||
*/
|
|
||||||
private function purgePollById($poll_id) {
|
|
||||||
$done = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->pollRepository->beginTransaction();
|
|
||||||
$done &= $this->commentRepository->deleteByPollId($poll_id);
|
|
||||||
$done &= $this->voteRepository->deleteByPollId($poll_id);
|
|
||||||
$done &= $this->slotRepository->deleteByPollId($poll_id);
|
|
||||||
$done &= $this->pollRepository->deleteById($poll_id);
|
|
||||||
|
|
||||||
if ($done) {
|
|
||||||
$this->pollRepository->commit();
|
|
||||||
} else {
|
|
||||||
$this->pollRepository->rollback();
|
|
||||||
}
|
|
||||||
} catch (DBALException $e) {
|
|
||||||
$this->logService->log('ERROR', $e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return $done;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Framadate\Services;
|
|
||||||
|
|
||||||
use Framadate\Security\PasswordHasher;
|
|
||||||
use Framadate\Security\Token;
|
|
||||||
|
|
||||||
class SecurityService {
|
|
||||||
function __construct() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a CSRF token by name, or (re)create it.
|
|
||||||
*
|
|
||||||
* It creates a new token if :
|
|
||||||
* <ul>
|
|
||||||
* <li>There no token with the given name in session</li>
|
|
||||||
* <li>The token time is in past</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify if the current session allows to access given poll.
|
|
||||||
*
|
|
||||||
* @param $poll \stdClass The poll which we seek access
|
|
||||||
* @return bool true if the current session can access this poll
|
|
||||||
*/
|
|
||||||
public function canAccessPoll($poll) {
|
|
||||||
if (is_null($poll->password_hash)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->ensureSessionPollSecurityIsCreated();
|
|
||||||
|
|
||||||
$currentPassword = isset($_SESSION['poll_security'][$poll->id]) ? $_SESSION['poll_security'][$poll->id] : null;
|
|
||||||
if (!empty($currentPassword) && PasswordHasher::verify($currentPassword, $poll->password_hash)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
unset($_SESSION['poll_security'][$poll->id]);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submit to the session a poll password
|
|
||||||
*
|
|
||||||
* @param $poll \stdClass The poll which we seek access
|
|
||||||
* @param $password string the password to compare
|
|
||||||
*/
|
|
||||||
public function submitPollAccess($poll, $password) {
|
|
||||||
if (!empty($password)) {
|
|
||||||
$this->ensureSessionPollSecurityIsCreated();
|
|
||||||
$_SESSION['poll_security'][$poll->id] = $password;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function ensureSessionPollSecurityIsCreated() {
|
|
||||||
if (!isset($_SESSION['poll_security'])) {
|
|
||||||
$_SESSION['poll_security'] = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
|
|
||||||
namespace Framadate\Services;
|
|
||||||
|
|
||||||
class SessionService {
|
|
||||||
/**
|
|
||||||
* Get value of $key in $section, or $defaultValue
|
|
||||||
*
|
|
||||||
* @param $section
|
|
||||||
* @param $key
|
|
||||||
* @param null $defaultValue
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function get($section, $key, $defaultValue=null) {
|
|
||||||
assert(!empty($key));
|
|
||||||
assert(!empty($section));
|
|
||||||
|
|
||||||
$this->initSectionIfNeeded($section);
|
|
||||||
|
|
||||||
$returnValue = $defaultValue;
|
|
||||||
if (isset($_SESSION[$section][$key])) {
|
|
||||||
$returnValue = $_SESSION[$section][$key];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a $value for $key in $section
|
|
||||||
*
|
|
||||||
* @param $section
|
|
||||||
* @param $key
|
|
||||||
* @param $value
|
|
||||||
*/
|
|
||||||
public function set($section, $key, $value) {
|
|
||||||
assert(!empty($key));
|
|
||||||
assert(!empty($section));
|
|
||||||
|
|
||||||
$this->initSectionIfNeeded($section);
|
|
||||||
|
|
||||||
$_SESSION[$section][$key] = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a session value
|
|
||||||
*
|
|
||||||
* @param $section
|
|
||||||
* @param $key
|
|
||||||
*/
|
|
||||||
public function remove($section, $key) {
|
|
||||||
assert(!empty($key));
|
|
||||||
assert(!empty($section));
|
|
||||||
|
|
||||||
unset($_SESSION[$section][$key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function initSectionIfNeeded($section) {
|
|
||||||
if (!isset($_SESSION[$section])) {
|
|
||||||
$_SESSION[$section] = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Framadate\Services;
|
|
||||||
|
|
||||||
use Framadate\Repositories\RepositoryFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The class provides action for application administrators.
|
|
||||||
*
|
|
||||||
* @package Framadate\Services
|
|
||||||
*/
|
|
||||||
class SuperAdminService {
|
|
||||||
private $pollRepository;
|
|
||||||
|
|
||||||
function __construct() {
|
|
||||||
$this->pollRepository = RepositoryFactory::pollRepository();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the list of all polls.
|
|
||||||
*
|
|
||||||
* @param array $search Array of search : ['id'=>..., 'title'=>..., 'name'=>..., 'mail'=>...]
|
|
||||||
* @param int $page The page index (O = first page)
|
|
||||||
* @param int $limit The limit size
|
|
||||||
* @return array ['polls' => The {$limit} polls, 'count' => Entries found by the query, 'total' => Total count]
|
|
||||||
*/
|
|
||||||
public function findAllPolls($search, $page, $limit) {
|
|
||||||
$start = $page * $limit;
|
|
||||||
$polls = $this->pollRepository->findAll($search, $start, $limit);
|
|
||||||
$count = $this->pollRepository->count($search);
|
|
||||||
$total = $this->pollRepository->count();
|
|
||||||
|
|
||||||
return ['polls' => $polls, 'count' => $count, 'total' => $total];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,209 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* 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 Parsedown;
|
|
||||||
|
|
||||||
class Utils {
|
|
||||||
/**
|
|
||||||
* @return string Server name
|
|
||||||
*/
|
|
||||||
public static function get_server_name() {
|
|
||||||
$serverName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '';
|
|
||||||
$serverPort = isset($_SERVER['SERVER_PORT']) ? $_SERVER['SERVER_PORT'] : '';
|
|
||||||
|
|
||||||
$scheme = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https')) ? 'https' : 'http';
|
|
||||||
$port = in_array($serverPort, ['80', '443'], true) ? '' : ':' . $serverPort;
|
|
||||||
$dirname = dirname($_SERVER['SCRIPT_NAME']);
|
|
||||||
$dirname = $dirname === '\\' ? '/' : $dirname . '/';
|
|
||||||
$dirname = str_replace('/admin', '', $dirname);
|
|
||||||
$dirname = str_replace('/action', '', $dirname);
|
|
||||||
$server_name = (defined('APP_URL') ? APP_URL : $serverName) . $port . $dirname;
|
|
||||||
|
|
||||||
return $scheme . '://' . preg_replace('#//+#', '/', $server_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $title
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
public static function print_header($title = '') {
|
|
||||||
global $locale;
|
|
||||||
|
|
||||||
echo '<!DOCTYPE html>
|
|
||||||
<html lang="' . $locale . '">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />';
|
|
||||||
|
|
||||||
if (!empty($title)) {
|
|
||||||
echo '<title>' . stripslashes($title) . ' - ' . NOMAPPLICATION . '</title>';
|
|
||||||
} else {
|
|
||||||
echo '<title>' . NOMAPPLICATION . '</title>';
|
|
||||||
}
|
|
||||||
|
|
||||||
echo '
|
|
||||||
<link rel="stylesheet" href="' . self::get_server_name() . 'css/bootstrap.min.css" />
|
|
||||||
<link rel="stylesheet" href="' . self::get_server_name() . 'css/datepicker3.css" />
|
|
||||||
<link rel="stylesheet" href="' . self::get_server_name() . 'css/style.css" />
|
|
||||||
<link rel="stylesheet" href="' . self::get_server_name() . 'css/frama.css" />
|
|
||||||
<link rel="stylesheet" href="' . self::get_server_name() . 'css/print.css" media="print" />
|
|
||||||
<script type="text/javascript" src="' . self::get_server_name() . 'js/jquery-1.12.4.min.js"></script>
|
|
||||||
<script type="text/javascript" src="' . self::get_server_name() . 'js/bootstrap.min.js"></script>
|
|
||||||
<script type="text/javascript" src="' . self::get_server_name() . 'js/bootstrap-datepicker.js"></script>';
|
|
||||||
if ('en' !== $locale) {
|
|
||||||
echo '
|
|
||||||
<script type="text/javascript" src="' . self::get_server_name() . 'js/locales/bootstrap-datepicker.' . $locale . '.js"></script>';
|
|
||||||
}
|
|
||||||
echo '
|
|
||||||
<script type="text/javascript" src="' . self::get_server_name() . 'js/core.js"></script>';
|
|
||||||
if (is_file($_SERVER['DOCUMENT_ROOT'] . "/nav/nav.js")) {
|
|
||||||
echo '<script src="/nav/nav.js" id="nav_js" type="text/javascript" charset="utf-8"></script><!-- /Framanav -->';
|
|
||||||
}
|
|
||||||
|
|
||||||
echo '
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container ombre">';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function allowing to generate poll's url
|
|
||||||
* @param string $id The poll's id
|
|
||||||
* @param bool $admin True to generate an admin URL, false for a public one
|
|
||||||
* @param string $vote_id (optional) The vote's unique id
|
|
||||||
* @param null $action
|
|
||||||
* @param null $action_value
|
|
||||||
* @return string The poll's URL.
|
|
||||||
*/
|
|
||||||
public static function getUrlSondage($id, $admin = false, $vote_id = '', $action = null, $action_value = null) {
|
|
||||||
// URL-Encode $action_value
|
|
||||||
$action_value = $action_value ? Utils::base64url_encode($action_value) : null;
|
|
||||||
|
|
||||||
if (URL_PROPRE) {
|
|
||||||
if ($admin === true) {
|
|
||||||
$url = self::get_server_name() . $id . '/admin';
|
|
||||||
} else {
|
|
||||||
$url = self::get_server_name() . $id;
|
|
||||||
}
|
|
||||||
if ($vote_id !== '') {
|
|
||||||
$url .= '/vote/' . $vote_id . "#edit";
|
|
||||||
} elseif ($action) {
|
|
||||||
if ($action_value) {
|
|
||||||
$url .= '/action/' . $action . '/' . $action_value;
|
|
||||||
} else {
|
|
||||||
$url .= '/action/' . $action;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ($admin === true) {
|
|
||||||
$url = self::get_server_name() . 'adminstuds.php?poll=' . $id;
|
|
||||||
} else {
|
|
||||||
$url = self::get_server_name() . 'studs.php?poll=' . $id;
|
|
||||||
}
|
|
||||||
if ($vote_id !== '') {
|
|
||||||
$url .= '&vote=' . $vote_id . "#edit";
|
|
||||||
} elseif ($action) {
|
|
||||||
if ($action_value) {
|
|
||||||
$url .= '&' . $action . "=" . $action_value;
|
|
||||||
} else {
|
|
||||||
$url .= '&' . $action . "=";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 '<pre>';
|
|
||||||
print_r($object);
|
|
||||||
echo '</pre>';
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function table($tableName) {
|
|
||||||
return TABLENAME_PREFIX . $tableName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function markdown($md, $clear=false, $line=true) {
|
|
||||||
$parseDown = new Parsedown();
|
|
||||||
|
|
||||||
$parseDown
|
|
||||||
->setBreaksEnabled(true)
|
|
||||||
->setSafeMode(true)
|
|
||||||
;
|
|
||||||
|
|
||||||
if ($line) {
|
|
||||||
$html = $parseDown->line($md);
|
|
||||||
} else {
|
|
||||||
$md = preg_replace_callback(
|
|
||||||
'#( ){2,}#',
|
|
||||||
function ($m) {
|
|
||||||
return str_repeat(' ', strlen($m[0]));
|
|
||||||
},
|
|
||||||
$md
|
|
||||||
);
|
|
||||||
$html = $parseDown->text($md);
|
|
||||||
}
|
|
||||||
|
|
||||||
$text = strip_tags($html);
|
|
||||||
|
|
||||||
return $clear ? $text : $html;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function htmlEscape($html) {
|
|
||||||
return htmlentities($html, ENT_HTML5 | ENT_QUOTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function htmlMailEscape($html) {
|
|
||||||
return htmlspecialchars($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);
|
|
||||||
$escaped = preg_replace("/^(=|\+|\-|\@)/", "'$1", $escaped);
|
|
||||||
|
|
||||||
return '"' . $escaped . '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function cleanFilename($title) {
|
|
||||||
$cleaned = preg_replace('[^a-zA-Z0-9._-]', '_', $title);
|
|
||||||
$cleaned = preg_replace(' {2,}', ' ', $cleaned);
|
|
||||||
|
|
||||||
return $cleaned;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function fromPostOrDefault($postKey, $default = '') {
|
|
||||||
return !empty($_POST[$postKey]) ? $_POST[$postKey] : $default;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function base64url_encode($input) {
|
|
||||||
return rtrim(strtr(base64_encode($input), '+/', '-_'), '=');
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function base64url_decode($input) {
|
|
||||||
return base64_decode(str_pad(strtr($input, '-_', '+/'), strlen($input) % 4, '=', STR_PAD_RIGHT), true);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,126 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Fully qualified domain name of your webserver.
|
|
||||||
// If this is unset or empty, the servername is determined automatically.
|
|
||||||
// You *have to set this* if you are running Framadate behind a reverse proxy.
|
|
||||||
const APP_URL = 'localhost';
|
|
||||||
|
|
||||||
// Application name
|
|
||||||
const NOMAPPLICATION = 'Framadate';
|
|
||||||
|
|
||||||
// Database administrator email
|
|
||||||
const ADRESSEMAILADMIN = 'mon@email.fr';
|
|
||||||
|
|
||||||
// Email for automatic responses (you should set it to "no-reply")
|
|
||||||
const ADRESSEMAILREPONSEAUTO = '';
|
|
||||||
|
|
||||||
// Database driver
|
|
||||||
const DB_DRIVER = 'pdo_mysql';
|
|
||||||
|
|
||||||
// Database name
|
|
||||||
const DB_NAME = 'framadate';
|
|
||||||
|
|
||||||
// Database host
|
|
||||||
const DB_HOST = 'db';
|
|
||||||
|
|
||||||
// Database port
|
|
||||||
const DB_PORT = '3307';
|
|
||||||
|
|
||||||
// Database user
|
|
||||||
const DB_USER = 'framadate';
|
|
||||||
|
|
||||||
// Database password
|
|
||||||
const DB_PASSWORD = 'framadatedbpassword';
|
|
||||||
|
|
||||||
// Table name prefix
|
|
||||||
const TABLENAME_PREFIX = 'fd_';
|
|
||||||
|
|
||||||
// Name of the table that stores migration script already executed
|
|
||||||
const MIGRATION_TABLE = 'framadate_migration';
|
|
||||||
|
|
||||||
// Default Language
|
|
||||||
const DEFAULT_LANGUAGE = 'fr';
|
|
||||||
|
|
||||||
// List of supported languages, fake constant as arrays can be used as constants only in PHP >=5.6
|
|
||||||
$ALLOWED_LANGUAGES = [
|
|
||||||
'fr' => 'Français',
|
|
||||||
'en' => 'English',
|
|
||||||
'oc' => 'Occitan',
|
|
||||||
'es' => 'Español',
|
|
||||||
'de' => 'Deutsch',
|
|
||||||
'nl' => 'Dutch',
|
|
||||||
'it' => 'Italiano',
|
|
||||||
'br' => 'Brezhoneg',
|
|
||||||
'ca' => 'Catalan',
|
|
||||||
];
|
|
||||||
|
|
||||||
// Path to image file with the title
|
|
||||||
const IMAGE_TITRE = 'images/logo-framadate.png';
|
|
||||||
|
|
||||||
// Clean URLs, boolean
|
|
||||||
const URL_PROPRE = true;
|
|
||||||
|
|
||||||
// Use REMOTE_USER data provided by web server
|
|
||||||
const USE_REMOTE_USER = true;
|
|
||||||
|
|
||||||
// Path to the log file
|
|
||||||
const LOG_FILE = 'admin/stdout.log';
|
|
||||||
|
|
||||||
// Days (after expiration date) before purging a poll
|
|
||||||
const PURGE_DELAY = 60;
|
|
||||||
|
|
||||||
// Max slots per poll
|
|
||||||
const MAX_SLOTS_PER_POLL = 366;
|
|
||||||
|
|
||||||
// Number of seconds before we allow to resend an "Remember Edit Link" email.
|
|
||||||
const TIME_EDIT_LINK_EMAIL = 60;
|
|
||||||
|
|
||||||
// uncomment to display a link to the demo poll at the home page
|
|
||||||
//const DEMO_POLL_ID = "aqg259dth55iuhwm";
|
|
||||||
|
|
||||||
// number of recent votes that are not deleted
|
|
||||||
const DEMO_POLL_NUMBER_VOTES = 10;
|
|
||||||
|
|
||||||
|
|
||||||
// Config
|
|
||||||
$config = [
|
|
||||||
/* general config */
|
|
||||||
'use_smtp' => false, // use email for polls creation/modification/responses notification (uses smtp only if `use_sendmail` is disabled)
|
|
||||||
'use_sendmail' => false, // use sendmail instead of smtp
|
|
||||||
'smtp_options' => [
|
|
||||||
'host' => 'localhost', // SMTP server (you could add many servers (main and backup for example) : use ";" like separator
|
|
||||||
'auth' => false, // Enable SMTP authentication
|
|
||||||
'username' => '', // SMTP username
|
|
||||||
'password' => '', // SMTP password
|
|
||||||
'secure' => '', // Enable encryption (false, tls or ssl)
|
|
||||||
'port' => 25, // TCP port to connect to
|
|
||||||
],
|
|
||||||
/* home */
|
|
||||||
'show_what_is_that' => true, // display "how to use" section
|
|
||||||
'show_the_software' => true, // display technical information about the software
|
|
||||||
'show_cultivate_your_garden' => true, // display "development and administration" information
|
|
||||||
/* create_classic_poll.php / create_date_poll.php */
|
|
||||||
'default_poll_duration' => 180, // default values for the new poll duration (number of days).
|
|
||||||
/* create_classic_poll.php */
|
|
||||||
'user_can_add_img_or_link' => true, // user can add link or URL when creating his poll.
|
|
||||||
'markdown_editor_by_default' => true, // The markdown editor for the description is enabled by default
|
|
||||||
'provide_fork_awesome' => true, // Whether the build-in fork-awesome should be provided
|
|
||||||
];
|
|
||||||
|
|
@ -1,116 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Fully qualified domain name of your webserver.
|
|
||||||
// If this is unset or empty, the servername is determined automatically.
|
|
||||||
// You *have to set this* if you are running Framadate behind a reverse proxy.
|
|
||||||
// const APP_URL = '<www.mydomain.fr>';
|
|
||||||
|
|
||||||
// Application name
|
|
||||||
const NOMAPPLICATION = 'Framadate';
|
|
||||||
|
|
||||||
// Database administrator email
|
|
||||||
const ADRESSEMAILADMIN = 'admin@app.tld';
|
|
||||||
|
|
||||||
// Email for automatic responses (you should set it to "no-reply")
|
|
||||||
const ADRESSEMAILREPONSEAUTO = 'no@reply';
|
|
||||||
|
|
||||||
// Database driver
|
|
||||||
const DB_DRIVER = 'pdo_sqlite';
|
|
||||||
|
|
||||||
// Database name
|
|
||||||
const DB_NAME = 'framadate';
|
|
||||||
|
|
||||||
// Database host
|
|
||||||
const DB_HOST = '';
|
|
||||||
|
|
||||||
// Database port
|
|
||||||
const DB_PORT = '';
|
|
||||||
|
|
||||||
// Database user
|
|
||||||
const DB_USER = '';
|
|
||||||
|
|
||||||
// Database password
|
|
||||||
const DB_PASSWORD = '';
|
|
||||||
|
|
||||||
// Table name prefix
|
|
||||||
const TABLENAME_PREFIX = 'fd_';
|
|
||||||
|
|
||||||
// Name of the table that stores migration script already executed
|
|
||||||
const MIGRATION_TABLE = 'framadate_migration';
|
|
||||||
|
|
||||||
// Default Language
|
|
||||||
const DEFAULT_LANGUAGE = 'fr';
|
|
||||||
|
|
||||||
// List of supported languages, fake constant as arrays can be used as constants only in PHP >=5.6
|
|
||||||
$ALLOWED_LANGUAGES = [
|
|
||||||
'fr' => 'Français',
|
|
||||||
'en' => 'English',
|
|
||||||
'oc' => 'Occitan',
|
|
||||||
'es' => 'Español',
|
|
||||||
'de' => 'Deutsch',
|
|
||||||
'nl' => 'Dutch',
|
|
||||||
'it' => 'Italiano',
|
|
||||||
'br' => 'Brezhoneg',
|
|
||||||
];
|
|
||||||
|
|
||||||
// Path to image file with the title
|
|
||||||
const IMAGE_TITRE = 'images/logo-framadate.png';
|
|
||||||
|
|
||||||
// Clean URLs, boolean
|
|
||||||
const URL_PROPRE = false;
|
|
||||||
|
|
||||||
// Use REMOTE_USER data provided by web server
|
|
||||||
const USE_REMOTE_USER = true;
|
|
||||||
|
|
||||||
// Path to the log file
|
|
||||||
const LOG_FILE = 'admin/stdout.log';
|
|
||||||
|
|
||||||
// Days (after expiration date) before purging a poll
|
|
||||||
const PURGE_DELAY = 60;
|
|
||||||
|
|
||||||
// Max slots per poll
|
|
||||||
const MAX_SLOTS_PER_POLL = 366;
|
|
||||||
|
|
||||||
// Number of seconds before we allow to resend an "Remember Edit Link" email.
|
|
||||||
const TIME_EDIT_LINK_EMAIL = 60;
|
|
||||||
|
|
||||||
// Config
|
|
||||||
$config = [
|
|
||||||
/* general config */
|
|
||||||
'use_smtp' => false, // use email for polls creation/modification/responses notification
|
|
||||||
'smtp_options' => [
|
|
||||||
'host' => 'localhost', // SMTP server (you could add many servers (main and backup for example) : use ";" like separator
|
|
||||||
'auth' => false, // Enable SMTP authentication
|
|
||||||
'username' => '', // SMTP username
|
|
||||||
'password' => '', // SMTP password
|
|
||||||
'secure' => '', // Enable encryption (false, tls or ssl)
|
|
||||||
'port' => 25, // TCP port to connect to
|
|
||||||
],
|
|
||||||
/* home */
|
|
||||||
'show_what_is_that' => true, // display "how to use" section
|
|
||||||
'show_the_software' => true, // display technical information about the software
|
|
||||||
'show_cultivate_your_garden' => true, // display "development and administration" information
|
|
||||||
/* create_classic_poll.php / create_date_poll.php */
|
|
||||||
'default_poll_duration' => 180, // default values for the new poll duration (number of days).
|
|
||||||
/* create_classic_poll.php */
|
|
||||||
'user_can_add_img_or_link' => true, // user can add link or URL when creating his poll.
|
|
||||||
'markdown_editor_by_default' => true, // The markdown editor for the description is enabled by default
|
|
||||||
'provide_fork_awesome' => true, // Whether the build-in fork-awesome should be provided
|
|
||||||
];
|
|
@ -1,45 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// FRAMADATE version
|
|
||||||
const VERSION = '1.2.0';
|
|
||||||
|
|
||||||
// PHP Needed version
|
|
||||||
const PHP_NEEDED_VERSION = '5.6';
|
|
||||||
|
|
||||||
// Config constants
|
|
||||||
const COMPILE_DIR = '/tpl_c/';
|
|
||||||
|
|
||||||
// Regex
|
|
||||||
const POLL_REGEX = '/^[a-z0-9-]*$/i';
|
|
||||||
const ADMIN_POLL_REGEX = '/^[a-z0-9]{24}$/i';
|
|
||||||
const CHOICE_REGEX = '/^[ 012]$/';
|
|
||||||
const BOOLEAN_REGEX = '/^(on|off|true|false|1|0)$/i';
|
|
||||||
const BOOLEAN_TRUE_REGEX = '/^(on|true|1)$/i';
|
|
||||||
const EDITABLE_CHOICE_REGEX = '/^[0-2]$/';
|
|
||||||
const COLLECT_MAIL_CHOICE_REGEX = '/^[0-3]$/';
|
|
||||||
const BASE64_REGEX = '/^[A-Za-z0-9]+$/';
|
|
||||||
const MD5_REGEX = '/^[A-Fa-f0-9]{32}$/';
|
|
||||||
|
|
||||||
// Session constants
|
|
||||||
const SESSION_EDIT_LINK_TOKEN = 'EditLinkToken';
|
|
||||||
const SESSION_EDIT_LINK_TIME = "EditLinkMail";
|
|
||||||
|
|
||||||
// CSRF (300s = 5min)
|
|
||||||
const TOKEN_TIME = 300;
|
|
@ -1,45 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Prepare I18N instance
|
|
||||||
$i18n = \o80\i18n\I18N::instance();
|
|
||||||
$i18n->setDefaultLang(DEFAULT_LANGUAGE);
|
|
||||||
$i18n->setPath(__DIR__ . '/../../locale');
|
|
||||||
|
|
||||||
// Change langauge when user asked for it
|
|
||||||
if (isset($_POST['lang']) && is_string($_POST['lang']) && in_array($_POST['lang'], array_keys($ALLOWED_LANGUAGES), true)) {
|
|
||||||
$_SESSION['lang'] = $_POST['lang'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* <html lang="$locale"> */
|
|
||||||
$i18n->get('', 'Something, just to load the dictionary');
|
|
||||||
$locale = str_replace('_', '-', $i18n->getLoadedLang());
|
|
||||||
|
|
||||||
/* Date Format */
|
|
||||||
$date_format['txt_full'] = __('Date', '%A, %B %e, %Y'); //summary in create_date_poll.php and removal date in choix_(date|autre).php
|
|
||||||
$date_format['txt_short'] = __('Date', '%A %e %B %Y'); // radio title
|
|
||||||
$date_format['txt_day'] = __('Date', '%a %e');
|
|
||||||
$date_format['txt_date'] = __('Date', '%Y-%m-%d');
|
|
||||||
$date_format['txt_month_year'] = __('Date', '%B %Y');
|
|
||||||
$date_format['txt_datetime_short'] = __('Date', '%m/%d/%Y %H:%M');
|
|
||||||
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('#(?<!%)((?:%%)*)%e#', '\1%#d', $v); //replace %e by %#d for windows
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Configuration;
|
|
||||||
use Doctrine\DBAL\DBALException;
|
|
||||||
use Doctrine\DBAL\DriverManager;
|
|
||||||
use Framadate\Repositories\RepositoryFactory;
|
|
||||||
use Framadate\Services\LogService;
|
|
||||||
|
|
||||||
// Autoloading of dependencies with Composer
|
|
||||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
|
||||||
require_once __DIR__ . '/../../vendor/o80/i18n/src/shortcuts.php';
|
|
||||||
|
|
||||||
if (session_id() === '') {
|
|
||||||
session_start();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ini_get('date.timezone') === '') {
|
|
||||||
date_default_timezone_set('Europe/Paris');
|
|
||||||
}
|
|
||||||
|
|
||||||
define('ROOT_DIR', __DIR__ . '/../../');
|
|
||||||
|
|
||||||
$path = '/app/inc/config.php';
|
|
||||||
if (getenv('APP_ENV') === 'test') {
|
|
||||||
$path = '/app/inc/config.test.php';
|
|
||||||
}
|
|
||||||
define('CONF_FILENAME', ROOT_DIR . $path);
|
|
||||||
|
|
||||||
require_once __DIR__ . '/constants.php';
|
|
||||||
|
|
||||||
if (is_file(CONF_FILENAME)) {
|
|
||||||
@include_once CONF_FILENAME;
|
|
||||||
|
|
||||||
// Connection to database
|
|
||||||
$doctrineConfig = new Configuration();
|
|
||||||
$connectionParams = [
|
|
||||||
'dbname' => DB_NAME,
|
|
||||||
'user' => DB_USER,
|
|
||||||
'password' => DB_PASSWORD,
|
|
||||||
'host' => DB_HOST,
|
|
||||||
'driver' => DB_DRIVER,
|
|
||||||
'charset' => DB_DRIVER === 'pdo_mysql' ? 'utf8mb4' : 'utf8',
|
|
||||||
];
|
|
||||||
|
|
||||||
if (DB_DRIVER === 'pdo_sqlite') {
|
|
||||||
$connectionParams['path'] = 'test_database.sqlite';
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$connect = DriverManager::getConnection($connectionParams, $doctrineConfig);
|
|
||||||
RepositoryFactory::init($connect);
|
|
||||||
$err = 0;
|
|
||||||
} catch (DBALException $e) {
|
|
||||||
$logger = new LogService();
|
|
||||||
$logger->log('ERROR', $e->getMessage());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
define('NOMAPPLICATION', 'Framadate');
|
|
||||||
define('DEFAULT_LANGUAGE', 'fr');
|
|
||||||
define('IMAGE_TITRE', 'images/logo-framadate.png');
|
|
||||||
define('LOG_FILE', 'admin/stdout.log');
|
|
||||||
$ALLOWED_LANGUAGES = [
|
|
||||||
'fr' => 'Français',
|
|
||||||
'en' => 'English',
|
|
||||||
'es' => 'Español',
|
|
||||||
'de' => 'Deutsch',
|
|
||||||
'it' => 'Italiano',
|
|
||||||
'br' => 'Brezhoneg',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once __DIR__ . '/i18n.php';
|
|
||||||
// Smarty
|
|
||||||
require_once __DIR__ . '/smarty.php';
|
|
@ -1,122 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../../vendor/smarty/smarty/libs/Smarty.class.php';
|
|
||||||
$smarty = new \Smarty();
|
|
||||||
$smarty->setTemplateDir(ROOT_DIR . '/tpl/');
|
|
||||||
$smarty->setCompileDir(ROOT_DIR . COMPILE_DIR);
|
|
||||||
$smarty->setCacheDir(ROOT_DIR . '/cache/');
|
|
||||||
$smarty->caching = false;
|
|
||||||
|
|
||||||
$serverName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '';
|
|
||||||
|
|
||||||
$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', strstr($serverName, 'framadate.org'));
|
|
||||||
$smarty->assign('provide_fork_awesome', !isset($config['provide_fork_awesome']) || $config['provide_fork_awesome']);
|
|
||||||
$smarty->assign('locale', $locale);
|
|
||||||
$smarty->assign('langs', $ALLOWED_LANGUAGES);
|
|
||||||
$smarty->assign('date_format', $date_format);
|
|
||||||
if (isset($config['tracking_code'])) {
|
|
||||||
$smarty->assign('tracking_code', $config['tracking_code']);
|
|
||||||
}
|
|
||||||
if (defined('FAVICON')) {
|
|
||||||
$smarty->assign('favicon', FAVICON);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dev Mode
|
|
||||||
if (isset($_SERVER['FRAMADATE_DEVMODE']) && $_SERVER['FRAMADATE_DEVMODE'] || php_sapi_name() === 'cli-server') {
|
|
||||||
$smarty->force_compile = true;
|
|
||||||
$smarty->compile_check = true;
|
|
||||||
} else {
|
|
||||||
$smarty->force_compile = false;
|
|
||||||
$smarty->compile_check = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function smarty_function_poll_url($params, Smarty_Internal_Template $template) {
|
|
||||||
$poll_id = filter_var($params['id'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
|
|
||||||
$admin = (isset($params['admin']) && $params['admin']) ? true : false;
|
|
||||||
$action = (isset($params['action']) && !empty($params['action'])) ? Utils::htmlEscape($params['action']) : false;
|
|
||||||
$action_value = (isset($params['action_value']) && !empty($params['action_value'])) ? $params['action_value'] : false;
|
|
||||||
$vote_unique_id = isset($params['vote_id']) ? filter_var($params['vote_id'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]) : '';
|
|
||||||
|
|
||||||
// If filter_var fails (i.e.: hack tentative), it will return false. At least no leak is possible from this.
|
|
||||||
|
|
||||||
return Utils::getUrlSondage($poll_id, $admin, $vote_unique_id, $action, $action_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function smarty_modifier_markdown($md, $clear = false, $inline=true) {
|
|
||||||
return Utils::markdown($md, $clear, $inline);
|
|
||||||
}
|
|
||||||
|
|
||||||
function smarty_modifier_resource($link) {
|
|
||||||
return Utils::get_server_name() . $link;
|
|
||||||
}
|
|
||||||
function smarty_modifier_addslashes_single_quote($string) {
|
|
||||||
return addcslashes($string, '\\\'');
|
|
||||||
}
|
|
||||||
|
|
||||||
function smarty_modifier_html($html) {
|
|
||||||
return Utils::htmlEscape($html);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* markdown_to_text
|
|
||||||
* Retrieves a markdown string and tries to make a plain text value
|
|
||||||
*
|
|
||||||
* @param array $options
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function smarty_function_markdown_to_text($options, Smarty_Internal_Template $template)
|
|
||||||
{
|
|
||||||
$locale = \o80\i18n\I18N::instance()->getLoadedLang();
|
|
||||||
$text = strip_tags(Parsedown::instance()->text($options['markdown']));
|
|
||||||
$number_letters = (new NumberFormatter($locale, NumberFormatter::ORDINAL))->format($options['id'] + 1);
|
|
||||||
return $text !== '' ? $text : __f('Poll results', '%s option', $number_letters);
|
|
||||||
}
|
|
||||||
|
|
||||||
function smarty_modifier_datepicker_path($lang) {
|
|
||||||
$i = 0;
|
|
||||||
while (!is_file(path_for_datepicker_locale($lang)) && $i < 3) {
|
|
||||||
$lang_arr = explode('-', $lang);
|
|
||||||
if ($lang_arr && count($lang_arr) > 1) {
|
|
||||||
$lang = $lang_arr[0];
|
|
||||||
} else {
|
|
||||||
$lang = 'en';
|
|
||||||
}
|
|
||||||
$i += 1;
|
|
||||||
}
|
|
||||||
return 'js/locales/bootstrap-datepicker.' . $lang . '.js';
|
|
||||||
}
|
|
||||||
|
|
||||||
function smarty_modifier_locale_2_lang($locale) {
|
|
||||||
$lang_arr = explode('-', $locale);
|
|
||||||
if ($lang_arr && count($lang_arr) > 1) {
|
|
||||||
return $lang_arr[0];
|
|
||||||
}
|
|
||||||
return $locale;
|
|
||||||
}
|
|
||||||
|
|
||||||
function path_for_datepicker_locale($lang) {
|
|
||||||
return __DIR__ . '/../../js/locales/bootstrap-datepicker.' . $lang . '.js';
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Framadate;
|
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
abstract class FramaTestCase extends TestCase {
|
|
||||||
protected function getTestResourcePath($resourcepath) {
|
|
||||||
return __DIR__ . '/../resources/' . $resourcepath;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function readTestResource($resourcepath) {
|
|
||||||
return file_get_contents($this->getTestResourcePath($resourcepath));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function invoke(&$object, $methodName) {
|
|
||||||
$reflectionClass = new \ReflectionClass($object);
|
|
||||||
$reflectionMethod = $reflectionClass->getMethod($methodName);
|
|
||||||
$reflectionMethod->setAccessible(true);
|
|
||||||
|
|
||||||
$params = array_slice(func_get_args(), 2); // get all the parameters after $methodName
|
|
||||||
return $reflectionMethod->invokeArgs($object, $params);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Framadate\Services;
|
|
||||||
|
|
||||||
use Framadate\FramaTestCase;
|
|
||||||
|
|
||||||
class InputServiceUnitTest extends FramaTestCase
|
|
||||||
{
|
|
||||||
public function liste_emails()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
// valids addresses
|
|
||||||
"valid address" => ["example@example.com", "example@example.com"],
|
|
||||||
"local address" => ["test@localhost", "test@localhost"],
|
|
||||||
"IP address" => ["ip.email@127.0.0.1", "ip.email@127.0.0.1"],
|
|
||||||
"with spaces arround" => [" with@spaces ", "with@spaces"],
|
|
||||||
"unicode caracters" => ["unicode.éà@idn-œ.com", "unicode.éà@idn-œ.com"],
|
|
||||||
// invalids addresses
|
|
||||||
"without domain" => ["without-domain", FALSE],
|
|
||||||
"space inside" => ["example example@example.com", FALSE],
|
|
||||||
"forbidden chars" => ["special_chars.@example.com", FALSE],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider liste_emails
|
|
||||||
*/
|
|
||||||
public function test_filterMail($email, $expected)
|
|
||||||
{
|
|
||||||
$inputService = new InputService();
|
|
||||||
$filtered = $inputService->filterMail($email);
|
|
||||||
|
|
||||||
$this->assertSame($expected, $filtered);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Framadate\Services;
|
|
||||||
|
|
||||||
use Framadate\FramaTestCase;
|
|
||||||
|
|
||||||
class MailServiceUnitTest extends FramaTestCase {
|
|
||||||
const MSG_KEY = '666';
|
|
||||||
|
|
||||||
public function test_should_send_a_2nd_mail_after_a_good_interval() {
|
|
||||||
// Given
|
|
||||||
$mailService = new MailService(true);
|
|
||||||
$_SESSION[MailService::MAILSERVICE_KEY] = [self::MSG_KEY => time() - 1000];
|
|
||||||
|
|
||||||
// When
|
|
||||||
$canSendMsg = $mailService->canSendMsg(self::MSG_KEY);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
$this->assertSame(true, $canSendMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_should_not_send_2_mails_in_a_short_interval() {
|
|
||||||
// Given
|
|
||||||
$mailService = new MailService(true);
|
|
||||||
$_SESSION[MailService::MAILSERVICE_KEY] = [self::MSG_KEY => time()];
|
|
||||||
|
|
||||||
// When
|
|
||||||
$canSendMsg = $mailService->canSendMsg(self::MSG_KEY);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
$this->assertSame(false, $canSendMsg);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
<?php
|
|
||||||
$loader = require __DIR__ . '/../../vendor/autoload.php';
|
|
||||||
$loader->addPsr4('Framadate\\', __DIR__ . '/Framadate');
|
|
72
bandeaux.php
72
bandeaux.php
@ -1,72 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
include_once __DIR__ . '/app/inc/init.php';
|
|
||||||
|
|
||||||
// bandeaux de titre
|
|
||||||
function bandeau_titre($titre)
|
|
||||||
{
|
|
||||||
global $ALLOWED_LANGUAGES;
|
|
||||||
$img = ( IMAGE_TITRE ) ? '<img src="' . Utils::get_server_name() . IMAGE_TITRE . '" alt="' . NOMAPPLICATION . '" class="img-responsive">' : '';
|
|
||||||
echo '
|
|
||||||
<header role="banner">';
|
|
||||||
if(count($ALLOWED_LANGUAGES) > 1){
|
|
||||||
echo '<form method="post" action="" class="hidden-print">
|
|
||||||
<div class="input-group input-group-sm pull-right col-md-2 col-xs-4">
|
|
||||||
<select name="lang" class="form-control" title="' . __('Language selector', 'Select language') . '" >' . liste_lang() . '</select>
|
|
||||||
<span class="input-group-btn">
|
|
||||||
<button type="submit" class="btn btn-default btn-sm" title="' . __('Language selector', 'Change language') . '">OK</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</form>';
|
|
||||||
}
|
|
||||||
echo '
|
|
||||||
<h1><a href="' . Utils::get_server_name() . '" title="' . __('Generic', 'Home') . ' - ' . NOMAPPLICATION . '">' . $img . '</a></h1>
|
|
||||||
<h2 class="lead"><i>' . $titre . '</i></h2>
|
|
||||||
<hr class="trait" role="presentation" />
|
|
||||||
</header>
|
|
||||||
<main role="main">';
|
|
||||||
}
|
|
||||||
|
|
||||||
function liste_lang()
|
|
||||||
{
|
|
||||||
global $ALLOWED_LANGUAGES; global $locale;
|
|
||||||
|
|
||||||
$str = '';
|
|
||||||
|
|
||||||
foreach ($ALLOWED_LANGUAGES as $k => $v ) {
|
|
||||||
if (substr($k,0,2)===$locale) {
|
|
||||||
$str .= '<option lang="' . substr($k,0,2) . '" selected value="' . $k . '">' . $v . '</option>' . "\n" ;
|
|
||||||
} else {
|
|
||||||
$str .= '<option lang="' . substr($k,0,2) . '" value="' . $k . '">' . $v . '</option>' . "\n" ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $str;
|
|
||||||
}
|
|
||||||
|
|
||||||
function bandeau_pied()
|
|
||||||
{
|
|
||||||
echo '
|
|
||||||
</main>
|
|
||||||
</div> <!-- .container -->
|
|
||||||
</body>
|
|
||||||
</html>' . "\n";
|
|
||||||
}
|
|
58
bin/doctrine
58
bin/doctrine
@ -1,58 +0,0 @@
|
|||||||
#!/usr/bin/env php
|
|
||||||
<?php
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Migrations\Configuration\Configuration;
|
|
||||||
use Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper;
|
|
||||||
use Framadate\Utils;
|
|
||||||
use Symfony\Component\Console\Application;
|
|
||||||
use Symfony\Component\Console\Helper\HelperSet;
|
|
||||||
use Symfony\Component\Console\Helper\QuestionHelper;
|
|
||||||
use Symfony\Component\Console\Input\ArgvInput;
|
|
||||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
|
||||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
|
||||||
|
|
||||||
try {
|
|
||||||
require_once __DIR__ . '/../app/inc/init.php';
|
|
||||||
|
|
||||||
$input = new ArgvInput();
|
|
||||||
$output = new ConsoleOutput();
|
|
||||||
$style = new SymfonyStyle($input, $output);
|
|
||||||
|
|
||||||
if ($connect === null) {
|
|
||||||
throw new \Exception("Undefined database connection\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// replace the ConsoleRunner::run() statement with:
|
|
||||||
$cli = new Application('Doctrine Command Line Interface', VERSION);
|
|
||||||
$cli->setCatchExceptions(true);
|
|
||||||
|
|
||||||
$helperSet = new HelperSet(
|
|
||||||
[
|
|
||||||
'db' => new ConnectionHelper($connect),
|
|
||||||
'question' => new QuestionHelper(),
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
$cli->setHelperSet($helperSet);
|
|
||||||
|
|
||||||
$migrateCommand = new \Doctrine\DBAL\Migrations\Tools\Console\Command\MigrateCommand();
|
|
||||||
$statusCommand = new \Doctrine\DBAL\Migrations\Tools\Console\Command\StatusCommand();
|
|
||||||
|
|
||||||
$migrationsDirectory = __DIR__ . '/../app/classes/Framadate/Migrations';
|
|
||||||
|
|
||||||
$configuration = new Configuration($connect);
|
|
||||||
$configuration->setMigrationsTableName(Utils::table(MIGRATION_TABLE) . '_new');
|
|
||||||
$configuration->setMigrationsDirectory($migrationsDirectory);
|
|
||||||
$configuration->setMigrationsNamespace('DoctrineMigrations');
|
|
||||||
$configuration->registerMigrationsFromDirectory($migrationsDirectory);
|
|
||||||
$migrateCommand->setMigrationConfiguration($configuration);
|
|
||||||
$statusCommand->setMigrationConfiguration($configuration);
|
|
||||||
|
|
||||||
// Register All Doctrine Commands
|
|
||||||
$cli->addCommands([$migrateCommand, $statusCommand]);
|
|
||||||
|
|
||||||
// Runs console application
|
|
||||||
$cli->run($input, $output);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
$style->error($e->getMessage());
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
<?php
|
|
||||||
include_once __DIR__ . '/app/inc/init.php';
|
|
||||||
?>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
</head>
|
|
||||||
<body><pre><?php
|
|
||||||
|
|
||||||
$goodLang = $_GET['good'];
|
|
||||||
$otherLang = $_GET['other'];
|
|
||||||
|
|
||||||
$good = json_decode(file_get_contents(__DIR__ . '/locale/' . $goodLang . '.json'), true);
|
|
||||||
$other = json_decode(file_get_contents(__DIR__ . '/locale/' . $otherLang . '.json'), true);
|
|
||||||
|
|
||||||
foreach ($good as $sectionName => $section) {
|
|
||||||
foreach ($section as $key => $value) {
|
|
||||||
$good[$sectionName][$key] = getFromOther($other, $key, $value, $otherLang);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
echo json_encode($good, JSON_PRETTY_PRINT | ~(JSON_ERROR_UTF8 | JSON_HEX_QUOT | JSON_HEX_APOS));
|
|
||||||
|
|
||||||
function getFromOther($other, $goodKey, $default, $otherLang) {
|
|
||||||
foreach ($other as $sectionName => $section) {
|
|
||||||
foreach ($section as $key => $value) {
|
|
||||||
if (
|
|
||||||
strtolower($key) === strtolower($goodKey) ||
|
|
||||||
strtolower(trim($key)) === strtolower($goodKey) ||
|
|
||||||
strtolower(substr($key, 0, strlen($key) - 1)) === strtolower($goodKey) ||
|
|
||||||
strtolower(trim(substr(trim($key), 0, strlen($key) - 1))) === strtolower($goodKey)
|
|
||||||
) {
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
echo '[-]' . $goodKey . "\n";
|
|
||||||
|
|
||||||
return strtoupper($otherLang) . '_' . $default;
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
</pre>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
68
compare.php
68
compare.php
@ -1,68 +0,0 @@
|
|||||||
<?php
|
|
||||||
include_once __DIR__ . '/app/inc/init.php';
|
|
||||||
?>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
</head>
|
|
||||||
<body><pre><?php
|
|
||||||
|
|
||||||
$goodLang = $_GET['good'];
|
|
||||||
$testLang = $_GET['test'];
|
|
||||||
|
|
||||||
$good = json_decode(file_get_contents(__DIR__ . '/locale/' . $goodLang . '.json'), true);
|
|
||||||
$test = json_decode(file_get_contents(__DIR__ . '/locale/' . $testLang . '.json'), true);
|
|
||||||
|
|
||||||
$diffSection = false;
|
|
||||||
|
|
||||||
foreach ($good as $sectionName => $section) {
|
|
||||||
if (!isset($test[$sectionName])) {
|
|
||||||
echo '- section: ' . $sectionName . "\n";
|
|
||||||
$diffSection = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach ($test as $sectionName => $section) {
|
|
||||||
if (!isset($good[$sectionName])) {
|
|
||||||
echo '+ section: ' . $sectionName . "\n";
|
|
||||||
$diffSection = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$diffSection and array_keys($good)!==array_keys($test)) {
|
|
||||||
var_dump(array_keys($good));
|
|
||||||
var_dump(array_keys($test));
|
|
||||||
} else {
|
|
||||||
echo 'All sections are in two langs.' . "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$diff = [];
|
|
||||||
|
|
||||||
foreach ($good as $sectionName => $section) {
|
|
||||||
$diffSection = false;
|
|
||||||
foreach($section as $key=>$value) {
|
|
||||||
if (!isset($test[$sectionName][$key])) {
|
|
||||||
$diff[$sectionName]['-'][] = $key;
|
|
||||||
$diffSection = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$diffSection and array_keys($good[$sectionName]) !== array_keys($test[$sectionName])) {
|
|
||||||
$diff[$sectionName]['order_good'] = array_keys($good[$sectionName]);
|
|
||||||
$diff[$sectionName]['order_test'] = array_keys($test[$sectionName]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($test as $sectionName => $section) {
|
|
||||||
foreach($section as $key=>$value) {
|
|
||||||
if (!isset($good[$sectionName][$key])) {
|
|
||||||
$diff[$sectionName]['+'][] = $key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (count($diff) > 0) {
|
|
||||||
var_dump($diff);
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
</pre>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,87 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "framasoft/framadate",
|
|
||||||
"description": "Application to facilitate the schedule of events or classic polls",
|
|
||||||
"homepage": "https://framadate.org/",
|
|
||||||
"keywords": ["poll", "framadate"],
|
|
||||||
"version": "0.9.0",
|
|
||||||
"license": "CECILL-B",
|
|
||||||
|
|
||||||
"type": "project",
|
|
||||||
"support": {
|
|
||||||
"issues": "https://framagit.org/framasoft/framadate/issues"
|
|
||||||
},
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Thomas CITHAREL",
|
|
||||||
"email": "tcit@tcit.fr",
|
|
||||||
"role": "Maintainer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "JosephK",
|
|
||||||
"email": "joseph@framasoft.org",
|
|
||||||
"role": "Maintainer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Olivier PEREZ",
|
|
||||||
"email": "olivier@olivierperez.fr",
|
|
||||||
"role": "Former maintainer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Antonin MURTIN",
|
|
||||||
"email": "antonin.murtin@gmail.com",
|
|
||||||
"role": "Former developper"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Simon LEBLANC",
|
|
||||||
"role": "Former developper",
|
|
||||||
"email": "contact@leblanc-simon.eu"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Pierre-Yves GOSSET",
|
|
||||||
"role": "Former developper",
|
|
||||||
"email": "pyg@framasoft.org"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Guilhem BORGHESI",
|
|
||||||
"role": "Studs developper",
|
|
||||||
"email": "borghesi@unistra.fr"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Raphaël DROZ",
|
|
||||||
"role": "Studs developper",
|
|
||||||
"email": "raphael.droz@gmail.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.6.0",
|
|
||||||
"ext-pdo": "*",
|
|
||||||
"smarty/smarty": "^3.1",
|
|
||||||
"o80/i18n": "dev-develop",
|
|
||||||
"phpmailer/phpmailer": "~6.0",
|
|
||||||
"ircmaxell/password-compat": "dev-master",
|
|
||||||
"roave/security-advisories": "dev-master",
|
|
||||||
"erusev/parsedown": "^1.7",
|
|
||||||
"egulias/email-validator": "~2.1",
|
|
||||||
"doctrine/dbal": "^2.5",
|
|
||||||
"doctrine/migrations": "^1.5",
|
|
||||||
"sensiolabs/ansi-to-html": "^1.1"
|
|
||||||
},
|
|
||||||
|
|
||||||
"require-dev": {
|
|
||||||
"phpunit/phpunit": "^5.7",
|
|
||||||
"friendsofphp/php-cs-fixer": "~2.0"
|
|
||||||
},
|
|
||||||
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Framadate\\": "app/classes/Framadate/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"config": {
|
|
||||||
"platform": {
|
|
||||||
"php": "5.6.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
3566
composer.lock
generated
3566
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,220 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
use Framadate\Choice;
|
|
||||||
use Framadate\Form;
|
|
||||||
use Framadate\Services\InputService;
|
|
||||||
use Framadate\Services\LogService;
|
|
||||||
use Framadate\Services\MailService;
|
|
||||||
use Framadate\Services\PollService;
|
|
||||||
use Framadate\Services\PurgeService;
|
|
||||||
use Framadate\Services\SessionService;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
include_once __DIR__ . '/app/inc/init.php';
|
|
||||||
|
|
||||||
/* Service */
|
|
||||||
/*---------*/
|
|
||||||
$logService = new LogService();
|
|
||||||
$pollService = new PollService($connect, $logService);
|
|
||||||
$mailService = new MailService($config['use_smtp'], $config['smtp_options'], $config['use_sendmail']);
|
|
||||||
$purgeService = new PurgeService($connect, $logService);
|
|
||||||
$sessionService = new SessionService();
|
|
||||||
|
|
||||||
if (is_file('bandeaux_local.php')) {
|
|
||||||
include_once('bandeaux_local.php');
|
|
||||||
} else {
|
|
||||||
include_once('bandeaux.php');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Min/Max archive date
|
|
||||||
$min_expiry_time = $pollService->minExpiryDate();
|
|
||||||
$max_expiry_time = $pollService->maxExpiryDate();
|
|
||||||
|
|
||||||
$form = isset($_SESSION['form']) ? unserialize($_SESSION['form']) : null;
|
|
||||||
|
|
||||||
if ($form === null || !($form instanceof Form)) {
|
|
||||||
$smarty->assign('title', __('Error', 'Error!'));
|
|
||||||
$smarty->assign('error', __('Error', 'You haven\'t filled the first section of the poll creation, or your session has expired.'));
|
|
||||||
$smarty->display('error.tpl');
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The poll format is AUTRE (other) if we are in this file
|
|
||||||
if (!isset($form->format)) {
|
|
||||||
$form->format = 'A';
|
|
||||||
}
|
|
||||||
|
|
||||||
// The poll format is AUTRE (other)
|
|
||||||
if ($form->format !== 'A') {
|
|
||||||
$form->format = 'A';
|
|
||||||
$form->clearChoices();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($form->title) || !isset($form->admin_name) || ($config['use_smtp'] && !isset($form->admin_mail))) {
|
|
||||||
$step = 1;
|
|
||||||
} elseif (isset($_POST['confirmation'])) {
|
|
||||||
$step = 4;
|
|
||||||
} elseif (empty($_POST['fin_sondage_autre']) ) {
|
|
||||||
$step = 2;
|
|
||||||
} else {
|
|
||||||
$step = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($step) {
|
|
||||||
case 2: // Step 2/4 : Select choices of the poll
|
|
||||||
$choices = $form->getChoices();
|
|
||||||
$nb_choices = max( 5- count($choices), 0);
|
|
||||||
while ($nb_choices-- > 0) {
|
|
||||||
$c = new Choice('');
|
|
||||||
$form->addChoice($c);
|
|
||||||
}
|
|
||||||
|
|
||||||
$_SESSION['form'] = serialize($form);
|
|
||||||
|
|
||||||
// Display step 2
|
|
||||||
$smarty->assign('title', __('Step 2 classic', 'Poll options (2 of 3)'));
|
|
||||||
$smarty->assign('choices', $form->getChoices());
|
|
||||||
$smarty->assign('allowMarkdown', $config['user_can_add_img_or_link']);
|
|
||||||
$smarty->assign('error', null);
|
|
||||||
|
|
||||||
$smarty->display('create_classic_poll_step_2.tpl');
|
|
||||||
exit;
|
|
||||||
|
|
||||||
case 3: // Step 3/4 : Confirm poll creation and choose a removal date
|
|
||||||
// Handle Step2 submission
|
|
||||||
if (!empty($_POST['choices'])) {
|
|
||||||
// remove empty choices
|
|
||||||
$_POST['choices'] = array_filter($_POST['choices'], function ($c) {
|
|
||||||
return !empty($c);
|
|
||||||
});
|
|
||||||
|
|
||||||
$form->clearChoices();
|
|
||||||
|
|
||||||
// store choices in $_SESSION
|
|
||||||
foreach ($_POST['choices'] as $c) {
|
|
||||||
$c = strip_tags($c);
|
|
||||||
$choice = new Choice($c);
|
|
||||||
$form->addChoice($choice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expiry date is initialised with config parameter. Value will be modified in step 4 if user has defined an other date
|
|
||||||
$form->end_date = $max_expiry_time;
|
|
||||||
|
|
||||||
// Summary
|
|
||||||
$summary = '<ol>';
|
|
||||||
foreach ($form->getChoices() as $i => $choice) {
|
|
||||||
/** @var Choice $choice */
|
|
||||||
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]) : __('Generic', 'Choice') . ' ' . ($i + 1);
|
|
||||||
$li_subject_html = '<a href="' . $md_a_img[3][0] . '"><img src="' . $md_a_img[2][0] . '" class="img-responsive" alt="' . $li_subject_text . '" /></a>';
|
|
||||||
} 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]) : __('Generic', 'Choice') . ' ' . ($i + 1);
|
|
||||||
$li_subject_html = '<img src="' . $md_img[2][0] . '" class="img-responsive" alt="' . $li_subject_text . '" />';
|
|
||||||
} 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]) : __('Generic', 'Choice') . ' ' . ($i + 1);
|
|
||||||
$li_subject_html = '<a href="' . $md_a[2][0] . '">' . $li_subject_text . '</a>';
|
|
||||||
} else { // text only
|
|
||||||
$li_subject_text = stripslashes($choice->getName());
|
|
||||||
$li_subject_html = $li_subject_text;
|
|
||||||
}
|
|
||||||
|
|
||||||
$summary .= '<li>' . $li_subject_html . '</li>' . "\n";
|
|
||||||
}
|
|
||||||
$summary .= '</ol>';
|
|
||||||
|
|
||||||
$end_date_str = utf8_encode(strftime($date_format['txt_date'], $max_expiry_time)); //textual date
|
|
||||||
|
|
||||||
$_SESSION['form'] = serialize($form);
|
|
||||||
|
|
||||||
$smarty->assign('title', __('Step 3', 'Removal date and confirmation (3 of 3)'));
|
|
||||||
$smarty->assign('summary', $summary);
|
|
||||||
$smarty->assign('end_date_str', $end_date_str);
|
|
||||||
$smarty->assign('default_poll_duration', $config['default_poll_duration']);
|
|
||||||
$smarty->assign('use_smtp', $config['use_smtp']);
|
|
||||||
|
|
||||||
$smarty->display('create_poll_step_3.tpl');
|
|
||||||
exit;
|
|
||||||
case 4: // Step 4 : Data prepare before insert in DB
|
|
||||||
$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_expiry_time) {
|
|
||||||
$form->end_date = $min_expiry_time;
|
|
||||||
} elseif ($max_expiry_time < $time) {
|
|
||||||
$form->end_date = $max_expiry_time;
|
|
||||||
} else {
|
|
||||||
$form->end_date = $time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($form->end_date)) {
|
|
||||||
// By default, expiration date is 6 months after last day
|
|
||||||
$form->end_date = $max_expiry_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert poll in database
|
|
||||||
$ids = $pollService->createPoll($form);
|
|
||||||
$poll_id = $ids[0];
|
|
||||||
$admin_poll_id = $ids[1];
|
|
||||||
|
|
||||||
// Send confirmation by mail if enabled
|
|
||||||
if ($config['use_smtp'] === true) {
|
|
||||||
$message = __('Mail', "This is the message to forward to the poll participants.");
|
|
||||||
$message .= '<br/><br/>';
|
|
||||||
$message .= Utils::htmlMailEscape($form->admin_name) . ' ' . __('Mail', 'has just created a poll called') . ' : "' . Utils::htmlMailEscape($form->title) . '".<br/>';
|
|
||||||
$message .= sprintf(__('Mail', 'Thank you for participating in the poll at the following link') . ' :<br/><br/><a href="%1$s">%1$s</a>', Utils::getUrlSondage($poll_id));
|
|
||||||
|
|
||||||
$message_admin = __('Mail', "This message should NOT be sent to the poll participants. You should keep it private. <br/><br/>You can modify your poll at the following link");
|
|
||||||
$message_admin .= sprintf(' :<br/><br/><a href="%1$s">%1$s</a>', Utils::getUrlSondage($admin_poll_id, true));
|
|
||||||
|
|
||||||
if ($mailService->isValidEmail($form->admin_mail)) {
|
|
||||||
$mailService->send($form->admin_mail, '[' . NOMAPPLICATION . '][' . __('Mail', 'Message for the author') . '] ' . __('Generic', 'Poll') . ': ' . $form->title, $message_admin);
|
|
||||||
$mailService->send($form->admin_mail, '[' . NOMAPPLICATION . '][' . __('Mail', 'Participant link') . '] ' . __('Generic', 'Poll') . ': ' . $form->title, $message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean Form data in $_SESSION
|
|
||||||
unset($_SESSION['form']);
|
|
||||||
|
|
||||||
// Delete old polls
|
|
||||||
$purgeService->purgeOldPolls();
|
|
||||||
|
|
||||||
// creation message
|
|
||||||
$sessionService->set("Framadate", "messagePollCreated", TRUE);
|
|
||||||
// Redirect to poll administration
|
|
||||||
header('Location:' . Utils::getUrlSondage($admin_poll_id, true));
|
|
||||||
exit;
|
|
||||||
|
|
||||||
case 1: // Step 1/4 : error if $_SESSION from info_sondage are not valid
|
|
||||||
default:
|
|
||||||
$smarty->assign('title', __('Error', 'Error!'));
|
|
||||||
$smarty->assign('error', __('Error', 'You haven\'t filled the first section of the poll creation, or your session has expired.'));
|
|
||||||
$smarty->display('error.tpl');
|
|
||||||
exit;
|
|
||||||
}
|
|
@ -1,263 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft https://framagit.org/framasoft/framadate/)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft https://framagit.org/framasoft/framadate/)
|
|
||||||
*/
|
|
||||||
use Framadate\Choice;
|
|
||||||
use Framadate\Form;
|
|
||||||
use Framadate\Services\InputService;
|
|
||||||
use Framadate\Services\LogService;
|
|
||||||
use Framadate\Services\MailService;
|
|
||||||
use Framadate\Services\PollService;
|
|
||||||
use Framadate\Services\PurgeService;
|
|
||||||
use Framadate\Services\SessionService;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
include_once __DIR__ . '/app/inc/init.php';
|
|
||||||
|
|
||||||
/* Service */
|
|
||||||
/*---------*/
|
|
||||||
$logService = new LogService();
|
|
||||||
$pollService = new PollService($connect, $logService);
|
|
||||||
$mailService = new MailService($config['use_smtp'], $config['smtp_options'], $config['use_sendmail']);
|
|
||||||
$purgeService = new PurgeService($connect, $logService);
|
|
||||||
$inputService = new InputService();
|
|
||||||
$sessionService = new SessionService();
|
|
||||||
|
|
||||||
if (is_readable('bandeaux_local.php')) {
|
|
||||||
include_once('bandeaux_local.php');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Min/Max archive date
|
|
||||||
$min_expiry_time = $pollService->minExpiryDate();
|
|
||||||
$max_expiry_time = $pollService->maxExpiryDate();
|
|
||||||
|
|
||||||
$form = isset($_SESSION['form']) ? unserialize($_SESSION['form']) : null;
|
|
||||||
|
|
||||||
if ($form === null || !($form instanceof Form)) {
|
|
||||||
$smarty->assign('title', __('Error', 'Error!'));
|
|
||||||
$smarty->assign('error', __('Error', 'You haven\'t filled the first section of the poll creation, or your session has expired.'));
|
|
||||||
$smarty->display('error.tpl');
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The poll format is DATE if we are in this file
|
|
||||||
if (!isset($form->format)) {
|
|
||||||
$form->format = 'D';
|
|
||||||
}
|
|
||||||
// If we come from another format, we need to clear choices
|
|
||||||
if ($form->format !== 'D') {
|
|
||||||
$form->format = 'D';
|
|
||||||
$form->clearChoices();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($form->title) || !isset($form->admin_name) || ($config['use_smtp'] && !isset($form->admin_mail))) {
|
|
||||||
$step = 1;
|
|
||||||
} else if (!empty($_POST['confirmation'])) {
|
|
||||||
$step = 4;
|
|
||||||
} else if (empty($_POST['choixheures']) || isset($form->totalchoixjour)) {
|
|
||||||
$step = 2;
|
|
||||||
} else {
|
|
||||||
$step = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($step) {
|
|
||||||
case 2:
|
|
||||||
// Step 2/4 : Select dates of the poll
|
|
||||||
|
|
||||||
// Prefill form->choices
|
|
||||||
foreach ($form->getChoices() as $c) {
|
|
||||||
/** @var Choice $c */
|
|
||||||
$count = 3 - count($c->getSlots());
|
|
||||||
for ($i = 0; $i < $count; $i++) {
|
|
||||||
$c->addSlot('');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$count = 3 - count($form->getChoices());
|
|
||||||
for ($i = 0; $i < $count; $i++) {
|
|
||||||
$c = new Choice('');
|
|
||||||
$c->addSlot('');
|
|
||||||
$c->addSlot('');
|
|
||||||
$c->addSlot('');
|
|
||||||
$form->addChoice($c);
|
|
||||||
}
|
|
||||||
|
|
||||||
$_SESSION['form'] = serialize($form);
|
|
||||||
|
|
||||||
// Display step 2
|
|
||||||
$smarty->assign('title', __('Step 2 date', 'Poll dates (2 of 3)'));
|
|
||||||
$smarty->assign('choices', $form->getChoices());
|
|
||||||
$smarty->assign('error', null);
|
|
||||||
|
|
||||||
$smarty->display('create_date_poll_step_2.tpl');
|
|
||||||
exit;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
// Step 3/4 : Confirm poll creation
|
|
||||||
|
|
||||||
// Handle Step2 submission
|
|
||||||
if (!empty($_POST['days'])) {
|
|
||||||
// Remove empty dates
|
|
||||||
$_POST['days'] = array_filter($_POST['days'], function ($d) {
|
|
||||||
return !empty($d);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check if there are at most MAX_SLOTS_PER_POLL slots
|
|
||||||
if (count($_POST['days']) > MAX_SLOTS_PER_POLL) {
|
|
||||||
// Display step 2
|
|
||||||
$smarty->assign('title', __('Step 2 date', 'Poll dates (2 of 3)'));
|
|
||||||
$smarty->assign('choices', $form->getChoices());
|
|
||||||
$smarty->assign('error', __f('Error', 'You can\'t select more than %d dates', MAX_SLOTS_PER_POLL));
|
|
||||||
|
|
||||||
$smarty->display('create_date_poll_step_2.tpl');
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear previous choices
|
|
||||||
$form->clearChoices();
|
|
||||||
|
|
||||||
// Reorder moments to deal with suppressed dates
|
|
||||||
$moments = [];
|
|
||||||
$i = 0;
|
|
||||||
while(count($moments) < count($_POST['days'])) {
|
|
||||||
if (!empty($_POST['horaires' . $i])) {
|
|
||||||
$moments[] = $_POST['horaires' . $i];
|
|
||||||
}
|
|
||||||
$i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for ($i = 0; $i < count($_POST['days']); $i++) {
|
|
||||||
$day = $_POST['days'][$i];
|
|
||||||
|
|
||||||
if (!empty($day)) {
|
|
||||||
// Add choice to Form data
|
|
||||||
$date = DateTime::createFromFormat(__('Date', 'Y-m-d'), $_POST['days'][$i])->setTime(0, 0, 0);
|
|
||||||
$time = (string) $date->getTimestamp();
|
|
||||||
$choice = new Choice($time);
|
|
||||||
$form->addChoice($choice);
|
|
||||||
|
|
||||||
$schedules = $inputService->filterArray($moments[$i], FILTER_DEFAULT);
|
|
||||||
for ($j = 0; $j < count($schedules); $j++) {
|
|
||||||
if (!empty($schedules[$j])) {
|
|
||||||
$choice->addSlot(strip_tags($schedules[$j]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$form->sortChoices();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display step 3
|
|
||||||
$summary = '<ul>';
|
|
||||||
$choices = $form->getChoices();
|
|
||||||
foreach ($choices as $choice) {
|
|
||||||
/** @var Choice $choice */
|
|
||||||
$summary .= '<li>' . strftime($date_format['txt_full'], $choice->getName());
|
|
||||||
$first = true;
|
|
||||||
foreach ($choice->getSlots() as $slots) {
|
|
||||||
$summary .= $first ? ': ' : ', ';
|
|
||||||
$summary .= $slots;
|
|
||||||
$first = false;
|
|
||||||
}
|
|
||||||
$summary .= '</li>';
|
|
||||||
}
|
|
||||||
$summary .= '</ul>';
|
|
||||||
|
|
||||||
$end_date_str = utf8_encode(strftime($date_format['txt_date'], $max_expiry_time)); // textual date
|
|
||||||
|
|
||||||
$_SESSION['form'] = serialize($form);
|
|
||||||
|
|
||||||
$smarty->assign('title', __('Step 3', 'Removal date and confirmation (3 of 3)'));
|
|
||||||
$smarty->assign('summary', $summary);
|
|
||||||
$smarty->assign('end_date_str', $end_date_str);
|
|
||||||
$smarty->assign('default_poll_duration', $config['default_poll_duration']);
|
|
||||||
$smarty->assign('use_smtp', $config['use_smtp']);
|
|
||||||
|
|
||||||
$smarty->display('create_poll_step_3.tpl');
|
|
||||||
exit;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
// Step 4 : Data prepare before insert in DB
|
|
||||||
|
|
||||||
// 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_expiry_time) {
|
|
||||||
$form->end_date = $min_expiry_time;
|
|
||||||
} elseif ($max_expiry_time < $time) {
|
|
||||||
$form->end_date = $max_expiry_time;
|
|
||||||
} else {
|
|
||||||
$form->end_date = $time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($form->end_date)) {
|
|
||||||
// By default, expiration date is 6 months after last day
|
|
||||||
$form->end_date = $max_expiry_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert poll in database
|
|
||||||
$ids = $pollService->createPoll($form);
|
|
||||||
$poll_id = $ids[0];
|
|
||||||
$admin_poll_id = $ids[1];
|
|
||||||
|
|
||||||
// Send confirmation by mail if enabled
|
|
||||||
if ($config['use_smtp'] === true) {
|
|
||||||
$message = __('Mail', "This is the message to forward to the poll participants.");
|
|
||||||
$message .= '<br/><br/>';
|
|
||||||
$message .= Utils::htmlEscape($form->admin_name) . ' ' . __('Mail', 'has just created a poll called') . ' : "' . Utils::htmlEscape($form->title) . '".<br/>';
|
|
||||||
$message .= __('Mail', 'Thank you for participating in the poll at the following link') . ' :<br/><br/><a href="%1$s">%1$s</a>';
|
|
||||||
|
|
||||||
$message_admin = __('Mail', "This message should NOT be sent to the poll participants. You should keep it private. <br/><br/>You can modify your poll at the following link");
|
|
||||||
$message_admin .= ' :<br/><br/><a href="%1$s">%1$s</a>';
|
|
||||||
|
|
||||||
$message = sprintf($message, Utils::getUrlSondage($poll_id));
|
|
||||||
$message_admin = sprintf($message_admin, Utils::getUrlSondage($admin_poll_id, true));
|
|
||||||
|
|
||||||
if ($mailService->isValidEmail($form->admin_mail)) {
|
|
||||||
$mailService->send($form->admin_mail, '[' . NOMAPPLICATION . '][' . __('Mail', 'Message for the author') . '] ' . __('Generic', 'Poll') . ': ' . $form->title, $message_admin);
|
|
||||||
$mailService->send($form->admin_mail, '[' . NOMAPPLICATION . '][' . __('Mail', 'Participant link') . '] ' . __('Generic', 'Poll') . ': ' . $form->title, $message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean Form data in $_SESSION
|
|
||||||
unset($_SESSION['form']);
|
|
||||||
|
|
||||||
$purgeService->repeatedCleanings();
|
|
||||||
|
|
||||||
// creation message
|
|
||||||
$sessionService->set("Framadate", "messagePollCreated", TRUE);
|
|
||||||
|
|
||||||
// Redirect to poll administration
|
|
||||||
header('Location:' . Utils::getUrlSondage($admin_poll_id, true));
|
|
||||||
exit;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
default:
|
|
||||||
// Step 1/4 : error if $_SESSION from info_sondage are not valid
|
|
||||||
$smarty->assign('title', __('Error', 'Error!'));
|
|
||||||
$smarty->assign('error', __('Error', 'You haven\'t filled the first section of the poll creation, or your session has expired.'));
|
|
||||||
$smarty->display('error.tpl');
|
|
||||||
exit;
|
|
||||||
}
|
|
313
create_poll.php
313
create_poll.php
@ -1,313 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Rapha<EFBFBD>l DROZ
|
|
||||||
* Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft)
|
|
||||||
*
|
|
||||||
* =============================
|
|
||||||
*
|
|
||||||
* Ce logiciel est r<EFBFBD>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
|
|
||||||
*
|
|
||||||
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Rapha<EFBFBD>l DROZ
|
|
||||||
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
|
|
||||||
*/
|
|
||||||
|
|
||||||
use Framadate\Form;
|
|
||||||
use Framadate\Repositories\RepositoryFactory;
|
|
||||||
use Framadate\Security\PasswordHasher;
|
|
||||||
use Framadate\Services\InputService;
|
|
||||||
use Framadate\Utils;
|
|
||||||
|
|
||||||
include_once __DIR__ . '/app/inc/init.php';
|
|
||||||
|
|
||||||
const GO_TO_STEP_2 = 'gotostep2';
|
|
||||||
|
|
||||||
/* Services */
|
|
||||||
/*----------*/
|
|
||||||
|
|
||||||
$inputService = new InputService();
|
|
||||||
$pollRepository = RepositoryFactory::pollRepository();
|
|
||||||
|
|
||||||
/* PAGE */
|
|
||||||
/* ---- */
|
|
||||||
$form = isset($_SESSION['form']) ? unserialize($_SESSION['form']) : null;
|
|
||||||
|
|
||||||
if ($form === null || !($form instanceof Form)) {
|
|
||||||
$form = new Form();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type de sondage
|
|
||||||
if (isset($_GET['type']) && $_GET['type'] === 'date') {
|
|
||||||
$poll_type = 'date';
|
|
||||||
$form->choix_sondage = $poll_type;
|
|
||||||
} else {
|
|
||||||
$poll_type = 'classic';
|
|
||||||
$form->choix_sondage = $poll_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We clean the data
|
|
||||||
$goToStep2 = filter_input(INPUT_POST, GO_TO_STEP_2, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^(date|classic)$/']]);
|
|
||||||
if ($goToStep2) {
|
|
||||||
$title = $inputService->filterTitle($_POST['title']);
|
|
||||||
|
|
||||||
$use_ValueMax = isset($_POST['use_ValueMax']) ? $inputService->filterBoolean($_POST['use_ValueMax']) : false;
|
|
||||||
$ValueMax = $use_ValueMax === true ? $inputService->filterValueMax($_POST['ValueMax']) : null;
|
|
||||||
|
|
||||||
$use_customized_url = isset($_POST['use_customized_url']) ? $inputService->filterBoolean($_POST['use_customized_url']) : false;
|
|
||||||
$customized_url = $use_customized_url === true ? $inputService->filterId($_POST['customized_url']) : null;
|
|
||||||
$name = $inputService->filterName($_POST['name']);
|
|
||||||
$mail = $config['use_smtp'] === true ? $inputService->filterMail($_POST['mail']) : null;
|
|
||||||
$description = $inputService->filterDescription($_POST['description']);
|
|
||||||
$editable = $inputService->filterEditable($_POST['editable']);
|
|
||||||
$receiveNewVotes = isset($_POST['receiveNewVotes']) ? $inputService->filterBoolean($_POST['receiveNewVotes']) : false;
|
|
||||||
$receiveNewComments = isset($_POST['receiveNewComments']) ? $inputService->filterBoolean($_POST['receiveNewComments']) : false;
|
|
||||||
$hidden = isset($_POST['hidden']) ? $inputService->filterBoolean($_POST['hidden']) : false;
|
|
||||||
$use_password = filter_input(INPUT_POST, 'use_password', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_REGEX]]);
|
|
||||||
$collect_users_mail = $inputService->filterCollectMail($_POST['collect_users_mail']);
|
|
||||||
$use_password = filter_input(INPUT_POST, 'use_password', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_REGEX]]);
|
|
||||||
$password = isset($_POST['password']) ? $_POST['password'] : null;
|
|
||||||
$password_repeat = isset($_POST['password_repeat']) ? $_POST['password_repeat'] : null;
|
|
||||||
$results_publicly_visible = filter_input(INPUT_POST, 'results_publicly_visible', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BOOLEAN_REGEX]]);
|
|
||||||
|
|
||||||
// On initialise également les autres variables
|
|
||||||
$error_on_mail = false;
|
|
||||||
$error_on_title = false;
|
|
||||||
$error_on_name = false;
|
|
||||||
$error_on_description = false;
|
|
||||||
$error_on_password = false;
|
|
||||||
$error_on_password_repeat = false;
|
|
||||||
$error_on_customized_url = false;
|
|
||||||
$error_on_ValueMax = false;
|
|
||||||
|
|
||||||
$form->title = $title;
|
|
||||||
$form->id = $customized_url;
|
|
||||||
$form->use_customized_url = $use_customized_url;
|
|
||||||
$form->use_ValueMax = $use_ValueMax;
|
|
||||||
$form->ValueMax = $ValueMax;
|
|
||||||
$form->admin_name = $name;
|
|
||||||
$form->admin_mail = $mail;
|
|
||||||
$form->description = $description;
|
|
||||||
$form->editable = $editable;
|
|
||||||
$form->receiveNewVotes = $receiveNewVotes;
|
|
||||||
$form->receiveNewComments = $receiveNewComments;
|
|
||||||
$form->hidden = $hidden;
|
|
||||||
$form->collect_users_mail = $collect_users_mail;
|
|
||||||
$form->use_password = ($use_password !== null);
|
|
||||||
$form->results_publicly_visible = ($results_publicly_visible !== null);
|
|
||||||
|
|
||||||
if ($config['use_smtp'] === true && empty($mail)) {
|
|
||||||
$error_on_mail = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($title !== $_POST['title']) {
|
|
||||||
$error_on_title = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($use_customized_url) {
|
|
||||||
if ($customized_url === false) {
|
|
||||||
$error_on_customized_url = true;
|
|
||||||
} else if ($pollRepository->existsById($customized_url)) {
|
|
||||||
$error_on_customized_url = true;
|
|
||||||
$error_on_customized_url_msg = __('Error', 'Identifier is already used');
|
|
||||||
} else if (in_array($customized_url, ['admin', 'vote', 'action'], true)) {
|
|
||||||
$error_on_customized_url = true;
|
|
||||||
$error_on_customized_url_msg = __('Error', 'This identifier is not allowed');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($use_ValueMax && $ValueMax === false) {
|
|
||||||
$error_on_ValueMax = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($name !== $_POST['name']) {
|
|
||||||
$error_on_name = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($description === false) {
|
|
||||||
$error_on_description = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si pas d'erreur dans l'adresse alors on change de page vers date ou autre
|
|
||||||
if ($config['use_smtp'] === true) {
|
|
||||||
$email_OK = $mail && !$error_on_mail;
|
|
||||||
} else {
|
|
||||||
$email_OK = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($use_password) {
|
|
||||||
if (empty($password)) {
|
|
||||||
$error_on_password = true;
|
|
||||||
} else if ($password !== $password_repeat) {
|
|
||||||
$error_on_password_repeat = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($title && $name && $email_OK && !$error_on_title && !$error_on_customized_url && !$error_on_description && !$error_on_name
|
|
||||||
&& !$error_on_password && !$error_on_password_repeat &&!$error_on_ValueMax
|
|
||||||
) {
|
|
||||||
// If no errors, we hash the password if needed
|
|
||||||
if ($form->use_password) {
|
|
||||||
$form->password_hash = PasswordHasher::hash($password);
|
|
||||||
} else {
|
|
||||||
$form->password_hash = null;
|
|
||||||
$form->results_publicly_visible = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$_SESSION['form'] = serialize($form);
|
|
||||||
|
|
||||||
if ($goToStep2 === 'date') {
|
|
||||||
header('Location:create_date_poll.php');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($goToStep2 === 'classic') {
|
|
||||||
header('Location:create_classic_poll.php');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Title Erreur !
|
|
||||||
$title = __('Error', 'Error!') . ' - ' . __('Step 1', 'Poll creation (1 of 3)');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Title OK (formulaire pas encore rempli)
|
|
||||||
$title = __('Step 1', 'Poll creation (1 of 3)');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare error messages
|
|
||||||
$errors = [
|
|
||||||
'title' => [
|
|
||||||
'msg' => '',
|
|
||||||
'aria' => '',
|
|
||||||
'class' => ''
|
|
||||||
],
|
|
||||||
'customized_url' => [
|
|
||||||
'msg' => '',
|
|
||||||
'aria' => '',
|
|
||||||
'class' => ''
|
|
||||||
],
|
|
||||||
'description' => [
|
|
||||||
'msg' => '',
|
|
||||||
'aria' => '',
|
|
||||||
'class' => ''
|
|
||||||
],
|
|
||||||
'name' => [
|
|
||||||
'msg' => '',
|
|
||||||
'aria' => '',
|
|
||||||
'class' => ''
|
|
||||||
],
|
|
||||||
'email' => [
|
|
||||||
'msg' => '',
|
|
||||||
'aria' => '',
|
|
||||||
'class' => ''
|
|
||||||
],
|
|
||||||
'password' => [
|
|
||||||
'msg' => '',
|
|
||||||
'aria' => '',
|
|
||||||
'class' => ''
|
|
||||||
],
|
|
||||||
'ValueMax' => [
|
|
||||||
'msg' => '',
|
|
||||||
'aria' => '',
|
|
||||||
'class' => ''
|
|
||||||
],
|
|
||||||
'password_repeat' => [
|
|
||||||
'msg' => '',
|
|
||||||
'aria' => '',
|
|
||||||
'class' => ''
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
if (!empty($_POST[GO_TO_STEP_2])) {
|
|
||||||
if (empty($_POST['title'])) {
|
|
||||||
$errors['title']['aria'] = 'aria-describeby="poll_title_error" ';
|
|
||||||
$errors['title']['class'] = ' has-error';
|
|
||||||
$errors['title']['msg'] = __('Error', 'Enter a title');
|
|
||||||
} elseif ($error_on_title) {
|
|
||||||
$errors['title']['aria'] = 'aria-describeby="poll_title_error" ';
|
|
||||||
$errors['title']['class'] = ' has-error';
|
|
||||||
$errors['title']['msg'] = __('Error', 'Something is wrong with the format');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($error_on_customized_url) {
|
|
||||||
$errors['customized_url']['aria'] = 'aria-describeby="customized_url" ';
|
|
||||||
$errors['customized_url']['class'] = ' has-error';
|
|
||||||
$errors['customized_url']['msg'] = isset($error_on_customized_url_msg) ? $error_on_customized_url_msg : __('Error', "Something is wrong with the format: Customized URLs should only consist of alphanumeric characters and hyphens.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($error_on_description) {
|
|
||||||
$errors['description']['aria'] = 'aria-describeby="poll_comment_error" ';
|
|
||||||
$errors['description']['class'] = ' has-error';
|
|
||||||
$errors['description']['msg'] = __('Error', 'Something is wrong with the format');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($_POST['name'])) {
|
|
||||||
$errors['name']['aria'] = 'aria-describeby="poll_name_error" ';
|
|
||||||
$errors['name']['class'] = ' has-error';
|
|
||||||
$errors['name']['msg'] = __('Error', 'Enter a name');
|
|
||||||
} elseif ($error_on_name) {
|
|
||||||
$errors['name']['aria'] = 'aria-describeby="poll_name_error" ';
|
|
||||||
$errors['name']['class'] = ' has-error';
|
|
||||||
$errors['name']['msg'] = __('Error', "Something is wrong with the format: name shouldn't have any spaces before or after");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($_POST['mail'])) {
|
|
||||||
$errors['email']['aria'] = 'aria-describeby="poll_name_error" ';
|
|
||||||
$errors['email']['class'] = ' has-error';
|
|
||||||
$errors['email']['msg'] = __('Error', 'Enter an email address');
|
|
||||||
} elseif ($error_on_mail) {
|
|
||||||
$errors['email']['aria'] = 'aria-describeby="poll_email_error" ';
|
|
||||||
$errors['email']['class'] = ' has-error';
|
|
||||||
$errors['email']['msg'] = __('Error', '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.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($error_on_password) {
|
|
||||||
$errors['password']['aria'] = 'aria-describeby="poll_password_error" ';
|
|
||||||
$errors['password']['class'] = ' has-error';
|
|
||||||
$errors['password']['msg'] = __('Error', 'Password is empty.');
|
|
||||||
}
|
|
||||||
if ($error_on_password_repeat) {
|
|
||||||
$errors['password_repeat']['aria'] = 'aria-describeby="poll_password_repeat_error" ';
|
|
||||||
$errors['password_repeat']['class'] = ' has-error';
|
|
||||||
$errors['password_repeat']['msg'] = __('Error', 'Passwords do not match.');
|
|
||||||
}
|
|
||||||
if ($error_on_ValueMax) {
|
|
||||||
$errors['ValueMax']['aria'] = 'aria-describeby="poll_ValueMax" ';
|
|
||||||
$errors['ValueMax']['class'] = ' has-error';
|
|
||||||
$errors['ValueMax']['msg'] = __('Error', 'Error on amount of votes limitation: Value must be an integer greater than 0');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$useRemoteUser = USE_REMOTE_USER && isset($_SERVER['REMOTE_USER']);
|
|
||||||
|
|
||||||
$smarty->assign('title', $title);
|
|
||||||
$smarty->assign('useRemoteUser', $useRemoteUser);
|
|
||||||
$smarty->assign('errors', $errors);
|
|
||||||
$smarty->assign('advanced_errors', $goToStep2 && ($error_on_ValueMax || $error_on_customized_url || $error_on_password || $error_on_password_repeat));
|
|
||||||
$smarty->assign('use_smtp', $config['use_smtp']);
|
|
||||||
$smarty->assign('default_to_marldown_editor', $config['markdown_editor_by_default']);
|
|
||||||
$smarty->assign('goToStep2', GO_TO_STEP_2);
|
|
||||||
|
|
||||||
$smarty->assign('poll_type', $poll_type);
|
|
||||||
$smarty->assign('poll_title', Utils::fromPostOrDefault('title', $form->title));
|
|
||||||
$smarty->assign('customized_url', Utils::fromPostOrDefault('customized_url', $form->id));
|
|
||||||
$smarty->assign('use_customized_url', Utils::fromPostOrDefault('use_customized_url', $form->use_customized_url));
|
|
||||||
$smarty->assign('ValueMax', Utils::fromPostOrDefault('ValueMax', $form->ValueMax));
|
|
||||||
$smarty->assign('use_ValueMax', Utils::fromPostOrDefault('use_ValueMax', $form->use_ValueMax));
|
|
||||||
$smarty->assign('collect_users_mail', Utils::fromPostOrDefault('collect_users_mail', $form->collect_users_mail));
|
|
||||||
$smarty->assign('poll_description', !empty($_POST['description']) ? $_POST['description'] : $form->description);
|
|
||||||
$smarty->assign('poll_name', Utils::fromPostOrDefault('name', $form->admin_name));
|
|
||||||
$smarty->assign('poll_mail', Utils::fromPostOrDefault('mail', $form->admin_mail));
|
|
||||||
$smarty->assign('poll_editable', Utils::fromPostOrDefault('editable', $form->editable));
|
|
||||||
$smarty->assign('poll_receiveNewVotes', Utils::fromPostOrDefault('receiveNewVotes', $form->receiveNewVotes));
|
|
||||||
$smarty->assign('poll_receiveNewComments', Utils::fromPostOrDefault('receiveNewComments', $form->receiveNewComments));
|
|
||||||
$smarty->assign('poll_hidden', Utils::fromPostOrDefault('hidden', $form->hidden));
|
|
||||||
$smarty->assign('poll_use_password', Utils::fromPostOrDefault('use_password', $form->use_password));
|
|
||||||
$smarty->assign('poll_results_publicly_visible', Utils::fromPostOrDefault('results_publicly_visible', $form->results_publicly_visible));
|
|
||||||
$smarty->assign('form', $form);
|
|
||||||
|
|
||||||
$smarty->display('create_poll.tpl');
|
|
@ -1,25 +0,0 @@
|
|||||||
.form-horizontal .radio label {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.optionnal-parameters:hover, .optionnal-parameters:focus {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.optionnal-parameters:active, .optionnal-parameters:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.optionnal-parameters .caret, .optionnal-parameters.collapsed .caret.caret-up {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.optionnal-parameters .caret.caret-up, .optionnal-parameters.collapsed .caret {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.caret.caret-up {
|
|
||||||
border-bottom: 4px dashed;
|
|
||||||
border-top: 0 none;
|
|
||||||
content: "";
|
|
||||||
}
|
|
587
css/bootstrap-theme.css
vendored
587
css/bootstrap-theme.css
vendored
@ -1,587 +0,0 @@
|
|||||||
/*!
|
|
||||||
* Bootstrap v3.3.7 (http://getbootstrap.com)
|
|
||||||
* Copyright 2011-2016 Twitter, Inc.
|
|
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
|
||||||
*/
|
|
||||||
.btn-default,
|
|
||||||
.btn-primary,
|
|
||||||
.btn-success,
|
|
||||||
.btn-info,
|
|
||||||
.btn-warning,
|
|
||||||
.btn-danger {
|
|
||||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
|
|
||||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
|
|
||||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
|
|
||||||
}
|
|
||||||
.btn-default:active,
|
|
||||||
.btn-primary:active,
|
|
||||||
.btn-success:active,
|
|
||||||
.btn-info:active,
|
|
||||||
.btn-warning:active,
|
|
||||||
.btn-danger:active,
|
|
||||||
.btn-default.active,
|
|
||||||
.btn-primary.active,
|
|
||||||
.btn-success.active,
|
|
||||||
.btn-info.active,
|
|
||||||
.btn-warning.active,
|
|
||||||
.btn-danger.active {
|
|
||||||
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
|
|
||||||
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
|
|
||||||
}
|
|
||||||
.btn-default.disabled,
|
|
||||||
.btn-primary.disabled,
|
|
||||||
.btn-success.disabled,
|
|
||||||
.btn-info.disabled,
|
|
||||||
.btn-warning.disabled,
|
|
||||||
.btn-danger.disabled,
|
|
||||||
.btn-default[disabled],
|
|
||||||
.btn-primary[disabled],
|
|
||||||
.btn-success[disabled],
|
|
||||||
.btn-info[disabled],
|
|
||||||
.btn-warning[disabled],
|
|
||||||
.btn-danger[disabled],
|
|
||||||
fieldset[disabled] .btn-default,
|
|
||||||
fieldset[disabled] .btn-primary,
|
|
||||||
fieldset[disabled] .btn-success,
|
|
||||||
fieldset[disabled] .btn-info,
|
|
||||||
fieldset[disabled] .btn-warning,
|
|
||||||
fieldset[disabled] .btn-danger {
|
|
||||||
-webkit-box-shadow: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
.btn-default .badge,
|
|
||||||
.btn-primary .badge,
|
|
||||||
.btn-success .badge,
|
|
||||||
.btn-info .badge,
|
|
||||||
.btn-warning .badge,
|
|
||||||
.btn-danger .badge {
|
|
||||||
text-shadow: none;
|
|
||||||
}
|
|
||||||
.btn:active,
|
|
||||||
.btn.active {
|
|
||||||
background-image: none;
|
|
||||||
}
|
|
||||||
.btn-default {
|
|
||||||
text-shadow: 0 1px 0 #fff;
|
|
||||||
background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
|
|
||||||
background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
border-color: #dbdbdb;
|
|
||||||
border-color: #ccc;
|
|
||||||
}
|
|
||||||
.btn-default:hover,
|
|
||||||
.btn-default:focus {
|
|
||||||
background-color: #e0e0e0;
|
|
||||||
background-position: 0 -15px;
|
|
||||||
}
|
|
||||||
.btn-default:active,
|
|
||||||
.btn-default.active {
|
|
||||||
background-color: #e0e0e0;
|
|
||||||
border-color: #dbdbdb;
|
|
||||||
}
|
|
||||||
.btn-default.disabled,
|
|
||||||
.btn-default[disabled],
|
|
||||||
fieldset[disabled] .btn-default,
|
|
||||||
.btn-default.disabled:hover,
|
|
||||||
.btn-default[disabled]:hover,
|
|
||||||
fieldset[disabled] .btn-default:hover,
|
|
||||||
.btn-default.disabled:focus,
|
|
||||||
.btn-default[disabled]:focus,
|
|
||||||
fieldset[disabled] .btn-default:focus,
|
|
||||||
.btn-default.disabled.focus,
|
|
||||||
.btn-default[disabled].focus,
|
|
||||||
fieldset[disabled] .btn-default.focus,
|
|
||||||
.btn-default.disabled:active,
|
|
||||||
.btn-default[disabled]:active,
|
|
||||||
fieldset[disabled] .btn-default:active,
|
|
||||||
.btn-default.disabled.active,
|
|
||||||
.btn-default[disabled].active,
|
|
||||||
fieldset[disabled] .btn-default.active {
|
|
||||||
background-color: #e0e0e0;
|
|
||||||
background-image: none;
|
|
||||||
}
|
|
||||||
.btn-primary {
|
|
||||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
|
|
||||||
background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
border-color: #245580;
|
|
||||||
}
|
|
||||||
.btn-primary:hover,
|
|
||||||
.btn-primary:focus {
|
|
||||||
background-color: #265a88;
|
|
||||||
background-position: 0 -15px;
|
|
||||||
}
|
|
||||||
.btn-primary:active,
|
|
||||||
.btn-primary.active {
|
|
||||||
background-color: #265a88;
|
|
||||||
border-color: #245580;
|
|
||||||
}
|
|
||||||
.btn-primary.disabled,
|
|
||||||
.btn-primary[disabled],
|
|
||||||
fieldset[disabled] .btn-primary,
|
|
||||||
.btn-primary.disabled:hover,
|
|
||||||
.btn-primary[disabled]:hover,
|
|
||||||
fieldset[disabled] .btn-primary:hover,
|
|
||||||
.btn-primary.disabled:focus,
|
|
||||||
.btn-primary[disabled]:focus,
|
|
||||||
fieldset[disabled] .btn-primary:focus,
|
|
||||||
.btn-primary.disabled.focus,
|
|
||||||
.btn-primary[disabled].focus,
|
|
||||||
fieldset[disabled] .btn-primary.focus,
|
|
||||||
.btn-primary.disabled:active,
|
|
||||||
.btn-primary[disabled]:active,
|
|
||||||
fieldset[disabled] .btn-primary:active,
|
|
||||||
.btn-primary.disabled.active,
|
|
||||||
.btn-primary[disabled].active,
|
|
||||||
fieldset[disabled] .btn-primary.active {
|
|
||||||
background-color: #265a88;
|
|
||||||
background-image: none;
|
|
||||||
}
|
|
||||||
.btn-success {
|
|
||||||
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
|
|
||||||
background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
border-color: #3e8f3e;
|
|
||||||
}
|
|
||||||
.btn-success:hover,
|
|
||||||
.btn-success:focus {
|
|
||||||
background-color: #419641;
|
|
||||||
background-position: 0 -15px;
|
|
||||||
}
|
|
||||||
.btn-success:active,
|
|
||||||
.btn-success.active {
|
|
||||||
background-color: #419641;
|
|
||||||
border-color: #3e8f3e;
|
|
||||||
}
|
|
||||||
.btn-success.disabled,
|
|
||||||
.btn-success[disabled],
|
|
||||||
fieldset[disabled] .btn-success,
|
|
||||||
.btn-success.disabled:hover,
|
|
||||||
.btn-success[disabled]:hover,
|
|
||||||
fieldset[disabled] .btn-success:hover,
|
|
||||||
.btn-success.disabled:focus,
|
|
||||||
.btn-success[disabled]:focus,
|
|
||||||
fieldset[disabled] .btn-success:focus,
|
|
||||||
.btn-success.disabled.focus,
|
|
||||||
.btn-success[disabled].focus,
|
|
||||||
fieldset[disabled] .btn-success.focus,
|
|
||||||
.btn-success.disabled:active,
|
|
||||||
.btn-success[disabled]:active,
|
|
||||||
fieldset[disabled] .btn-success:active,
|
|
||||||
.btn-success.disabled.active,
|
|
||||||
.btn-success[disabled].active,
|
|
||||||
fieldset[disabled] .btn-success.active {
|
|
||||||
background-color: #419641;
|
|
||||||
background-image: none;
|
|
||||||
}
|
|
||||||
.btn-info {
|
|
||||||
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
|
|
||||||
background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
border-color: #28a4c9;
|
|
||||||
}
|
|
||||||
.btn-info:hover,
|
|
||||||
.btn-info:focus {
|
|
||||||
background-color: #2aabd2;
|
|
||||||
background-position: 0 -15px;
|
|
||||||
}
|
|
||||||
.btn-info:active,
|
|
||||||
.btn-info.active {
|
|
||||||
background-color: #2aabd2;
|
|
||||||
border-color: #28a4c9;
|
|
||||||
}
|
|
||||||
.btn-info.disabled,
|
|
||||||
.btn-info[disabled],
|
|
||||||
fieldset[disabled] .btn-info,
|
|
||||||
.btn-info.disabled:hover,
|
|
||||||
.btn-info[disabled]:hover,
|
|
||||||
fieldset[disabled] .btn-info:hover,
|
|
||||||
.btn-info.disabled:focus,
|
|
||||||
.btn-info[disabled]:focus,
|
|
||||||
fieldset[disabled] .btn-info:focus,
|
|
||||||
.btn-info.disabled.focus,
|
|
||||||
.btn-info[disabled].focus,
|
|
||||||
fieldset[disabled] .btn-info.focus,
|
|
||||||
.btn-info.disabled:active,
|
|
||||||
.btn-info[disabled]:active,
|
|
||||||
fieldset[disabled] .btn-info:active,
|
|
||||||
.btn-info.disabled.active,
|
|
||||||
.btn-info[disabled].active,
|
|
||||||
fieldset[disabled] .btn-info.active {
|
|
||||||
background-color: #2aabd2;
|
|
||||||
background-image: none;
|
|
||||||
}
|
|
||||||
.btn-warning {
|
|
||||||
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
|
|
||||||
background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
border-color: #e38d13;
|
|
||||||
}
|
|
||||||
.btn-warning:hover,
|
|
||||||
.btn-warning:focus {
|
|
||||||
background-color: #eb9316;
|
|
||||||
background-position: 0 -15px;
|
|
||||||
}
|
|
||||||
.btn-warning:active,
|
|
||||||
.btn-warning.active {
|
|
||||||
background-color: #eb9316;
|
|
||||||
border-color: #e38d13;
|
|
||||||
}
|
|
||||||
.btn-warning.disabled,
|
|
||||||
.btn-warning[disabled],
|
|
||||||
fieldset[disabled] .btn-warning,
|
|
||||||
.btn-warning.disabled:hover,
|
|
||||||
.btn-warning[disabled]:hover,
|
|
||||||
fieldset[disabled] .btn-warning:hover,
|
|
||||||
.btn-warning.disabled:focus,
|
|
||||||
.btn-warning[disabled]:focus,
|
|
||||||
fieldset[disabled] .btn-warning:focus,
|
|
||||||
.btn-warning.disabled.focus,
|
|
||||||
.btn-warning[disabled].focus,
|
|
||||||
fieldset[disabled] .btn-warning.focus,
|
|
||||||
.btn-warning.disabled:active,
|
|
||||||
.btn-warning[disabled]:active,
|
|
||||||
fieldset[disabled] .btn-warning:active,
|
|
||||||
.btn-warning.disabled.active,
|
|
||||||
.btn-warning[disabled].active,
|
|
||||||
fieldset[disabled] .btn-warning.active {
|
|
||||||
background-color: #eb9316;
|
|
||||||
background-image: none;
|
|
||||||
}
|
|
||||||
.btn-danger {
|
|
||||||
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
|
|
||||||
background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
border-color: #b92c28;
|
|
||||||
}
|
|
||||||
.btn-danger:hover,
|
|
||||||
.btn-danger:focus {
|
|
||||||
background-color: #c12e2a;
|
|
||||||
background-position: 0 -15px;
|
|
||||||
}
|
|
||||||
.btn-danger:active,
|
|
||||||
.btn-danger.active {
|
|
||||||
background-color: #c12e2a;
|
|
||||||
border-color: #b92c28;
|
|
||||||
}
|
|
||||||
.btn-danger.disabled,
|
|
||||||
.btn-danger[disabled],
|
|
||||||
fieldset[disabled] .btn-danger,
|
|
||||||
.btn-danger.disabled:hover,
|
|
||||||
.btn-danger[disabled]:hover,
|
|
||||||
fieldset[disabled] .btn-danger:hover,
|
|
||||||
.btn-danger.disabled:focus,
|
|
||||||
.btn-danger[disabled]:focus,
|
|
||||||
fieldset[disabled] .btn-danger:focus,
|
|
||||||
.btn-danger.disabled.focus,
|
|
||||||
.btn-danger[disabled].focus,
|
|
||||||
fieldset[disabled] .btn-danger.focus,
|
|
||||||
.btn-danger.disabled:active,
|
|
||||||
.btn-danger[disabled]:active,
|
|
||||||
fieldset[disabled] .btn-danger:active,
|
|
||||||
.btn-danger.disabled.active,
|
|
||||||
.btn-danger[disabled].active,
|
|
||||||
fieldset[disabled] .btn-danger.active {
|
|
||||||
background-color: #c12e2a;
|
|
||||||
background-image: none;
|
|
||||||
}
|
|
||||||
.thumbnail,
|
|
||||||
.img-thumbnail {
|
|
||||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
|
|
||||||
box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
|
|
||||||
}
|
|
||||||
.dropdown-menu > li > a:hover,
|
|
||||||
.dropdown-menu > li > a:focus {
|
|
||||||
background-color: #e8e8e8;
|
|
||||||
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
|
|
||||||
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
.dropdown-menu > .active > a,
|
|
||||||
.dropdown-menu > .active > a:hover,
|
|
||||||
.dropdown-menu > .active > a:focus {
|
|
||||||
background-color: #2e6da4;
|
|
||||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
|
|
||||||
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
.navbar-default {
|
|
||||||
background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
|
|
||||||
background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
border-radius: 4px;
|
|
||||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
|
|
||||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
|
|
||||||
}
|
|
||||||
.navbar-default .navbar-nav > .open > a,
|
|
||||||
.navbar-default .navbar-nav > .active > a {
|
|
||||||
background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
|
|
||||||
background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
|
|
||||||
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
|
|
||||||
}
|
|
||||||
.navbar-brand,
|
|
||||||
.navbar-nav > li > a {
|
|
||||||
text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
|
|
||||||
}
|
|
||||||
.navbar-inverse {
|
|
||||||
background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
|
|
||||||
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
.navbar-inverse .navbar-nav > .open > a,
|
|
||||||
.navbar-inverse .navbar-nav > .active > a {
|
|
||||||
background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
|
|
||||||
background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
|
|
||||||
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
|
|
||||||
}
|
|
||||||
.navbar-inverse .navbar-brand,
|
|
||||||
.navbar-inverse .navbar-nav > li > a {
|
|
||||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
|
|
||||||
}
|
|
||||||
.navbar-static-top,
|
|
||||||
.navbar-fixed-top,
|
|
||||||
.navbar-fixed-bottom {
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
@media (max-width: 767px) {
|
|
||||||
.navbar .navbar-nav .open .dropdown-menu > .active > a,
|
|
||||||
.navbar .navbar-nav .open .dropdown-menu > .active > a:hover,
|
|
||||||
.navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
|
|
||||||
color: #fff;
|
|
||||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
|
|
||||||
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.alert {
|
|
||||||
text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
|
|
||||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
|
|
||||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
|
|
||||||
}
|
|
||||||
.alert-success {
|
|
||||||
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
|
|
||||||
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
border-color: #b2dba1;
|
|
||||||
}
|
|
||||||
.alert-info {
|
|
||||||
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
|
|
||||||
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
border-color: #9acfea;
|
|
||||||
}
|
|
||||||
.alert-warning {
|
|
||||||
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
|
|
||||||
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
border-color: #f5e79e;
|
|
||||||
}
|
|
||||||
.alert-danger {
|
|
||||||
background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
|
|
||||||
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
border-color: #dca7a7;
|
|
||||||
}
|
|
||||||
.progress {
|
|
||||||
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
|
|
||||||
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
.progress-bar {
|
|
||||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
|
|
||||||
background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
.progress-bar-success {
|
|
||||||
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
|
|
||||||
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
.progress-bar-info {
|
|
||||||
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
|
|
||||||
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
.progress-bar-warning {
|
|
||||||
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
|
|
||||||
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
.progress-bar-danger {
|
|
||||||
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
|
|
||||||
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
.progress-bar-striped {
|
|
||||||
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
|
|
||||||
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
|
|
||||||
background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
|
|
||||||
}
|
|
||||||
.list-group {
|
|
||||||
border-radius: 4px;
|
|
||||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
|
|
||||||
box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
|
|
||||||
}
|
|
||||||
.list-group-item.active,
|
|
||||||
.list-group-item.active:hover,
|
|
||||||
.list-group-item.active:focus {
|
|
||||||
text-shadow: 0 -1px 0 #286090;
|
|
||||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
|
|
||||||
background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
border-color: #2b669a;
|
|
||||||
}
|
|
||||||
.list-group-item.active .badge,
|
|
||||||
.list-group-item.active:hover .badge,
|
|
||||||
.list-group-item.active:focus .badge {
|
|
||||||
text-shadow: none;
|
|
||||||
}
|
|
||||||
.panel {
|
|
||||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
|
|
||||||
box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
|
|
||||||
}
|
|
||||||
.panel-default > .panel-heading {
|
|
||||||
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
|
|
||||||
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
.panel-primary > .panel-heading {
|
|
||||||
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
|
|
||||||
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
.panel-success > .panel-heading {
|
|
||||||
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
|
|
||||||
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
.panel-info > .panel-heading {
|
|
||||||
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
|
|
||||||
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
.panel-warning > .panel-heading {
|
|
||||||
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
|
|
||||||
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
.panel-danger > .panel-heading {
|
|
||||||
background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
|
|
||||||
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
.well {
|
|
||||||
background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
|
|
||||||
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
border-color: #dcdcdc;
|
|
||||||
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
|
|
||||||
box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
|
|
||||||
}
|
|
||||||
/*# sourceMappingURL=bootstrap-theme.css.map */
|
|
File diff suppressed because one or more lines are too long
6
css/bootstrap-theme.min.css
vendored
6
css/bootstrap-theme.min.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
6757
css/bootstrap.css
vendored
6757
css/bootstrap.css
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
6
css/bootstrap.min.css
vendored
6
css/bootstrap.min.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,512 +0,0 @@
|
|||||||
/*!
|
|
||||||
* Datepicker for Bootstrap
|
|
||||||
*
|
|
||||||
* Copyright 2012 Stefan Petre
|
|
||||||
* Improvements by Andrew Rowls
|
|
||||||
* Licensed under the Apache License v2.0
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
.datepicker {
|
|
||||||
padding: 4px;
|
|
||||||
-webkit-border-radius: 4px;
|
|
||||||
-moz-border-radius: 4px;
|
|
||||||
border-radius: 4px;
|
|
||||||
direction: ltr;
|
|
||||||
/*.dow {
|
|
||||||
border-top: 1px solid #ddd !important;
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
.datepicker-inline {
|
|
||||||
width: 220px;
|
|
||||||
}
|
|
||||||
.datepicker.datepicker-rtl {
|
|
||||||
direction: rtl;
|
|
||||||
}
|
|
||||||
.datepicker.datepicker-rtl table tr td span {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
.datepicker-dropdown {
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
.datepicker-dropdown:before {
|
|
||||||
content: '';
|
|
||||||
display: inline-block;
|
|
||||||
border-left: 7px solid transparent;
|
|
||||||
border-right: 7px solid transparent;
|
|
||||||
border-bottom: 7px solid #ccc;
|
|
||||||
border-top: 0;
|
|
||||||
border-bottom-color: rgba(0, 0, 0, 0.2);
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
.datepicker-dropdown:after {
|
|
||||||
content: '';
|
|
||||||
display: inline-block;
|
|
||||||
border-left: 6px solid transparent;
|
|
||||||
border-right: 6px solid transparent;
|
|
||||||
border-bottom: 6px solid #ffffff;
|
|
||||||
border-top: 0;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
.datepicker-dropdown.datepicker-orient-left:before {
|
|
||||||
left: 6px;
|
|
||||||
}
|
|
||||||
.datepicker-dropdown.datepicker-orient-left:after {
|
|
||||||
left: 7px;
|
|
||||||
}
|
|
||||||
.datepicker-dropdown.datepicker-orient-right:before {
|
|
||||||
right: 6px;
|
|
||||||
}
|
|
||||||
.datepicker-dropdown.datepicker-orient-right:after {
|
|
||||||
right: 7px;
|
|
||||||
}
|
|
||||||
.datepicker-dropdown.datepicker-orient-top:before {
|
|
||||||
top: -7px;
|
|
||||||
}
|
|
||||||
.datepicker-dropdown.datepicker-orient-top:after {
|
|
||||||
top: -6px;
|
|
||||||
}
|
|
||||||
.datepicker-dropdown.datepicker-orient-bottom:before {
|
|
||||||
bottom: -7px;
|
|
||||||
border-bottom: 0;
|
|
||||||
border-top: 7px solid #999;
|
|
||||||
}
|
|
||||||
.datepicker-dropdown.datepicker-orient-bottom:after {
|
|
||||||
bottom: -6px;
|
|
||||||
border-bottom: 0;
|
|
||||||
border-top: 6px solid #ffffff;
|
|
||||||
}
|
|
||||||
.datepicker > div {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.datepicker.days div.datepicker-days {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.datepicker.months div.datepicker-months {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.datepicker.years div.datepicker-years {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.datepicker table {
|
|
||||||
margin: 0;
|
|
||||||
-webkit-touch-callout: none;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-khtml-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
.datepicker td,
|
|
||||||
.datepicker th {
|
|
||||||
text-align: center;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
-webkit-border-radius: 4px;
|
|
||||||
-moz-border-radius: 4px;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
.table-striped .datepicker table tr td,
|
|
||||||
.table-striped .datepicker table tr th {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
.datepicker table tr td.day:hover,
|
|
||||||
.datepicker table tr td.day.focused {
|
|
||||||
background: #eeeeee;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.datepicker table tr td.old,
|
|
||||||
.datepicker table tr td.new {
|
|
||||||
color: #999999;
|
|
||||||
}
|
|
||||||
.datepicker table tr td.disabled,
|
|
||||||
.datepicker table tr td.disabled:hover {
|
|
||||||
background: none;
|
|
||||||
color: #999999;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
.datepicker table tr td.today,
|
|
||||||
.datepicker table tr td.today:hover,
|
|
||||||
.datepicker table tr td.today.disabled,
|
|
||||||
.datepicker table tr td.today.disabled:hover {
|
|
||||||
background-color: #fde19a;
|
|
||||||
background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a);
|
|
||||||
background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a);
|
|
||||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));
|
|
||||||
background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a);
|
|
||||||
background-image: -o-linear-gradient(top, #fdd49a, #fdf59a);
|
|
||||||
background-image: linear-gradient(top, #fdd49a, #fdf59a);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);
|
|
||||||
border-color: #fdf59a #fdf59a #fbed50;
|
|
||||||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
.datepicker table tr td.today:hover,
|
|
||||||
.datepicker table tr td.today:hover:hover,
|
|
||||||
.datepicker table tr td.today.disabled:hover,
|
|
||||||
.datepicker table tr td.today.disabled:hover:hover,
|
|
||||||
.datepicker table tr td.today:active,
|
|
||||||
.datepicker table tr td.today:hover:active,
|
|
||||||
.datepicker table tr td.today.disabled:active,
|
|
||||||
.datepicker table tr td.today.disabled:hover:active,
|
|
||||||
.datepicker table tr td.today.active,
|
|
||||||
.datepicker table tr td.today:hover.active,
|
|
||||||
.datepicker table tr td.today.disabled.active,
|
|
||||||
.datepicker table tr td.today.disabled:hover.active,
|
|
||||||
.datepicker table tr td.today.disabled,
|
|
||||||
.datepicker table tr td.today:hover.disabled,
|
|
||||||
.datepicker table tr td.today.disabled.disabled,
|
|
||||||
.datepicker table tr td.today.disabled:hover.disabled,
|
|
||||||
.datepicker table tr td.today[disabled],
|
|
||||||
.datepicker table tr td.today:hover[disabled],
|
|
||||||
.datepicker table tr td.today.disabled[disabled],
|
|
||||||
.datepicker table tr td.today.disabled:hover[disabled] {
|
|
||||||
background-color: #fdf59a;
|
|
||||||
}
|
|
||||||
.datepicker table tr td.today:active,
|
|
||||||
.datepicker table tr td.today:hover:active,
|
|
||||||
.datepicker table tr td.today.disabled:active,
|
|
||||||
.datepicker table tr td.today.disabled:hover:active,
|
|
||||||
.datepicker table tr td.today.active,
|
|
||||||
.datepicker table tr td.today:hover.active,
|
|
||||||
.datepicker table tr td.today.disabled.active,
|
|
||||||
.datepicker table tr td.today.disabled:hover.active {
|
|
||||||
background-color: #fbf069 \9;
|
|
||||||
}
|
|
||||||
.datepicker table tr td.today:hover:hover {
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
.datepicker table tr td.today.active:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
.datepicker table tr td.range,
|
|
||||||
.datepicker table tr td.range:hover,
|
|
||||||
.datepicker table tr td.range.disabled,
|
|
||||||
.datepicker table tr td.range.disabled:hover {
|
|
||||||
background: #eeeeee;
|
|
||||||
-webkit-border-radius: 0;
|
|
||||||
-moz-border-radius: 0;
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
.datepicker table tr td.range.today,
|
|
||||||
.datepicker table tr td.range.today:hover,
|
|
||||||
.datepicker table tr td.range.today.disabled,
|
|
||||||
.datepicker table tr td.range.today.disabled:hover {
|
|
||||||
background-color: #f3d17a;
|
|
||||||
background-image: -moz-linear-gradient(top, #f3c17a, #f3e97a);
|
|
||||||
background-image: -ms-linear-gradient(top, #f3c17a, #f3e97a);
|
|
||||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));
|
|
||||||
background-image: -webkit-linear-gradient(top, #f3c17a, #f3e97a);
|
|
||||||
background-image: -o-linear-gradient(top, #f3c17a, #f3e97a);
|
|
||||||
background-image: linear-gradient(top, #f3c17a, #f3e97a);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);
|
|
||||||
border-color: #f3e97a #f3e97a #edde34;
|
|
||||||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
|
||||||
-webkit-border-radius: 0;
|
|
||||||
-moz-border-radius: 0;
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
.datepicker table tr td.range.today:hover,
|
|
||||||
.datepicker table tr td.range.today:hover:hover,
|
|
||||||
.datepicker table tr td.range.today.disabled:hover,
|
|
||||||
.datepicker table tr td.range.today.disabled:hover:hover,
|
|
||||||
.datepicker table tr td.range.today:active,
|
|
||||||
.datepicker table tr td.range.today:hover:active,
|
|
||||||
.datepicker table tr td.range.today.disabled:active,
|
|
||||||
.datepicker table tr td.range.today.disabled:hover:active,
|
|
||||||
.datepicker table tr td.range.today.active,
|
|
||||||
.datepicker table tr td.range.today:hover.active,
|
|
||||||
.datepicker table tr td.range.today.disabled.active,
|
|
||||||
.datepicker table tr td.range.today.disabled:hover.active,
|
|
||||||
.datepicker table tr td.range.today.disabled,
|
|
||||||
.datepicker table tr td.range.today:hover.disabled,
|
|
||||||
.datepicker table tr td.range.today.disabled.disabled,
|
|
||||||
.datepicker table tr td.range.today.disabled:hover.disabled,
|
|
||||||
.datepicker table tr td.range.today[disabled],
|
|
||||||
.datepicker table tr td.range.today:hover[disabled],
|
|
||||||
.datepicker table tr td.range.today.disabled[disabled],
|
|
||||||
.datepicker table tr td.range.today.disabled:hover[disabled] {
|
|
||||||
background-color: #f3e97a;
|
|
||||||
}
|
|
||||||
.datepicker table tr td.range.today:active,
|
|
||||||
.datepicker table tr td.range.today:hover:active,
|
|
||||||
.datepicker table tr td.range.today.disabled:active,
|
|
||||||
.datepicker table tr td.range.today.disabled:hover:active,
|
|
||||||
.datepicker table tr td.range.today.active,
|
|
||||||
.datepicker table tr td.range.today:hover.active,
|
|
||||||
.datepicker table tr td.range.today.disabled.active,
|
|
||||||
.datepicker table tr td.range.today.disabled:hover.active {
|
|
||||||
background-color: #efe24b \9;
|
|
||||||
}
|
|
||||||
.datepicker table tr td.selected,
|
|
||||||
.datepicker table tr td.selected:hover,
|
|
||||||
.datepicker table tr td.selected.disabled,
|
|
||||||
.datepicker table tr td.selected.disabled:hover {
|
|
||||||
background-color: #9e9e9e;
|
|
||||||
background-image: -moz-linear-gradient(top, #b3b3b3, #808080);
|
|
||||||
background-image: -ms-linear-gradient(top, #b3b3b3, #808080);
|
|
||||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080));
|
|
||||||
background-image: -webkit-linear-gradient(top, #b3b3b3, #808080);
|
|
||||||
background-image: -o-linear-gradient(top, #b3b3b3, #808080);
|
|
||||||
background-image: linear-gradient(top, #b3b3b3, #808080);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);
|
|
||||||
border-color: #808080 #808080 #595959;
|
|
||||||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
|
||||||
color: #fff;
|
|
||||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
|
||||||
}
|
|
||||||
.datepicker table tr td.selected:hover,
|
|
||||||
.datepicker table tr td.selected:hover:hover,
|
|
||||||
.datepicker table tr td.selected.disabled:hover,
|
|
||||||
.datepicker table tr td.selected.disabled:hover:hover,
|
|
||||||
.datepicker table tr td.selected:active,
|
|
||||||
.datepicker table tr td.selected:hover:active,
|
|
||||||
.datepicker table tr td.selected.disabled:active,
|
|
||||||
.datepicker table tr td.selected.disabled:hover:active,
|
|
||||||
.datepicker table tr td.selected.active,
|
|
||||||
.datepicker table tr td.selected:hover.active,
|
|
||||||
.datepicker table tr td.selected.disabled.active,
|
|
||||||
.datepicker table tr td.selected.disabled:hover.active,
|
|
||||||
.datepicker table tr td.selected.disabled,
|
|
||||||
.datepicker table tr td.selected:hover.disabled,
|
|
||||||
.datepicker table tr td.selected.disabled.disabled,
|
|
||||||
.datepicker table tr td.selected.disabled:hover.disabled,
|
|
||||||
.datepicker table tr td.selected[disabled],
|
|
||||||
.datepicker table tr td.selected:hover[disabled],
|
|
||||||
.datepicker table tr td.selected.disabled[disabled],
|
|
||||||
.datepicker table tr td.selected.disabled:hover[disabled] {
|
|
||||||
background-color: #808080;
|
|
||||||
}
|
|
||||||
.datepicker table tr td.selected:active,
|
|
||||||
.datepicker table tr td.selected:hover:active,
|
|
||||||
.datepicker table tr td.selected.disabled:active,
|
|
||||||
.datepicker table tr td.selected.disabled:hover:active,
|
|
||||||
.datepicker table tr td.selected.active,
|
|
||||||
.datepicker table tr td.selected:hover.active,
|
|
||||||
.datepicker table tr td.selected.disabled.active,
|
|
||||||
.datepicker table tr td.selected.disabled:hover.active {
|
|
||||||
background-color: #666666 \9;
|
|
||||||
}
|
|
||||||
.datepicker table tr td.active,
|
|
||||||
.datepicker table tr td.active:hover,
|
|
||||||
.datepicker table tr td.active.disabled,
|
|
||||||
.datepicker table tr td.active.disabled:hover {
|
|
||||||
background-color: #006dcc;
|
|
||||||
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
|
|
||||||
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
|
|
||||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
|
|
||||||
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
|
|
||||||
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
|
|
||||||
background-image: linear-gradient(top, #0088cc, #0044cc);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
|
|
||||||
border-color: #0044cc #0044cc #002a80;
|
|
||||||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
|
||||||
color: #fff;
|
|
||||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
|
||||||
}
|
|
||||||
.datepicker table tr td.active:hover,
|
|
||||||
.datepicker table tr td.active:hover:hover,
|
|
||||||
.datepicker table tr td.active.disabled:hover,
|
|
||||||
.datepicker table tr td.active.disabled:hover:hover,
|
|
||||||
.datepicker table tr td.active:active,
|
|
||||||
.datepicker table tr td.active:hover:active,
|
|
||||||
.datepicker table tr td.active.disabled:active,
|
|
||||||
.datepicker table tr td.active.disabled:hover:active,
|
|
||||||
.datepicker table tr td.active.active,
|
|
||||||
.datepicker table tr td.active:hover.active,
|
|
||||||
.datepicker table tr td.active.disabled.active,
|
|
||||||
.datepicker table tr td.active.disabled:hover.active,
|
|
||||||
.datepicker table tr td.active.disabled,
|
|
||||||
.datepicker table tr td.active:hover.disabled,
|
|
||||||
.datepicker table tr td.active.disabled.disabled,
|
|
||||||
.datepicker table tr td.active.disabled:hover.disabled,
|
|
||||||
.datepicker table tr td.active[disabled],
|
|
||||||
.datepicker table tr td.active:hover[disabled],
|
|
||||||
.datepicker table tr td.active.disabled[disabled],
|
|
||||||
.datepicker table tr td.active.disabled:hover[disabled] {
|
|
||||||
background-color: #0044cc;
|
|
||||||
}
|
|
||||||
.datepicker table tr td.active:active,
|
|
||||||
.datepicker table tr td.active:hover:active,
|
|
||||||
.datepicker table tr td.active.disabled:active,
|
|
||||||
.datepicker table tr td.active.disabled:hover:active,
|
|
||||||
.datepicker table tr td.active.active,
|
|
||||||
.datepicker table tr td.active:hover.active,
|
|
||||||
.datepicker table tr td.active.disabled.active,
|
|
||||||
.datepicker table tr td.active.disabled:hover.active {
|
|
||||||
background-color: #003399 \9;
|
|
||||||
}
|
|
||||||
.datepicker table tr td span {
|
|
||||||
display: block;
|
|
||||||
width: 23%;
|
|
||||||
height: 54px;
|
|
||||||
line-height: 54px;
|
|
||||||
float: left;
|
|
||||||
margin: 1%;
|
|
||||||
cursor: pointer;
|
|
||||||
-webkit-border-radius: 4px;
|
|
||||||
-moz-border-radius: 4px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
.datepicker table tr td span:hover {
|
|
||||||
background: #eeeeee;
|
|
||||||
}
|
|
||||||
.datepicker table tr td span.disabled,
|
|
||||||
.datepicker table tr td span.disabled:hover {
|
|
||||||
background: none;
|
|
||||||
color: #999999;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
.datepicker table tr td span.active,
|
|
||||||
.datepicker table tr td span.active:hover,
|
|
||||||
.datepicker table tr td span.active.disabled,
|
|
||||||
.datepicker table tr td span.active.disabled:hover {
|
|
||||||
background-color: #006dcc;
|
|
||||||
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
|
|
||||||
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
|
|
||||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
|
|
||||||
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
|
|
||||||
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
|
|
||||||
background-image: linear-gradient(top, #0088cc, #0044cc);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
|
|
||||||
border-color: #0044cc #0044cc #002a80;
|
|
||||||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
|
||||||
color: #fff;
|
|
||||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
|
||||||
}
|
|
||||||
.datepicker table tr td span.active:hover,
|
|
||||||
.datepicker table tr td span.active:hover:hover,
|
|
||||||
.datepicker table tr td span.active.disabled:hover,
|
|
||||||
.datepicker table tr td span.active.disabled:hover:hover,
|
|
||||||
.datepicker table tr td span.active:active,
|
|
||||||
.datepicker table tr td span.active:hover:active,
|
|
||||||
.datepicker table tr td span.active.disabled:active,
|
|
||||||
.datepicker table tr td span.active.disabled:hover:active,
|
|
||||||
.datepicker table tr td span.active.active,
|
|
||||||
.datepicker table tr td span.active:hover.active,
|
|
||||||
.datepicker table tr td span.active.disabled.active,
|
|
||||||
.datepicker table tr td span.active.disabled:hover.active,
|
|
||||||
.datepicker table tr td span.active.disabled,
|
|
||||||
.datepicker table tr td span.active:hover.disabled,
|
|
||||||
.datepicker table tr td span.active.disabled.disabled,
|
|
||||||
.datepicker table tr td span.active.disabled:hover.disabled,
|
|
||||||
.datepicker table tr td span.active[disabled],
|
|
||||||
.datepicker table tr td span.active:hover[disabled],
|
|
||||||
.datepicker table tr td span.active.disabled[disabled],
|
|
||||||
.datepicker table tr td span.active.disabled:hover[disabled] {
|
|
||||||
background-color: #0044cc;
|
|
||||||
}
|
|
||||||
.datepicker table tr td span.active:active,
|
|
||||||
.datepicker table tr td span.active:hover:active,
|
|
||||||
.datepicker table tr td span.active.disabled:active,
|
|
||||||
.datepicker table tr td span.active.disabled:hover:active,
|
|
||||||
.datepicker table tr td span.active.active,
|
|
||||||
.datepicker table tr td span.active:hover.active,
|
|
||||||
.datepicker table tr td span.active.disabled.active,
|
|
||||||
.datepicker table tr td span.active.disabled:hover.active {
|
|
||||||
background-color: #003399 \9;
|
|
||||||
}
|
|
||||||
.datepicker table tr td span.old,
|
|
||||||
.datepicker table tr td span.new {
|
|
||||||
color: #999999;
|
|
||||||
}
|
|
||||||
.datepicker th.datepicker-switch {
|
|
||||||
width: 145px;
|
|
||||||
}
|
|
||||||
.datepicker thead tr:first-child th,
|
|
||||||
.datepicker tfoot tr th {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.datepicker thead tr:first-child th:hover,
|
|
||||||
.datepicker tfoot tr th:hover {
|
|
||||||
background: #eeeeee;
|
|
||||||
}
|
|
||||||
.datepicker .cw {
|
|
||||||
font-size: 10px;
|
|
||||||
width: 12px;
|
|
||||||
padding: 0 2px 0 5px;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
.datepicker thead tr:first-child th.cw {
|
|
||||||
cursor: default;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
.input-append.date .add-on i,
|
|
||||||
.input-prepend.date .add-on i {
|
|
||||||
cursor: pointer;
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
}
|
|
||||||
.input-daterange input {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.input-daterange input:first-child {
|
|
||||||
-webkit-border-radius: 3px 0 0 3px;
|
|
||||||
-moz-border-radius: 3px 0 0 3px;
|
|
||||||
border-radius: 3px 0 0 3px;
|
|
||||||
}
|
|
||||||
.input-daterange input:last-child {
|
|
||||||
-webkit-border-radius: 0 3px 3px 0;
|
|
||||||
-moz-border-radius: 0 3px 3px 0;
|
|
||||||
border-radius: 0 3px 3px 0;
|
|
||||||
}
|
|
||||||
.input-daterange .add-on {
|
|
||||||
display: inline-block;
|
|
||||||
width: auto;
|
|
||||||
min-width: 16px;
|
|
||||||
height: 20px;
|
|
||||||
padding: 4px 5px;
|
|
||||||
font-weight: normal;
|
|
||||||
line-height: 20px;
|
|
||||||
text-align: center;
|
|
||||||
text-shadow: 0 1px 0 #ffffff;
|
|
||||||
vertical-align: middle;
|
|
||||||
background-color: #eeeeee;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
margin-left: -5px;
|
|
||||||
margin-right: -5px;
|
|
||||||
}
|
|
||||||
.datepicker.dropdown-menu {
|
|
||||||
position: absolute;
|
|
||||||
top: 100%;
|
|
||||||
left: 0;
|
|
||||||
z-index: 1000;
|
|
||||||
float: left;
|
|
||||||
display: none;
|
|
||||||
min-width: 160px;
|
|
||||||
list-style: none;
|
|
||||||
background-color: #ffffff;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
|
||||||
-webkit-border-radius: 5px;
|
|
||||||
-moz-border-radius: 5px;
|
|
||||||
border-radius: 5px;
|
|
||||||
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
|
||||||
-moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
|
||||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
|
||||||
-webkit-background-clip: padding-box;
|
|
||||||
-moz-background-clip: padding;
|
|
||||||
background-clip: padding-box;
|
|
||||||
*border-right-width: 2px;
|
|
||||||
*border-bottom-width: 2px;
|
|
||||||
color: #333333;
|
|
||||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
||||||
font-size: 13px;
|
|
||||||
line-height: 20px;
|
|
||||||
}
|
|
||||||
.datepicker.dropdown-menu th,
|
|
||||||
.datepicker.dropdown-menu td {
|
|
||||||
padding: 4px 5px;
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user