Subversion Repositories eFlore/Applications.del

Compare Revisions

No changes between revisions

Ignore whitespace Rev 1534 → Rev 1535

/tags/v1.1-helium/build.properties
New file
0,0 → 1,3
projectName = org.tela_botanica.del.Del
# pour la compilation "rapide" (ant quick)
projectTestName = org.tela_botanica.del.Del-test
/tags/v1.1-helium/readme.txt
New file
0,0 → 1,95
Configuration du poste de developpement pas à pas
 
##################################################
############# INSTALLATION ECLIPSE ###############
##################################################
Installer Eclipse Helios (3.6)
Installer le plugin GWT 2.4 pour eclipse sur http://dl.google.com/eclipse/plugin/3.6
Telecharger GWT 2.4 sur le poste local à partir de http://google-web-toolkit.googlecode.com/files/gwt-2.4.0.zip et installer dans un repertoire que nous appellerons GWT_HOME dans ce document
 
##########################################################
################### RECUPERATION DU PROJET ###############
##########################################################
Recuperer le projet avec un client svn sur http://svn.tela-botanica.net/svn/eflore/applications/del
Normalement la propriété svn:ignore devrait exister sur :
- le fichier .classpath à la racine du projet
- le reperoire war/WEB-INF
 
###############################################################
#################### CONFIGURATION D'ECLIPSE ##################
###############################################################
Régler l'encodage à UTF-8
Dans eclipse File>Import>General>Existing Project Into Workspace puis choisir l'emplacement du répertoire del
Clicker sur "OK"
 
Click droit sur le projet del => Properties
Aller ds Google>Web Toolkit et cocher "Use Google Web Toolkit" avec le SDK 2.4
Click droit sur le projet del => Properties
Clicker sur "OK"
 
Aller ds Java Build Path => Onglet "Source"
Dans "source folders in build path" choisir "del/src" et accepter lorqu'il propose d'effacer les autres fichiers sources
Dans default output folder entrer "del/war/WEB-INF/classes/"
Clicker sur "OK"
 
Click droit sur le projet del => Properties
Aller ds Java Build Path => Onglet "Librairies"
Clicker sur "Add library"
Choisir "JRE System Library" puis bouton "Next" et cocher Workspace default JRE(jre6)
Choisir "JUnit 4"
Cliquez sur "Add jars" et ajouter successivement :
- "del> lib > cobogw-1.3.1.jar"
- "del> lib > mockito-all-1.8.5.jar"
 
Clicker sur "OK"
 
Puis Project>Clean et les erreurs doivent disparaitre.
 
######################################################################
################ CONFIGURATION DES SOURCES ###########################
######################################################################
Dans src>org.tela_botanica.del.client.i18n :
- clic droit sur Vocabulary.properties et choisir "properties'. Puis dans Ressources mettre l'encodage à UTF-8
- clic droit sur Messages.properties et choisir 'properties'. Puis dans Ressources mettre l'encodage à UTF-8
 
######################################################################
################ CONFIGURATION DE JREST ##############################
######################################################################
Dans jrest, copiez le fichier jrest.ini.defaut.php et renomez le : jrest.ini.php
En fonction, de l'emplacement du dossier jrest sur votre serveur web modifié les paramètres :
- baseURL
- baseURLAbsolu
- delUrlAbsolu
 
######################################################################
################ CONFIGURATION DE DEL ##############################
######################################################################
Dans war > config, copier le fichier config.defaut.js et renomez le config.js.
En fonction, de l'emplacement du dossier jrest et del sur votre serveur web, modifier les paramètres :
- serviceBaseUrl
- delUrl
######################################################################
################ CONFIGURATION DU SCRIPT ANT DE DEPLOIEMENT ##########
######################################################################
Creer un fichier local.properties à la racine du projet et reseignez les valeurs suivantes:
server-url=xxxxxxxxxxxx
server-login=xxxxxxxxxxxxxx
server-password=xxxxxxxxxxxx
server-dir=xxxxxxxxxxxxxx
gwt-path=xxxxxxxxxxxxxxxx
Mettre ce fichier en svn:ignore (attention tt commit rendra les codes du serveur accessibles sur internet!)
 
######################################################################
################# CONFIGURATION DE ANT POUR ECLIPSE ##################
######################################################################
Télécharger le dernier binaire (jar) de commons.net sur http://commons.apache.org/net/download_net.cgi
Dans Eclipse Window>Preferences>Ant>Runtime>Ant Home Entries puis cliquer sur "Add jar" et ajoutez le jat que vous venez de selectionner et cliquez sur "OK"
Puis Window>Show view>Ant et sur la dorite de votre IDE un onglet Ant apparait
Drag'n'droppez le fichier build.xml situe a la racine du projet vers cet onglet
Sous del deux taches apparaissent, a executer en faisant un clic droit sur la tache puis "run as">"ant build"
La tache "build and deploy test" compile le projet et le déploie sur le serveur de test
 
Bon développement!
 
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/tags/v1.1-helium/local.defaut.properties
New file
0,0 → 1,3
gwt-path=/home/benjamin/opt/gwt-2.4.0/
local-deploy-path=C:\\Program Files\\EasyPHP5.2.10\\www\\del
webservices-root-url=http://localhost/del/jrest
/tags/v1.1-helium/build.xml
New file
0,0 → 1,210
<project name="del" xmlns:artifact="urn:maven-artifact-ant" basedir=".">
 
<property file="build.properties"/>
 
<path id="gwt">
<fileset includes="*.jar" dir="${user.home}/src/gwt/gwt/build/lib"/>
<fileset includes="cobogw-1.3.2.jar" dir="${user.home}/src/gwt"/>
<pathelement location="src" />
</path>
 
<target name="quick">
<java classname="com.google.gwt.dev.Compiler" fork="true">
<arg line="-style DETAILED -draftCompile ${projectTestName}" />
<classpath refid="gwt"/>
</java>
</target>
 
<target name="compile">
<!-- <java classname="com.google.gwt.dev.GWTCompiler" fork="true"> -->
<java classname="com.google.gwt.dev.Compiler" fork="true">
<arg line="-localWorkers 4 -style DETAILED ${projectName}"/>
<!-- <arg line="-out build/gwtOutput"/> -->
<classpath refid="gwt"/>
</java>
</target>
 
 
<target name="init-local-properties">
<property file="local.properties" />
<property name="gwt-path" value="${gwt-path}" />
<property name="webservices-root-url" value="${webservices-root-url}" />
</target>
 
<target name="init-server-properties">
<property file="server.properties" />
<property name="server-url" value="${server-url}" />
<property name="server-login" value="${server-login}" />
<property name="server-password" value="${server-password}" />
<property name="server-dir" value="${server-dir}" />
<property name="webservices-root-url" value="${webservices-root-url}" />
</target>
 
<target name="gwt-compile" depends="init-local-properties">
<java classname="com.google.gwt.dev.Compiler" fork="true">
<arg line="-logLevel INFO" />
<arg line="-style OBF" />
<arg value="org.tela_botanica.del.Del" />
<classpath>
<path>
<pathelement location="${gwt-path}/gwt-user.jar" />
<pathelement location="${gwt-path}/gwt-dev.jar" />
<pathelement location="${gwt-path}/validation-api-1.0.0.GA-sources.jar" />
<pathelement location="${gwt-path}/validation-api-1.0.0.GA.jar" />
<pathelement location="src" />
<pathelement location="war/WEB-INF/classes" />
<fileset dir="lib">
<include name="**/*.jar" />
</fileset>
</path>
</classpath>
</java>
</target>
 
<target name="generate-vocabulary" depends="init-local-properties">
<java classname="com.google.gwt.i18n.tools.I18NSync" fork="true">
<arg value="org.tela_botanica.del.client.i18n.Vocabulary" />
<classpath>
<path>
<pathelement location="${gwt-path}/gwt-user.jar" />
<pathelement location="${gwt-path}/gwt-dev.jar" />
<pathelement location="src" />
</path>
</classpath>
</java>
</target>
 
<target name="build-and-deploy-test-server">
<antcall target="gwt-compile" />
<antcall target="remove-server-files" />
<antcall target="copy-javascript-files-to-server" />
<antcall target="copy-img-files-to-server" />
<antcall target="copy-php-files-to-server" />
<antcall target="copy-config-files-to-server" />
</target>
 
<target name="remove-server-files" depends="init-server-properties">
 
<!-- Avant de redeployer supprime sur le serveur tous les fichiers et repertoires sauf ceux configures pour apache-->
<ftp action="del" server="${server-url}" remotedir="${server-dir}/" userid="${server-login}" password="${server-password}">
<fileset>
<include name="**/*" />
<exclude name="services/framework.php" />
<exclude name="services/configurations/*" />
</fileset>
</ftp>
</target>
 
<target name="copy-javascript-files-to-server" depends="init-server-properties">
<ftp server="${server-url}" remotedir="${server-dir}/" userid="${server-login}" password="${server-password}">
<fileset dir="war">
<exclude name="config/*" />
<exclude name="org.tela_botanica.del.Del.JUnit/*" />
<exclude name="WEB-INF/**" />
<exclude name="img/*" />
</fileset>
</ftp>
</target>
 
<target name="copy-img-files-to-server" depends="init-server-properties">
<ftp server="${server-url}" remotedir="${server-dir}/img" userid="${server-login}" password="${server-password}">
<fileset dir="war/img">
</fileset>
</ftp>
</target>
 
<target name="copy-php-files-to-server" depends="init-server-properties">
<ftp server="${server-url}" remotedir="${server-dir}/services" userid="${server-login}" password="${server-password}">
<fileset dir="services" excludes="*.svn">
<include name="**/*" />
<exclude name="configurations/*" />
<exclude name="framework.php" />
</fileset>
</ftp>
</target>
 
<target name="copy-config-files-to-server" depends="init-server-properties">
<filter token="webservices-root-url" value="${webservices-root-url}" />
<delete failonerror="false">
<fileset dir="target">
</fileset>
</delete>
 
<copy file="war/config/config.defaut.js" tofile="target/config/config.js" filtering="true" />
<copy file="war/config/apropos.defaut.js" tofile="target/config/apropos.js" filtering="true" />
 
<ftp server="${server-url}" remotedir="${server-dir}/config" userid="${server-login}" password="${server-password}">
<fileset dir="target/config" excludes="*.svn" />
</ftp>
</target>
 
 
 
<target name="build-and-deploy-local">
<antcall target="gwt-compile" />
<antcall target="deploy-local" />
</target>
 
<target name="deploy-local" depends="init-local-properties">
<delete dir="${local-deploy-path}" />
 
<copy todir="${local-deploy-path}">
<fileset dir="war" excludes="*.svn">
</fileset>
</copy>
 
<antcall target="filter-local-config-files">
</antcall>
<copy todir="${local-deploy-path}/config" filtering="true">
<fileset dir="war/config" excludes="*.svn" />
</copy>
</target>
 
<target name="filter-local-config-files" depends="init-local-properties">
<filter token="webservices-root-url" value="${webservices-root-url}" />
<copy flatten="true" file="war/config/config.defaut.js" tofile="war/config/config.js" filtering="true" />
<copy flatten="true" file="war/config/apropos.defaut.js" tofile="war/config/apropos.js" filtering="true" />
</target>
 
<target name="hosted-mode" depends="init-local-properties">
<java classname="com.google.gwt.dev.DevMode" fork="true">
<arg line="-noserver -port 80 -war '${local-deploy-path}/del' -startupUrl del/del.html -logLevel INFO -codeServerPort 9997 org.tela_botanica.del.Del" />
<classpath>
<path>
<pathelement location="${gwt-path}/gwt-user.jar" />
<pathelement location="${gwt-path}/gwt-dev.jar" />
<pathelement location="${gwt-path}/validation-api-1.0.0.GA-sources.jar" />
<pathelement location="${gwt-path}/validation-api-1.0.0.GA.jar" />
<pathelement location="src" />
<fileset dir="lib">
<include name="**/*.jar" />
</fileset>
</path>
</classpath>
 
</java>
</target>
 
<!-- In order to execute task you must execute a remote java application in your debug configuration on default port 8000-->
<target name="debug-mode" depends="init-local-properties">
<java classname="com.google.gwt.dev.DevMode" fork="true">
<jvmarg value="-Xdebug" />
<jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000" />
<arg line="-noserver -port 80 -war '${local-deploy-path}/del' -startupUrl del/del.html -logLevel INFO -codeServerPort 9997 org.tela_botanica.del.Del" />
<classpath>
<path>
<pathelement location="${gwt-path}/gwt-user.jar" />
<pathelement location="${gwt-path}/gwt-dev.jar" />
<pathelement location="${gwt-path}/validation-api-1.0.0.GA-sources.jar" />
<pathelement location="${gwt-path}/validation-api-1.0.0.GA.jar" />
<pathelement location="src" />
<fileset dir="lib">
<include name="**/*.jar" />
</fileset>
</path>
</classpath>
 
</java>
</target>
 
</project>
/tags/v1.1-helium/services/modules/0.1/determinations/ListeImagesDeterminationsProbables.php
New file
0,0 → 1,312
<?php
/**
* Le web service image récupère toutes les données de la table del_obs_images
* pour retourner une liste d'images associée à la détermination la plus probable
* avec la possibilité de ne renvoyer que les images les mieux notées pour un protocole donné
*
* @category php 5.2
* @package del
* @subpackage images
* @author Raphaël Droz <raphael@tela-botanica.org>
* @author Aurélien Peronnet <aurelien@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images
*/
 
class ListeImagesDeterminationsProbables {
private $indexImagesIds = array();
private $conteneur;
private $navigation;
private $masque;
private $gestionBdd;
private $bdd;
private $parametres = array();
private $ressources = array();
private $tri = 'date_transmission';
private $directionTri = 'desc';
private $protocole_defaut = null;
private $valeur_vote_min_defaut = null;
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_determinations.ini');
$this->navigation = $conteneur->getNavigation();
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
/**
* Méthode principale de la classe.
* Lance la récupération des images dans la base et les place dans un objet ResultatService
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function consulter($ressources, $parametres) {
// initialiserRessourcesEtParametres()
$this->ressources = $ressources;
$this->parametres = $parametres;
if(!isset($parametres['masque.protocole'])) {
$this->parametres['masque.protocole'] = $this->protocole_defaut;
}
if(!isset($parametres['masque.valeur_vote_min'])) {
$this->parametres['masque.valeur_vote_min'] = $this->valeur_vote_min_defaut;
}
// Gestion des configuration du script
// configurer();
$this->mappingFiltre = $this->conteneur->getParametre('mapping_masque');
$this->mappingObservation = $this->conteneur->getParametre('mapping_observation');
$this->mappingVotes = $this->conteneur->getParametre('mapping_votes');
// verifierConfiguration()
if(! $this->conteneur->getParametre('protocoles_possibles')) {
throw new Exception("Erreur lors de la configuration : \n- le fichier de configuration ne contient pas le parametre protocoles_possibles ou celui-ci est vide ;", RestServeur::HTTP_CODE_ERREUR);
}
 
$this->verifierParametres();
// initialiserTri()
$this->tri = isset($this->parametres['tri']) ? $this->parametres['tri'] : $this->tri;
$this->directionTri = isset($this->parametres['ordre']) ? $this->parametres['ordre'] : $this->directionTri;
 
// Lancement du service
$liaisons = $this->chargerLiaisons();
$images = array();
$total = 0;
 
if($liaisons) {
$compte = $this->bdd->recuperer('SELECT FOUND_ROWS() AS nbre');
$total = (int) $compte['nbre'];
 
$images = $this->chargerImage($liaisons);
$images = $this->chargerPropositionPlusProbable($images);
}
$this->navigation->setTotal($total);
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
$resultat->corps = array('entete' => $this->conteneur->getEntete(), 'resultats' => $images);
return $resultat;
}
private function verifierParametres() {
$erreurs = array();
$tableau_protocoles = explode(',',$this->conteneur->getParametre('protocoles_possibles'));
 
if(isset($this->parametres['masque.protocole']) &&
(!is_numeric($this->parametres['masque.protocole']) ||
!in_array($this->parametres['masque.protocole'], $tableau_protocoles)
)) {
$erreurs[] = '- la valeur pour le protocole doit être un entier compris dans les numéros de protocole existants '.$this->conteneur->getParametre('protocoles_possibles');
}
if(isset($this->parametres['masque.valeur_min_vote']) &&
(!is_numeric($this->parametres['masque.valeur_min_vote']) ||
$this->parametres['masque.valeur_min_vote'] < 0 ||
$this->parametres['masque.valeur_min_vote'] > 5
)) {
$erreurs[] = '- la valeur minimum de valeur des votes doit être un entier compris entre 0 et 5 ';
}
if (!empty($erreurs)) {
throw new Exception("Erreur lors de l\'analyse des parametres du service : \n" . implode("\n", $erreurs), RestServeur::HTTP_CODE_ERREUR);
}
}
/*-------------------------------------------------------------------------------
CHARGEMENT DES IMAGES
--------------------------------------------------------------------------------*/
private function chargerLiaisons() {
$champs = array('di.id_observation as id_observation', 'nom_referentiel', 'nom_ret', 'nom_ret_nn', 'nt', 'famille', 'ce_zone_geo', 'zone_geo',
'lieudit', 'station', 'milieu', 'date_observation', 'di.mots_cles_texte as mots_cles_texte', 'di.commentaire as commentaire',
'di.i_mots_cles_texte AS mots_cles_texte_image ', 'date_transmission', 'di.id_image as id_image', 'di.ce_utilisateur as ce_utilisateur',
'prenom', 'nom', 'courriel', 'di.nom_utilisateur', 'di.prenom_utilisateur', 'di.courriel_utilisateur', 'nom_original');
$where = array();
if(@$this->parametres['masque.protocole']) $where[] = 'ds.ce_protocole = ' . intval($this->parametres['masque.protocole']);
if(@intval($this->parametres['masque.valeur_vote_min'])) $where[] = 'moyenne >= ' . intval($this->parametres['masque.valeur_vote_min']);
 
$limite = @min(intval($this->parametres['navigation.limite']), 1000);
$limite = $limite ? $limite : 10; // 0 => 10
 
$requeteLiaisons = sprintf(
'SELECT SQL_CALC_FOUND_ROWS %s ce_protocole, moyenne, nb_votes, nb_tags'
// IF(LENGTH()) workaround pour la jointure sur tela_annuaire depuis un hash md5 casté
. ' FROM v_del_image di LEFT JOIN del_utilisateur du ON du.id_utilisateur = IF(LENGTH(di.ce_utilisateur) > 5, 0, di.ce_utilisateur)'
. ' LEFT JOIN del_image_stat ds ON di.id_image = ds.ce_image'
. ' WHERE %s GROUP BY id_image /* car plusieurs image pour obs, see PHP */ ORDER BY moyenne LIMIT %d, %d -- %s:%d',
 
implode(', ',$champs),
implode(' AND ', $where),
intval(@$this->parametres['navigation.depart']),
$limite,
__FILE__, __LINE__);
 
// GROUP BY (très couteux) car multiples observations associées à une image
// eg: 16150,16185,16245,16246,118995,129989
 
return $this->bdd->recupererTous($requeteLiaisons);
}
/**
* Retourner un tableau d'images formaté en fonction des liaisons trouvées
* @param $liaisons les liaisons de la table del_obs_images
* */
private function chargerImage($liaisons) {
$images = array();
foreach ($liaisons as $liaison) {
if($liaison['ce_utilisateur'] == 0) {
$liaison['prenom'] = $liaison['prenom_utilisateur'];
$liaison['nom'] = $liaison['nom_utilisateur'];
}
$idObs = $liaison['id_observation'];
$idImage = $liaison['id_image'];
// On enregistre l'ID de l'obs pour n'effectuer qu'une seule requête par la suite
$this->obsIds[] = $idObs;
$index = $liaison['id_image'].'-'.$liaison['id_observation'];
$this->indexImagesIds[$idImage] = $index;
$images[$index] = array(
'id_image' => $idImage,
'id_observation' => $idObs,
'auteur.intitule' => $liaison['prenom'].' '.$liaison['nom'],
'binaire.href' => sprintf($this->conteneur->getParametre('url_images'), $idImage),
'determination.famille' => $liaison['famille'],
'determination.referentiel' => $liaison['nom_referentiel'],
'determination.ns' => $liaison['nom_ret'],
'determination.nn' => $liaison['nom_ret_nn'],
'determination.nt' => $liaison['nt'],
'date_observation' => $liaison['date_observation'],
'localite' => $this->formaterLieu($liaison),
'mots_cles_image_cel' => $this->formaterMotsClesCel($liaison['mots_cles_texte_image']),
'mots_cles_image_del' => ""
);
}
return $images;
}
/**
* Charger les votes pour chaque image
**/
private function chargerPropositionPlusProbable($images) {
$resultatsPropositions = $this->bdd->recupererTous(sprintf(
'SELECT * FROM del_commentaire WHERE ce_observation IN (%s) AND nom_sel IS NOT NULL',
implode(',', $this->obsIds)));
 
$resultatsVotes = $this->bdd->recupererTous(sprintf(
'SELECT ce_proposition, valeur, ce_utilisateur FROM del_commentaire_vote WHERE ce_proposition IN'.
' ( SELECT id_commentaire FROM del_commentaire WHERE ce_observation IN (%s) AND nom_sel IS NOT NULL )'.
' ORDER BY ce_proposition',
implode(',', $this->obsIds)));
 
$resultatsMotsCles = $this->bdd->recupererTous(sprintf(
'SELECT tag, ce_image FROM del_image_tag WHERE ce_image IN (%s) AND actif = 1',
implode(',', array_keys($this->indexImagesIds))));
 
$propositions = array();
$votes = array();
foreach($resultatsVotes as $vote) {
if(!isset($votes[$vote['ce_proposition']])) {
$votes[$vote['ce_proposition']] = 0;
}
$valeur = ($vote['valeur'] == 1) ? 1 : -1;
$votes[$vote['ce_proposition']] += is_numeric($vote['ce_utilisateur']) ? 3*$valeur : $valeur;
}
foreach($resultatsPropositions as $proposition) {
$id_proposition = $proposition['id_commentaire'];
$id_obs = $proposition['ce_observation'];
if(isset($votes[$id_proposition])) {
$score = $votes[$id_proposition];
} else {
$score = -1;
}
$proposition['valeur'] = $score;
if(!isset($propositions[$id_obs])) {
$propositions[$id_obs] = $proposition;
} else {
$score_ancienne_proposition = $propositions[$id_obs]['valeur'];
$propositions[$id_obs] = ($score >= $score_ancienne_proposition) ?
$proposition : $propositions[$id_obs];
}
}
foreach ($resultatsMotsCles as $motCle) {
$tag = $motCle['tag'];
$index = $this->indexImagesIds[$motCle['ce_image']];
if($images[$index]['mots_cles_image_del'] != "") {
$tag = ",".$tag;
}
$images[$index]['mots_cles_image_del'] .= $tag ;
}
 
foreach ($images as $id => $image) {
if ($this->doitRemplacerObservationParProposition($propositions, $image)) {
$id_obs = $image['id_observation'];
$images[$id]['determination.famille'] = $propositions[$id_obs]['famille'];
$images[$id]['determination.ns'] = $propositions[$id_obs]['nom_sel'];
$images[$id]['determination.nn'] = $propositions[$id_obs]['nom_sel_nn'];
$images[$id]['determination.nt'] = $propositions[$id_obs]['nt'];
}
if(isset($images[$id]['determination.nn'])) {
$images[$id]['url_fiche_eflore'] = sprintf($this->conteneur->getParametre('url_fiche_eflore'), $images[$id]['determination.nn']); // formaterUrlFicheEflore
}
}
return $images;
}
private function doitRemplacerObservationParProposition($propositions, $image) {
return ((isset($propositions[$image['id_observation']]) &&
$propositions[$image['id_observation']] != null &&
$propositions[$image['id_observation']]['nom_sel_nn'] != 0) &&
($propositions[$image['id_observation']]['valeur'] > 0 ||
$image['determination.nn'] == 0)
);
}
/*-------------------------------------------------------------------------------
FORMATER ET METTRE EN FORME
--------------------------------------------------------------------------------*/
/**
* Formater les mots clés du cel en n'affichant que ceux faisant partie
* d'une liste définie dans le fichier de configuration
* @param $chaineMotCleCel la chaine de mots clés du cel
* @return string la chaine filtrée
* */
private function formaterMotsClesCel($chaineMotCleCel) {
return implode(',', array_intersect(
explode(',', $this->conteneur->getParametre('mots_cles_cel_affiches')), // $tabMotsClesAffiches
explode(',', $chaineMotCleCel))); // $tabMotsClesCel
}
 
private function formaterLieu($image) {
if(! $image['ce_zone_geo']) return '';
 
$lieu = $image['zone_geo'];
$id_zone_geo = $image['ce_zone_geo'];
if(strpos($image['ce_zone_geo'], 'INSEE-C:') === 0) {
$id_zone_geo = str_replace('INSEE-C:', '', $image['ce_zone_geo']);
$id_zone_geo = strlen($id_zone_geo) >= 5 ? substr($id_zone_geo, 0, 2) : $id_zone_geo;
}
return $lieu . ' ('.$id_zone_geo.')';
}
}
/tags/v1.1-helium/services/modules/0.1/determinations/ValiderDetermination.php
New file
0,0 → 1,125
<?php
// declare(encoding='UTF-8');
/**
* Le web service récupére un identifiant de proposition et appelle un service web externe
* (du cel) afin de modifier le nom de l'observation associée par celui de la proposition
*
* @category php 5.2
* @package del
* @subpackage images
* @author Aurélien Peronnet <aurelien@tela-botanica.org>
* @copyright Copyright (c) 2013, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images
*/
 
class ValiderDetermination {
private $conteneur;
private $navigation;
private $masque;
private $gestionBdd;
private $bdd;
private $parametres = array();
private $ressources = array();
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_determinations.ini');
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
public function modifier($ressources, $parametres) {
$this->verifierParametres($ressources, $parametres);
$id_proposition = $ressources[1];
$e = $this->modifierObservationParDetermination($id_proposition, $parametres['auteur.id']);
if($e == 'ok' || $e == 'OK' || $e == 'Not Modified') {
RestServeur::envoyerEnteteStatutHttp(RestServeur::HTTP_CODE_OK);
return;
}
throw new Exception("error: Cel returned \"$e\"", RestServeur::HTTP_CODE_ERREUR);
}
public function verifierParametres($ressources, $parametres) {
$erreurs = array();
if (!is_numeric($ressources[1])) {
$erreurs[] = '- le paramètre indiquant l\'identifiant de la proposition doit être numérique ;';
}
 
//Le paramètre auteur.id (id de l'auteur de la détermination)
// est là pour éviter que le $_POST ne soit vide
if (!isset($parametres['auteur.id'])) {
$erreurs[] = '- paramètre "auteur.id" manquant ;';
}
if ($erreurs) {
throw new Exception("Erreur lors de la configuration :\n" . implode("\n", $erreurs),
RestServeur::HTTP_CODE_ERREUR);
}
}
/*
* 1) récupère l'observation, autrement échec
* 2) récupère et l'auteur officiel et valide l'authentification (match sur $_POST['auteur.id'] et $_SESSION), autrement échec
* 3) prépare les nouvelles valeurs à mettre à jour dans cel_obs depuis del_commentaire
* 4) effectue la mise à jour
* 5) si tout s'est passé comme convenu, marque la proposition comme "retenue"
*/
private function modifierObservationParDetermination($id_proposition, $auteurId) {
$champs_a_modifier = array('nom_sel', 'nom_sel_nn', 'nom_ret', 'nom_ret_nn', 'nom_referentiel');
 
// obtenirInformationDetermination()
// TODO: else { LIMIT 1 ? }
$proposition = $this->bdd->recuperer(sprintf('SELECT ce_observation, id_commentaire, %s FROM del_commentaire WHERE id_commentaire = %d AND %s',
implode(',', $champs_a_modifier),
intval($id_proposition),
$auteurId ? 'ce_utilisateur = ' . $this->bdd->proteger($auteurId) : 1));
 
if(! $proposition) {
throw new Exception("Cette proposition est invalide.", RestServeur::HTTP_CODE_ERREUR);
}
 
 
$obsId = $proposition['ce_observation'];
// obtenirInformationsObservation()
$realAuteurId = $this->bdd->recuperer(sprintf('SELECT ce_utilisateur FROM del_observation WHERE id_observation = %d',
intval($obsId)));
$realAuteurId = $realAuteurId['ce_utilisateur']; // XXX: PHP-5.3
 
if(! $this->validationReqOriginMatchObsAuthor($realAuteurId)) {
throw new Exception("Seul l'utilisateur ayant saisi l'observation peut la valider : veuillez vous identifier.\n",
RestServeur::HTTP_CODE_ERREUR);
}
 
$parametres_formates = array_intersect_key($proposition,
array_flip($champs_a_modifier));
$parametres_formates = array_merge($parametres_formates,
array('id_observation' => $obsId,
'ce_utilisateur' => $realAuteurId,
// on change la "certitude" de l'observation correspondante
'certitude' => 'Certaine',
'obsKeywordDelete' => 'adeterminer'));
$ret = $this->conteneur->getRestClient()->modifier($this->conteneur->getParametre('url_service_validation_base') . $obsId,
$parametres_formates);
// cf cel/jrest/services/CelValidationObservation.php::updateElement()
// TODO: check sur HTTP code == 200, plutôt que sur texte
if($ret == 'ok' || $ret == 'OK') {
// remet à 0 le status "proposition_retenue" pour toutes les propositions faites sur cette
// observation à l'exception de celle désormais validée
$this->bdd->requeter(sprintf('UPDATE del_commentaire SET proposition_retenue = IF(id_commentaire = %d, 1, 0)' .
' WHERE ce_observation = %d -- %s',
$proposition['id_commentaire'], $obsId, __FILE__ . ':' . __LINE__));
}
return $ret;
}
private function validationReqOriginMatchObsAuthor($ce_utilisateur) {
$controle_utilisateur = new ControleAcces($this->conteneur);
$utilisateur_connecte = $controle_utilisateur->getInfosUtilisateurConnecte();
return $ce_utilisateur == $utilisateur_connecte['id_utilisateur'];
}
}
/tags/v1.1-helium/services/modules/0.1/commentaires/ListeCommentaires.php
New file
0,0 → 1,205
<?php
// declare(encoding='UTF-8');
/**
* Le web service image récupère toutes les données de la table del_obs_images
* pour retourner une liste d'images associée à une observation
*
* @category php 5.2
* @package del
* @subpackage images
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images
*/
 
class ListeCommentaires {
private $conteneur;
private $navigation;
private $masque;
private $gestionBdd;
private $bdd;
private $parametres = array();
private $ressources = array();
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_commentaires.ini');
$this->conteneur->chargerConfiguration('config_mapping_commentaires.ini');
$this->navigation = $conteneur->getNavigation();
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
/**
* Méthode principale de la classe.
* Lance la récupération des images dans la base et les place dans un objet ResultatService
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function consulter($ressources, $parametres) {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
// Gestion des configuration du script
$this->configurer();
$this->verifierConfiguration();
// Lancement du service
$commentaires = $this->chargerCommentaires();
$commentaires = $this->formaterCommentaires($commentaires);
$total = $this->compterCommentaires();
$this->navigation->setTotal($total);
 
$resultat = new ResultatService();
$resultat->corps = array('entete' => $this->conteneur->getEntete(), 'resultats' => $commentaires);
return $resultat;
}
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
/*-------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
--------------------------------------------------------------------------------*/
/**
* Configuration du service en fonction du fichier de config config_del.ini
* */
public function configurer() {
$this->mappingFiltre = $this->conteneur->getParametre('mapping_masque');
$this->mappingCommentaire = $this->conteneur->getParametre('mapping_commentaire');
}
/**
* Vérifier que le service est bien configuré
* */
public function verifierConfiguration() {
$erreurs = array();
$tableauCommentaires = $this->conteneur->getParametre('commentaires');
if (empty($tableauCommentaires)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [commentaires] ou celui-ci est vide ;';
} else {
if ($this->conteneur->getParametre('url_service') == null) {
$erreurs[] = '- paramètre "url_service" manquant ;';
}
}
 
if (empty($this->mappingCommentaire)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [mapping_commentaire] ou celui-ci est vide ;';
} else {
$champsMappingCom = array('id_commentaire', 'texte', 'ce_utilisateur', 'utilisateur_nom', 'utilisateur_prenom', 'utilisateur_courriel', 'date');
foreach ($champsMappingCom as $champ) {
if (!isset($this->mappingCommentaire[$champ])) {
$erreurs[] = '- le mapping du champ "'.$champ.'" pour le commentaire est manquant ;';
}
}
}
if (empty($this->mappingFiltre)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [mapping_masque] ou celui-ci est vide ;';
} else {
$champsMappingFiltre = array('observation');
foreach ($champsMappingFiltre as $champ) {
if (!isset($this->mappingFiltre[$champ])) {
$erreurs[] = '- le mapping du champ "'.$champ.'" pour l\'observation est manquant ;';
}
}
}
if (!empty($erreurs)) {
$e = 'Erreur lors de la configuration : '."\n";
$e .= implode("\n", $erreurs);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
/**
* Charger la clause WHERE en fonction des paramètres de masque
* */
private function chargerClauseWhere() {
$where = array();
$tableauMasque = $this->masque->getMasque();
if (!empty($tableauMasque)) {
foreach($tableauMasque as $idMasque => $valeurMasque) {
//TODO: scinder ceci en fonctions réutilisables ?
// voir si c'est interessant par rapport à la recherche générale
$idMasque = str_replace('masque.', '', $idMasque);
switch ($idMasque) {
default:
$where[] = ' '.$this->mappingFiltre[$idMasque].' = '.$this->proteger($valeurMasque);
break;
}
}
}
if (!empty($where)) {
return ' WHERE '.implode('AND', $where);
} else {
return;
}
}
/*-------------------------------------------------------------------------------
CHARGEMENT DES COMMENTAIRES
--------------------------------------------------------------------------------*/
/**
* Chargement depuis la bdd de tous les commentaires
* */
private function chargerCommentaires() {
$requeteLiaisons = 'SELECT DISTINCT SQL_CALC_FOUND_ROWS * '.
'FROM '.$this->gestionBdd->formaterTable('del_commentaire', 'dc');
$requeteLiaisons .= $this->chargerClauseWhere();
$requeteLiaisons .= $this->gestionBdd->getLimitSql();
return $this->bdd->recupererTous($requeteLiaisons);
}
/**
* Compter le nombre total de commentaires dans la base pour affichage dans entete.
* */
private function compterCommentaires() {
$requete = 'SELECT FOUND_ROWS() AS nbre ';
$resultats = $this->bdd->recuperer($requete);
return (int) $resultats['nbre'];
}
/*-------------------------------------------------------------------------------
FORMATER ET METTRE EN FORME
--------------------------------------------------------------------------------*/
/**
* Formater les commentaires
* @param $commentaires les commentaires à mettre à jour
* @return $commentaires les commentaires mis à jour
* */
private function formaterCommentaires($commentaires) {
$retourCommentaires = array();
foreach ($commentaires as $id => $commentaire) {
$nouveauCommentaire = array();
foreach ($this->mappingCommentaire as $nomOriginal => $nomFinal) {
$nouveauCommentaire[$nomFinal] = $commentaire[$nomOriginal];
}
$retourCommentaires[$nouveauCommentaire['id_commentaire']] = $nouveauCommentaire;
}
return $retourCommentaires;
}
private function proteger($valeur) {
if (is_array($valeur)) {
return $this->bdd->protegerTableau($valeur);
} else {
return $this->bdd->proteger($valeur);
}
}
}
?>
/tags/v1.1-helium/services/modules/0.1/commentaires/SupprimerCommentaire.php
New file
0,0 → 1,199
<?php
// declare(encoding='UTF-8');
/**
* Le web service image récupère toutes les données de la table del_obs_images
* pour retourner une liste d'images associée à une observation
*
* @category php 5.2
* @package del
* @subpackage images
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images
*/
 
class SupprimerCommentaire {
private $conteneur;
private $navigation;
private $masque;
private $gestionBdd;
private $bdd;
private $parametres = array();
private $ressources = array();
private $commentaireId;
private $utilisateurId;
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_commentaires.ini');
$this->conteneur->chargerConfiguration('config_mapping_commentaires.ini');
$this->navigation = $conteneur->getNavigation();
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
/**
* Méthode principale de la classe.
* Lance la récupération des images dans la base et les place dans un objet ResultatService
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function supprimer($ressources, $parametres) {
$resultat = new ResultatService();
$this->initialiserRessourcesEtParametres($ressources, $parametres);
// Gestion des configuration du script
$this->configurer();
// la suppression est autorisée pour le propriétaire et l'admin sur un commentaire ou une proposition
// qui n'a jamais été commentée en retour
if ($this->sansEnfant() && $this->utilisateurEstAutorise()) {
$this->supprimerCommentaire();
$this->supprimerVotesAssocies();
} else {
$e = 'Impossible de supprimer le commentaire car il a des réponses ou ce n\'est pas le vôtre.';
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
return $resultat;
}
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
/*-------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
--------------------------------------------------------------------------------*/
/** sansEnfant permet de vérifier que le commentaire que l'on veut supprimer
* n'a aucune réponse
* */
public function sansEnfant() {
$requete = 'SELECT * FROM '.$this->gestionBdd->formaterTable('del_commentaire').
'WHERE (ce_proposition = '.$this->commentaireId.' '.
'OR ce_commentaire_parent = '.$this->commentaireId.')';
$resultats = $this->bdd->recupererTous($requete);
if (!empty($resultats)) {
$e = 'Impossible de supprimer le commentaire car il a des réponses';
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
return true;
}
private function utilisateurEstAutorise() {
$autorise = true;
if(!$this->estProprietaire() && !$this->utilisateurEstAdmin()) {
$e = 'Impossible de supprimer le commentaire car l\'utilisateur n\'a pas les droits requis';
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
$autorise = false;
}
return $autorise;
}
/**
* estProprietaire permet de vérifier que le commentaire appartient à l'utilisateur
*
* */
public function estProprietaire() {
$requete = 'SELECT * FROM '.$this->gestionBdd->formaterTable('del_commentaire').
'WHERE id_commentaire = '.$this->commentaireId.' '.
'AND ce_utilisateur = '.$this->utilisateurId;
$resultats = $this->bdd->recupererTous($requete);
return !empty($resultats);
}
/**
* Obtient l'utilisateur par le cookie
*/
public function getUtilisateurParCookie() {
//TODO: utiliser le cookie n'est pas très sécurisé
// ceci aussi devrait être dans une classe utilitaire
if(isset($_COOKIE['del_courriel']) && $_COOKIE['del_courriel'] != '') {
$courriel = $_COOKIE['del_courriel'];
$requete = 'SELECT id_utilisateur FROM '.$this->gestionBdd->formaterTable('del_utilisateur', 'du').
'WHERE courriel = '.$this->bdd->proteger($courriel);
$utilisateur = $this->bdd->recuperer($requete);
$this->utilisateurId = $utilisateur['id_utilisateur'];
}
}
/**
* Renvoie vrai si l'utilisateur existe dans la base de données et si son champ admin est à 1
*/
private function utilisateurEstAdmin() {
//TODO: déplacer ceci dans une classe utilitaire
$requete = 'SELECT admin FROM '.$this->gestionBdd->formaterTable('del_utilisateur_infos', 'dui').
'WHERE id_utilisateur = '.$this->bdd->proteger($this->utilisateurId);
$resultat = $this->bdd->recuperer($requete);
return ($resultat && $resultat['admin'] == 1);
}
/**
* Initialiser les attributs de la classe avec les parametres
* */
public function configurer() {
$erreurs= array();
if (isset($this->ressources[0]) && is_numeric($this->ressources[0])) {
$this->commentaireId = $this->ressources[0];
} else {
$erreurs[] = ' - l\identifiant du commentaire doit être un entier; ';
}
if(isset($_COOKIE['del_courriel']) && $_COOKIE['del_courriel'] != '') {
$this->getUtilisateurParCookie();
} else {
$erreurs[] = ' - Ce service nécessite d\'être identifié; ';
}
if (!empty($erreurs)) {
$e = 'Erreur de configuration :';
$e = implode("\n", $erreurs);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
/*-------------------------------------------------------------------------------
SUPPRESSION DES COMMENTAIRES
--------------------------------------------------------------------------------*/
/**
* Requete effective de suppression
* */
public function supprimerCommentaire() {
$requete = 'DELETE FROM '.$this->gestionBdd->formaterTable('del_commentaire').' '.
'WHERE id_commentaire = '.$this->bdd->proteger($this->commentaireId).' '.
'AND ce_utilisateur = '.$this->bdd->proteger($this->utilisateurId);
$retour = $this->bdd->requeter($requete);
if (!$retour) {
$e = 'Erreur lors de la suppression';
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
/**
* Requete de suppression de votes associés au commentaire
*/
public function supprimerVotesAssocies() {
$requete = 'DELETE FROM '.$this->gestionBdd->formaterTable('del_commentaire_vote').' '.
'WHERE ce_proposition = '.$this->bdd->proteger($this->commentaireId);
$retour = $this->bdd->requeter($requete);
if (!$retour) {
$e = 'Erreur lors de la suppression des votes associés';
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
}
?>
/tags/v1.1-helium/services/modules/0.1/commentaires/AjouterCommentaire.php
New file
0,0 → 1,261
<?php
// declare(encoding='UTF-8');
/**
* Le web service image récupère toutes les données de la table del_obs_images
* pour retourner une liste d'images associée à une observation
*
* @category php 5.2
* @package del
* @subpackage images
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images
*/
 
class AjouterCommentaire {
 
private $conteneur;
private $navigation;
private $masque;
private $gestionBdd;
private $bdd;
private $parametres = array();
private $ressources = array();
 
private $commentaire;
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_commentaires.ini');
$this->conteneur->chargerConfiguration('config_mapping_commentaires.ini');
$this->navigation = $conteneur->getNavigation();
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
 
/**
* Ajoute un commentaire/determination si les objets fournis en paramètres sont valides
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function ajouter($ressources, $parametres) {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
 
// Gestion des configuration du script
$this->configurer();
$this->verifierConfiguration();
$utilisateur = $this->chercherUtilisateur();
$proposition_initiale = $this->verifierEtCreerPropositionDeterminationInitiale();
$insertion = $this->insererCommentaire($utilisateur);
 
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
$resultat->corps = array('id_commentaire' => $insertion);
 
return $resultat;
}
 
//ce_observation=728176&texte=ABC&auteur.id=11623&auteur.prenom=grégoire&auteur.nom=duché&auteur.courriel=gregoire@tela-botanica.org
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
/*-------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
--------------------------------------------------------------------------------*/
/**
* Initialiser les attributs de la classe avec les parametres
* */
public function configurer() {
$this->mappingCommentaire = $this->conteneur->getParametre('mapping_commentaire');
//TODO : Gérer le cas d'une proposition
}
 
/**
* Vérifier que le service est bien configuré
* */
public function verifierConfiguration() {
$erreurs = array();
 
if (empty($this->mappingCommentaire)) {
$erreurs[] = "Le fichier de configuration ne contient pas le tableau [mapping_commentaire] ou celui-ci est vide.";
}
 
$parametresPossibles = array_values($this->mappingCommentaire);
foreach ($this->parametres as $nomParam => $valeur) {
if (!in_array($nomParam, $parametresPossibles)) {
$erreurs[] = "Paramètre « {$nomParam} » non autorisé.";
}
}
 
if (!isset($this->parametres['observation'])) {
$erreurs[] = "Impossible d'ajouter un commentaire sans observation.";
}
 
if (!isset($this->parametres['auteur.id'])) {
if (!isset($this->parametres['auteur.nom'])) {
$erreurs[] = "Pas de nom d'utilisateur donné.";
}
 
if (!isset($this->parametres['auteur.prenom'])) {
$erreurs[] = "Pas de prenom d'utilisateur donné.";
}
 
if (!isset($this->parametres['auteur.courriel'])) {
$erreurs[] = "Pas de courriel d'utilisateur donné.";
}
}
 
if (isset($this->parametres['nom_sel']) &&trim($this->parametres['nom_sel']) == '') {
$erreurs[] = "S'il est présent le paramètre «nom_sel» ne peut pas être vide.";
}
 
//TODO : Gérer le cas d'une proposition
 
if (!empty($erreurs)) {
$e = implode("\n", $erreurs);
$msg = "Erreur de configuration :\n $e";
echo $msg;
throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
}
}
 
/*-------------------------------------------------------------------------------
INSERTION DES COMMENTAIRES
--------------------------------------------------------------------------------*/
/**
* Trouver l'utilisateur en fonction des paramètres ou de la base de données si le nom, prénom et courriel ne sont pas donnés
* @return le tableau utilisateur
* */
private function chercherUtilisateur() {
$utilisateur = array();
 
// Si l'id est fournit, on récupère les informations de l'utilisateur dans la base de données
// Sinon, on récupère les informations depuis le tableau Commentaire et on vérifie leur cohérence
if (isset($this->parametres['auteur.id'])) {
$requete = "SELECT id_utilisateur as 'auteur.id', nom as 'auteur.nom', prenom as 'auteur.prenom', courriel as 'auteur.courriel' ".
'FROM '.$this->gestionBdd->formaterTable('del_utilisateur').
'WHERE id_utilisateur = '.$this->bdd->proteger($this->parametres['auteur.id']);
$utilisateur = $this->bdd->recuperer($requete);
} else {
if (isset($this->parametres['auteur.nom']) && isset($this->parametres['auteur.prenom']) && isset($this->parametres['auteur.courriel'])) {
$utilisateur['auteur.nom'] = $this->parametres['auteur.nom'];
$utilisateur['auteur.prenom'] = $this->parametres['auteur.prenom'];
$utilisateur['auteur.courriel'] = $this->parametres['auteur.courriel'];
if ($utilisateur_recherche = $this->estValideDansBdd($utilisateur)) {
// si l'utilisateur est trouvé, on affecte son id au lieu du numéro temporaire
$utilisateur = $utilisateur_recherche;
$this->parametres['auteur.id'] = $utilisateur_recherche['auteur.id'];
}
// sinon pas d'erreur, on considere simplement que l'utilisateur
// est un homonyme ou bien qu'il a décidé d'utiliser un autre mail
}
}
 
return $utilisateur;
}
 
/**
* Vérifier que les informations saisies pour un utilisateur sont valides pour la bdd
* @param $utilisateur array le tableau de l'utilisateur
* */
private function estValideDansBdd($utilisateur) {
$nom = $this->bdd->proteger($utilisateur['auteur.nom']);
$prenom = $this->bdd->proteger($utilisateur['auteur.prenom']);
$courriel = $this->bdd->proteger($utilisateur['auteur.courriel']);
 
$requete = "SELECT id_utilisateur AS 'auteur.id', nom AS 'auteur.nom', prenom AS 'auteur.prenom', ".
" courriel AS 'auteur.courriel' ".
'FROM del_utilisateur '.
"WHERE courriel = $courriel ".
" AND nom = $nom ".
" AND prenom = $prenom ";
$utilisateurBdd = $this->bdd->recuperer($requete);
return $utilisateurBdd;
}
 
/**
* Insère un commentaire dans la table
* @param $utilisateur array la liste des paramètres utilisateur
* */
private function insererCommentaire($utilisateur) {
$requete = 'INSERT INTO del_commentaire '.
'('.$this->genererEntete($utilisateur).') '.
'VALUES ('.$this->genererValues().')';
 
$retour = $this->bdd->requeter($requete);
if ($retour == null) {
$e = "Erreur inopinée lors de l'insertion";
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
 
$retour = $this->bdd->recupererIdDernierAjout();
 
return $retour;
}
 
private function verifierEtCreerPropositionDeterminationInitiale() {
$id_observation = $this->parametres['observation'];
$proposition_existe = $this->propositionInitialeExiste($id_observation);
if (!$proposition_existe) {
$this->creerPropositionAPartirObservation($id_observation);
}
}
 
private function propositionInitialeExiste($id_observation) {
$requete = 'SELECT COUNT(*) >= 1 AS existe '.
'FROM del_commentaire '.
"WHERE ce_observation = $id_observation ".
' AND proposition_initiale = 1';
$resultat = $this->bdd->recuperer($requete);
return $resultat['existe'] == 1;
}
 
private function creerPropositionAPartirObservation($id_observation) {
$idObs = $this->bdd->proteger($id_observation);
$insertion = 'INSERT IGNORE INTO del_commentaire '.
'(ce_observation, ce_utilisateur, utilisateur_prenom, utilisateur_nom, utilisateur_courriel, '.
'nom_sel, nom_sel_nn, nom_ret, nom_ret_nn, nt, famille, nom_referentiel, date, proposition_initiale) '.
'SELECT id_observation, ce_utilisateur, prenom, nom, '.
' courriel, nom_sel, nom_sel_nn, nom_ret, nom_ret_nn, '.
" nt, famille, nom_referentiel, NOW(), '1' ".
'FROM del_observation AS do '.
' LEFT JOIN del_utilisateur AS du '.
' ON do.ce_utilisateur = du.id_utilisateur '.
"WHERE id_observation = $idObs ";
 
$resultat = $this->bdd->requeter($insertion);
return $resultat;
}
 
private function genererEntete($utilisateur) {
$this->parametres = array_merge($this->parametres, $utilisateur);
 
$entete = array('date');
foreach ($this->mappingCommentaire as $nomOriginal => $nomFinal) {
if (isset($this->parametres[$nomFinal]) && $this->parametres[$nomFinal] != null) {
$entete[] = $nomOriginal;
}
}
 
return implode(', ', $entete);
}
 
private function genererValues() {
$valeurs = array('NOW()');
foreach ($this->mappingCommentaire as $nomOriginal => $nomFinal) {
if (isset($this->parametres[$nomFinal]) && $this->parametres[$nomFinal] != null) {
$valeurs[] = $this->bdd->proteger($this->parametres[$nomFinal]);
}
}
 
return implode(', ', $valeurs);
}
}
?>
/tags/v1.1-helium/services/modules/0.1/commentaires/ConsulterCommentaire.php
New file
0,0 → 1,221
<?php
// declare(encoding='UTF-8');
/**
* Le web service image récupère toutes les données de la table del_obs_images
* pour retourner une liste d'images associée à une observation
*
* @category php 5.2
* @package del
* @subpackage images
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images
*/
 
class ConsulterCommentaire {
private $conteneur;
private $navigation;
private $masque;
private $gestionBdd;
private $bdd;
private $parametres = array();
private $ressources = array();
private $idCommentaire;
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_commentaires.ini');
$this->conteneur->chargerConfiguration('config_mapping_commentaires.ini');
$this->navigation = $conteneur->getNavigation();
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
/**
* Méthode principale de la classe.
* Lance la récupération des images dans la base et les place dans un objet ResultatService
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function consulter($ressources, $parametres) {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
// Gestion des configuration du script
$this->configurer();
$this->verifierConfiguration();
// Lancement du service
$commentaires = $this->chargerCommentaires();
$commentaires = $this->formaterCommentaires($commentaires);
$total = $this->compterCommentaires();
$this->navigation->setTotal($total);
/*$images = $this->chargerImage($liaisons);
$images = $this->chargerVotes($images);
// Mettre en forme le résultat et l'envoyer pour affichage*/
$resultat = new ResultatService();
$resultat->corps = array('entete' => $this->conteneur->getEntete(), 'resultats' => $commentaires);
return $resultat;
}
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
if (sizeof($this->ressources) == 1 && (is_numeric($this->ressources[0]))) {
$this->idCommentaire = $ressources[0];
} else {
$e = 'L\identifiant d\un commentaire est numérique';
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
$this->parametres = $parametres;
}
/*-------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
--------------------------------------------------------------------------------*/
/**
* Configuration du service en fonction du fichier de config config_del.ini
* */
public function configurer() {
$this->mappingFiltre = $this->conteneur->getParametre('mapping_masque');
$this->mappingCommentaire = $this->conteneur->getParametre('mapping_commentaire');
}
/**
* Vérifier que le service est bien configuré
* */
public function verifierConfiguration() {
$erreurs = array();
$tableauCommentaires = $this->conteneur->getParametre('commentaires');
if (empty($tableauCommentaires)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [commentaires] ou celui-ci est vide ;';
} else {
if ($this->conteneur->getParametre('url_service') == null) {
$erreurs[] = '- paramètre "url_service" manquant ;';
}
}
 
if (empty($this->mappingCommentaire)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [mapping_commentaire] ou celui-ci est vide ;';
} else {
$champsMappingCom = array('id_commentaire', 'texte', 'ce_utilisateur', 'utilisateur_nom', 'utilisateur_prenom', 'utilisateur_courriel', 'date');
foreach ($champsMappingCom as $champ) {
if (!isset($this->mappingCommentaire[$champ])) {
$erreurs[] = '- le mapping du champ "'.$champ.'" pour le commentaire est manquant ;';
}
}
}
if (empty($this->mappingFiltre)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [mapping_masque] ou celui-ci est vide ;';
} else {
$champsMappingFiltre = array('observation');
foreach ($champsMappingFiltre as $champ) {
if (!isset($this->mappingFiltre[$champ])) {
$erreurs[] = '- le mapping du champ "'.$champ.'" pour l\'observation est manquant ;';
}
}
}
if (!empty($erreurs)) {
$e = 'Erreur lors de la configuration : '."\n";
$e .= implode("\n", $erreurs);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
/**
* Charger la clause WHERE en fonction des paramètres de masque
* */
private function chargerClauseWhere() {
$where = array();
if (isset($this->idCommentaire)) {
$where[] = 'id_commentaire = '.$this->idCommentaire;
}
$tableauMasque = $this->masque->getMasque();
if (!empty($tableauMasque)) {
foreach($tableauMasque as $idMasque => $valeurMasque) {
//TODO: scinder ceci en fonctions réutilisables ?
// voir si c'est interessant par rapport à la recherche générale
$idMasque = str_replace('masque.', '', $idMasque);
switch ($idMasque) {
default:
$where[] = ' '.$this->mappingFiltre[$idMasque].' = '.$this->proteger($valeurMasque);
break;
}
}
}
if (!empty($where)) {
return ' WHERE '.implode('AND', $where);
} else {
return;
}
}
/*-------------------------------------------------------------------------------
CHARGEMENT DES COMMENTAIRES
--------------------------------------------------------------------------------*/
/**
* Chargement depuis la bdd de tous les commentaires
* */
private function chargerCommentaires() {
$requeteLiaisons = 'SELECT DISTINCT SQL_CALC_FOUND_ROWS * '.
'FROM '.$this->gestionBdd->formaterTable('del_commentaire', 'dc');
$requeteLiaisons .= $this->chargerClauseWhere();
$requeteLiaisons .= $this->gestionBdd->getLimitSql();
return $this->bdd->recupererTous($requeteLiaisons);
}
/**
* Compter le nombre total de commentaires dans la base pour affichage dans entete.
* */
private function compterCommentaires() {
$requete = 'SELECT FOUND_ROWS() AS nbre ';
$resultats = $this->bdd->recuperer($requete);
return (int) $resultats['nbre'];
}
/*-------------------------------------------------------------------------------
FORMATER ET METTRE EN FORME
--------------------------------------------------------------------------------*/
/**
* Formater les commentaires
* @param $commentaires les commentaires à mettre à jour
* @return $commentaires les commentaires mis à jour
* */
private function formaterCommentaires($commentaires) {
$retourCommentaires = array();
foreach ($commentaires as $id => $commentaire) {
foreach ($this->mappingCommentaire as $nomOriginal => $nomFinal) {
$retourCommentaires[$nomFinal] = $commentaire[$nomOriginal];
}
}
 
return $retourCommentaires;
}
private function proteger($valeur) {
if (is_array($valeur)) {
return $this->bdd->protegerTableau($valeur);
} else {
return $this->bdd->proteger($valeur);
}
}
}
?>
/tags/v1.1-helium/services/modules/0.1/communes/ListeCommunes.php
New file
0,0 → 1,81
<?php
// declare(encoding='UTF-8');
/**
* Le web service image récupère toutes les données de la table del_obs_images
* pour retourner une liste d'images associée à une observation
*
* @category php 5.2
* @package del
* @subpackage images
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images
*/
 
class ListeCommunes {
private $conteneur;
private $navigation;
private $masque;
private $gestionBdd;
private $bdd;
private $parametres = array();
private $ressources = array();
private $requete = null;
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_communes.ini');
$this->navigation = $conteneur->getNavigation();
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
/**
* Méthode principale de la classe.
* Lance la récupération des images dans la base et les place dans un objet ResultatService
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function consulter($ressources, $parametres) {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
// Lancement du service
$communes = $this->chargerCommunes($this->masque->getMasque('nom'));
$total = $this->compterCommunes($communes);
$this->navigation->setTotal($total);
$this->conteneur->setSansLimite();
$resultat = new ResultatService();
$resultat->corps = array('entete' => $this->conteneur->getEntete(), 'resultats' => $communes);
return $resultat;
}
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
/*-------------------------------------------------------------------------------
CHARGEMENT DES COMMENTAIRES
--------------------------------------------------------------------------------*/
/**
* Chargement depuis le serveur de toutes les communes
* */
private function chargerCommunes($requete) {
return json_decode(file_get_contents("http://www.tela-botanica.org/eflore/cel2/jrest/LocationSearch/".$requete));
}
/**
* Compter le nombre total de communes pour affichage dans entete.
* */
private function compterCommunes($communes) {
return sizeof($communes);
}
}
?>
/tags/v1.1-helium/services/modules/0.1/protocoles/ListeProtocoles.php
New file
0,0 → 1,144
<?php
// declare(encoding='UTF-8');
/**
* Le web service observations récupère tous les protocoles avec leur id, nom et descriptif
*
* @category php 5.2
* @package del
* @subpackage protocoles
* @author Aurélien Peronnet <aurelien@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Protocoles
*/
 
class ListeProtocoles extends RestService {
 
private $conteneur;
private $navigation;
private $masque;
private $gestionBdd;
protected $bdd;
private $parametres = array();
private $ressources = array();
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_mapping_votes.ini');
$this->navigation = $conteneur->getNavigation();
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
 
/**
* Méthode principale de la classe.
* Lance la récupération des protocoles dans la base et les place dans un objet ResultatService
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function consulter($ressources, $parametres) {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
 
// Gestion des configuration du script
$this->configurer();
$this->verifierConfiguration();
 
$protocoles = $this->chargerProtocoles();
$protocoles = $this->formaterProtocoles($protocoles);
$this->navigation->setTotal(count($protocoles));
 
$resultat = new ResultatService();
$resultat->corps = array('entete' => $this->conteneur->getEntete(), 'resultats' => $protocoles);
return $resultat;
}
 
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
/*-------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
--------------------------------------------------------------------------------*/
/**
* Configuration du service en fonction du fichier de config config_del.ini
* */
private function configurer() {
$this->mappingVotes = $this->conteneur->getParametre('mapping_votes');
}
 
/**
* Vérifier que le service est bien configuré
* */
private function verifierConfiguration() {
if (empty($this->mappingVotes)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [mapping_votes] ou celui-ci est vide ;';
} else {
$champsMappingVotes = array('id_protocole', 'intitule', 'descriptif');
foreach ($champsMappingVotes as $champ) {
if (!isset($this->mappingVotes[$champ])) {
$erreurs[] = '- le mapping du champ "'.$champ.'" pour les votes est manquant ;';
}
}
}
 
$parametres_autorises = array('navigation.depart', 'navigation.limite');
foreach ($this->parametres as $cle => $valeur) {
if($cle != 'navigation.depart' && $cle != 'navigation.limite') {
$erreurs[] = '- aucun masque n\'est autorisé pour ce service ;';
break;
}
}
 
if (!empty($erreurs)) {
$e = 'Erreur lors de la configuration : '."\n";
$e .= implode("\n", $erreurs);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
 
/*-------------------------------------------------------------------------------
CHARGEMENT DES PROTOCOLES
--------------------------------------------------------------------------------*/
/**
* Chargement depuis la bdd de tous les protocoles ainsi que leur descriptif
* */
private function chargerProtocoles() {
$requeteProtocoles = 'SELECT * FROM del_image_protocole';
return $this->bdd->recupererTous($requeteProtocoles);
}
 
/*-------------------------------------------------------------------------------
FORMATER ET METTRE EN FORME
--------------------------------------------------------------------------------*/
 
/**
* Formater les protocoles
* @param array $protocoles les protocoles
* */
private function formaterProtocoles($protocoles) {
$protocolesRetour = array();
foreach ($protocoles as $protocole) {
$protocoleFormate = array();
$idProtocole = $protocole['id_protocole'];
foreach($protocole as $champProtocole => $valeur) {
$protocoleFormate[$this->mappingVotes[$champProtocole]] = $valeur;
}
$protocolesRetour[$idProtocole] = $protocoleFormate;
}
 
return $protocolesRetour;
}
 
private function proteger($valeur) {
if (is_array($valeur)) {
return $this->bdd->protegerTableau($valeur);
} else {
return $this->bdd->proteger($valeur);
}
}
}
?>
/tags/v1.1-helium/services/modules/0.1/DelTk.php
New file
0,0 → 1,448
<?php
/**
* DEL (Détermination en ligne [Pictoflora/Identiplante]) Toolkit
* Quelques fonctions utiles, utilisées et/ou utilisables aussi bien par images/*, observations/*
* et probablement d'autres, comme determination/*.
*
* Les domaines des fonctions tournent autour de 4 aspects:
* - gestions des paramètres d'entrée utilisateurs, valeurs par défaut et sanitization
* - génération de SQL
* - processing de tableau de pattern d'utilisation SQL assez commun
* - formattage basique de sortie (JSON)
* + quelques helpers basiques
*
* @category php 5.2
* @package del
* @author Raphaël Droz <raphael@tela-botanica.org>
* @copyright Copyright (c) 2013 Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
*/
 
 
define('_LISTE_OBS_MAX_RESULT_LIMIT', 1000);
define('_LISTE_OBS_MAX_ID_OBS', 10e7);
// SELECT MAX(num_taxonomique) FROM bdtfx_v2_00;
define('_LISTE_OBS_MAX_BDTFX_NT', 1000000); // 44378 + 1000
// SELECT MAX(num_nom) FROM bdtfx_v2_00;
define('_LISTE_OBS_MAX_BDTFX_NN', 1000000); // 120816 + 10000
 
class DelTk {
static $parametres_autorises = array(
'masque', 'masque.famille', 'masque.nn', 'masque.referentiel', // taxon
'masque.genre', 'masque.espece', 'masque.ns', // nom_sel
'masque.commune', 'masque.departement', 'masque.id_zone_geo', // loc
'masque.auteur', 'masque.date', 'masque.tag', 'masque.type', // autres
// tri, offset
'navigation.depart', 'navigation.limite',
'tri', 'ordre', // TODO: 'total=[yes]', 'fields=[x,y,...]'
// TODO: masque.annee, masque.insee (!= departement)
);
 
static $default_params = array(
'navigation.depart' => 0, 'navigation.limite' => 10,
'tri' => 'date_transmission', 'ordre' => 'desc');
 
 
// input filtering
 
 
/* Construit un (vulgaire) abstract syntax tree:
"AND" => [ "tag1", "tag2" ]
Idéalement (avec un parser simple comme proposé par http://hoa-project.net/Literature/Hack/Compiler.html#Langage_PP)
nous aurions:
"AND" => [ "tag1", "tag2", "OR" => [ "tag3", "tag4" ] ]
 
Ici nous devons traiter les cas suivants:
tags séparés par des "ET/AND OU/OR", séparés par des espaces ou des virgules.
Mais la chaîne peut aussi avoir été issue du "masque général" (la barre de recherche générique).
ce qui implique des comportement par défaut différents afin de préserver la compatibilité.
 
Théorie:
1) tags passés par "champ tag":
- support du ET/OU, et explode par virgule.
- si pas d'opérande détectée: "OU"
 
2) tags passés par "recherche générale":
- support du ET/OU, et explode par whitespace.
- si pas d'opérande détectée: "ET"
 
La présence de $additional_sep s'explique car ET/OU sous-entendent une séparation par des espaces.
Mais ce n'est pas toujours pertinent car: 1) la compatibilité suggère de considérer parfois
la virgule comme séparateur et 2) les tags *peuvent* contenir des espaces. Par conséquent:
* a,b,c => "a" $default_op "b" $default_op "c"
* a,b AND c => "a" AND "b" AND "c"
* a OR b AND c,d => "a" AND "b" AND "c" AND "d"
C'est à dire par ordre décroissant de priorité:
1) opérande contenu dans la chaîne
2) opérande par défaut
3) les séparateurs présents sont substitués par l'opérande déterminée par 1) ou 2)
 
// TODO: support des parenthèses, imbrications & co: "(", ")"
// http://codehackit.blogspot.fr/2011/08/expression-parser-in-php.html
// http://blog.angeloff.name/post/2012/08/05/php-recursive-patterns/
 
@param $str: la chaîne à "parser"
@param $default_op: "AND" ou "OR"
@param $additional_sep: séparateur de mots:
*/
static function buildTagsAST($str = NULL, $default_op, $additional_sep = ',') {
if(!$str) return;
$words = preg_split('/ (OR|AND|ET|OU) /', $str, -1, PREG_SPLIT_NO_EMPTY);
 
if(preg_match('/\b(ET|AND)\b/', $str)) $op = 'AND';
elseif(preg_match('/\b(OU|OR)\b/', $str)) $op = 'OR';
else $op = $default_op;
 
if($additional_sep) {
array_walk($words,
create_function('&$v, $k, $sep', '$v = preg_split("/".$sep."/", $v, -1, PREG_SPLIT_NO_EMPTY);'),
$additional_sep);
}
$words = DelTk::array_flatten($words);
$words = array_map('trim', $words);
return array($op => array_filter($words));
}
 
 
static function array_flatten($arr) {
$arr = array_values($arr);
while (list($k,$v)=each($arr)) {
if (is_array($v)) {
array_splice($arr,$k,1,$v);
next($arr);
}
}
return $arr;
}
 
// supprime l'index du tableau des paramètres si sa valeur ne correspond pas
// au spectre passé par $values.
static function unsetIfInvalid(&$var, $index, $values) {
if(array_key_exists($index, $var)) {
if(!in_array($var[$index], $values)) unset($var[$index]);
else return $var[$index];
}
return NULL;
}
 
 
 
 
/* Filtre et valide les paramètres reconnus. Effectue *toute* la sanitization *sauf* l'escape-string
Cette fonction est appelée:
- une fois sur les champs de recherche avancées
- une fois sur le masque général si celui-ci à été spécifié. Dans ce cas,
la chaîne générale saisie est utilisée comme valeur pour chacun des champs particuliers
avec les traitements particuliers qui s'imposent
Par exemple: si l'on cherche "Languedoc", cela impliquera:
WHERE (nom_sel like "Languedoc" OR nom_ret ... OR ...) mais pas masque.date ou masque.departement
qui s'assure d'un pattern particulier */
static function requestFilterParams(Array $params, $parametres_autorises = NULL, Conteneur $c = NULL /* pour la récup des départements */ ) {
if($parametres_autorises) { // filtrage de toute clef inconnue
$params = array_intersect_key($params, array_flip($parametres_autorises));
}
 
$p['tri'] = DelTK::unsetIfInvalid($params, 'tri', array('date_observation'));
$p['ordre'] = DelTK::unsetIfInvalid($params, 'ordre', array('asc','desc'));
$p['masque.referentiel'] = DelTK::unsetIfInvalid($params, 'masque.referentiel', array('bdtfx','bdtxa','isfan'));
 
// TODO: use filter_input(INPUT_GET);
// renvoie FALSE ou NULL si absent ou invalide
$p['navigation.limite'] = filter_var(@$params['navigation.limite'],
FILTER_VALIDATE_INT,
array('options' => array('default' => NULL,
'min_range' => 1,
'max_range' => _LISTE_OBS_MAX_RESULT_LIMIT)));
$p['navigation.depart'] = filter_var(@$params['navigation.depart'],
FILTER_VALIDATE_INT,
array('options' => array('default' => NULL,
'min_range' => 0,
'max_range' => _LISTE_OBS_MAX_ID_OBS)));
if(isset($params['masque.departement'])) {
// STRING: 0 -> 95, 971 -> 976, 2A + 2B (./services/configurations/config_departements_bruts.ini)
// accept leading 0 ?
// TODO; filter patterns like 555.
if(preg_match(';^(\d{2}|\d{3}|2a|2b)$;i', $params['masque.departement'])) {
$p['masque.departement'] = $params['masque.departement'];
}
// cf configurations/config_departements_bruts.ini
elseif( !is_null($c) && ( $x = $c->getParametre(
strtolower(str_replace(' ','-',iconv("UTF-8", "ASCII//TRANSLIT", $params['masque.departement'])))
))) {
$p['masque.departement'] = sprintf("INSEE-C:%02d___", $x);
}
}
 
if(isset($params['masque.date'])) {
// une année, TODO: masque.annee
if(is_numeric($params['masque.date'])) {
$p['masque.date'] = $params['masque.date'];
}
elseif(strpos($params['masque.date'], '/' !== false) &&
($x = strtotime(str_replace('/','-',$params['masque.date'])))) {
$p['masque.date'] = $x;
}
elseif(strpos($params['masque.date'], '-' !== false) &&
($x = strtotime($params['masque.date'])) ) {
$p['masque.date'] = $x;
}
}
 
$p['masque.nn'] = filter_var(@$params['masque.nn'],
FILTER_VALIDATE_INT,
array('options' => array('default' => NULL,
'min_range' => 0,
'max_range' => _LISTE_OBS_MAX_BDTFX_NN)));
 
$p['masque.nt'] = filter_var(@$params['masque.nt'],
FILTER_VALIDATE_INT,
array('options' => array('default' => NULL,
'min_range' => 0,
'max_range' => _LISTE_OBS_MAX_BDTFX_NT)));
 
 
// TODO: should we really trim() ?
 
if(isset($params['masque.ns'])) $p['masque.ns'] = trim($params['masque.ns']);
// if(isset($params['masque.texte'])) $p['masque.texte'] = trim($params['masque.texte']);
 
if(isset($params['masque.famille'])) {
// mysql -N<<<"SELECT DISTINCT famille FROM bdtfx_v1_02;"|sed -r "s/(.)/\1\n/g"|sort -u|tr -d "\n"
$p['masque.famille'] = preg_replace('/[^a-zA-Z %_]/', '', iconv("UTF-8",
"ASCII//TRANSLIT",
$params['masque.famille']));
}
 
// masque.genre est un alias pour masque.ns (nom_sel), mais permet de rajouter une clause supplémentaire
// sur nom_sel. Précédemment: WHERE nom_sel LIKE '%<masque.genre>% %'.
// Désormais masque.genre doit être intégralement spécifié, les caractères '%' et '_' seront interprétés.
// Attention toutefois car la table del_observation intègre des nom_sel contenant '_'
if(isset($params['masque.genre'])) $p['masque.genre'] = trim($params['masque.genre']);
if(isset($params['masque.ns'])) $p['masque.ns'] = trim($params['masque.ns']);
// masque.espece n'était pas déclaré dans la "where" mais utilisé via config + switch//default
if(isset($params['masque.espece'])) $p['masque.espece'] = trim($params['masque.espece']);
 
// idem pour id_zone_geo qui mappait à ce_zone_geo:
if(isset($params['masque.id_zone_geo']) && preg_match(';^(INSEE-C:\d{5}|\d{2})$;', $params['masque.id_zone_geo'])) {
$p['masque.id_zone_geo'] = $params['masque.id_zone_geo'];
}
 
// masque.commune (zone_geo)
// TODO: que faire avec des '%' en INPUT ?
// Le masque doit *permettre* une regexp et non l'imposer. Charge au client de faire son travail
if(isset($params['masque.commune'])) $p['masque.commune'] = str_replace(array('-',' '), '_', $params['masque.commune']);
 
// masque.auteur: peut-être un id, un courriel, ou un nom ou prénom, ...
if(isset($params['masque.auteur'])) $p['masque.auteur'] = trim($params['masque.auteur']);
// sera trimmé plus tard, cf sqlAddConstraint
if(isset($params['masque'])) $p['masque'] = trim($params['masque']);
 
// masque.tag, idem que pour masque.genre et masque.commune
if(isset($params['masque.tag'])) {
$x = explode(',',$params['masque.tag']);
$x = array_map('trim', $x);
$p['masque.tag'] = implode('|', array_filter($x));
}
 
// masque.type: ['adeterminer', 'aconfirmer', 'endiscussion', 'validees']
if(isset($params['masque.type'])) {
$p['masque.type'] = array_flip(array_intersect(array_filter(explode(';', $params['masque.type'])),
array('adeterminer', 'aconfirmer', 'endiscussion', 'validees')));
}
 
 
// TODO: masque (général)
 
 
// on filtre les NULL, FALSE et '', mais pas les 0, d'où le callback()
// TODO: PHP-5.3
return array_filter($p, create_function('$a','return !in_array($a, array("",false,null),true);'));
}
 
 
 
// SQL helpers
 
/* Lorsque l'on concatène des champs, un seul NULL prend le dessus,
Il faut donc utiliser la syntaxe IFNULL(%s, "").
(Cette fonction effectue aussi l'implode() "final" */
static function sqlAddIfNullPourConcat($tab) {
// XXX: PHP-5.3
return implode(',',array_map(create_function('$a', 'return "IFNULL($a, \"\")";'), $tab));
}
 
 
 
/* Converti un tableau associatif et un préfix optionnel en une chaîne de champs adéquate
à un SELECT MySQL.
$select (optionnel) restreint les champs mappés aux valeurs de $select.
Si $select n'est pas fourni, toutes les clefs présentes dans $map seront présentes dans
le SELECT en sortie */
static function sqlFieldsToAlias($map, $select = NULL, $prefix = NULL) {
if($select) $arr = array_intersect_key($map, array_flip($select));
else $arr = $map;
$keys = array_keys($arr);
 
if($prefix) array_walk($keys, create_function('&$val, $k, $prefix', '$val = sprintf("%s.`%s`", $prefix, $val);'), $prefix);
else array_walk($keys, create_function('&$val, $k', '$val = sprintf("`%s`", $val);'));
 
return implode(', ', array_map(create_function('$v, $k', 'return sprintf("%s AS `%s`", $k, $v);'), $arr, $keys));
}
 
 
 
/*
Retourne une clause where du style:
CONCAT(IF(du.prenom IS NULL, "", du.prenom), [...] vdi.i_nomutilisateur) REGEXP 'xxx'
Note; i_(nom|prenom_utilisateur), alias pour cel_images.(nom|prenom), n'est pas traité
car cette information est redondante dans cel_image et devrait être supprimée.
*/
static function addAuteursConstraint($val, $db, &$where) {
@list($a, $b) = explode(' ', $val, 2);
// un seul terme
$champs_n = array('du.prenom', // info user authentifié de l'obs depuis l'annuaire
'vdi.prenom_utilisateur', // info user anonyme de l'obs
/* 'vdi.i_prenom_utilisateur' */ ); // info user anonyme de l'image
$champs_p = array('du.nom', // idem pour le nom
'vdi.nom_utilisateur',
/* 'vdi.i_nom_utilisateur' */ );
 
/*
Note: pour l'heure, étant donnés:
- les CONVERT() de la VIEW del_utilisateur
- DEFAULT CHARSET=latin1 pour tela_prod_v4.annuaire_tela
- DEFAULT CHARSET=utf8 pour tb_cel.cel_obs
et l'âge du capitaine...
- REGEXP est case-sensitive, et collate les caractères accentués
- LIKE est case-insensitive, et collate les caractères accentués
*/
if(! $b) {
$where[] = sprintf('CONCAT(%s,%s) LIKE %s',
DelTk::sqlAddIfNullPourConcat($champs_n),
DelTk::sqlAddIfNullPourConcat($champs_p),
$db->proteger("%".$val."%"));
}
else {
$where[] = sprintf('(CONCAT(%1$s,%2$s) LIKE %3$s AND CONCAT(%1$s,%2$s) LIKE %4$s)',
DelTk::sqlAddIfNullPourConcat($champs_n),
DelTk::sqlAddIfNullPourConcat($champs_p),
$db->proteger("%" . $a . "%"), $db->proteger("%" . $b . "%"));
}
}
 
 
 
 
 
/**
* - Rempli le tableau des contraintes "where" et "join" nécessaire
* à la *recherche* des observations demandées ($req) utilisées par self::getIdObs()
*
* Attention, cela signifie que toutes les tables ne sont pas *forcément*
* join'ées, par exemple si aucune contrainte ne le nécessite.
* $req tel qu'il est rempli ici est utile pour récupéré la seule liste des
* id d'observation qui match.
* Pour la récupération effective de "toutes" les données correspondante, il faut
* réinitialiser $req["join"] afin d'y ajouter toutes les autres tables.
*
* Note: toujours rajouter les préfixes de table (vdi,du,doi ou di), en fonction de ce que défini
* les JOIN qui sont utilisés.
* le préfix de v_del_image est "vdi" (cf: "FROM" de self::getIdObs())
* le préfix de del_utilisateur sur id_utilisateur = vdi.ce_utilisateur est "du"
*
* @param $p les paramètres (notamment de masque) passés par l'URL et déjà traités/filtrés (sauf quotes)
* @param $req le tableau, passé par référence représentant les composants de la requête à bâtir
*/
static function sqlAddConstraint($p, $db, &$req) {
if(!empty($p['masque.auteur'])) {
// id du poster de l'obs
$req['join'][] = 'LEFT JOIN del_utilisateur AS du ON du.id_utilisateur = vdi.ce_utilisateur';
// id du poster de l'image... NON, c'est le même que le posteur de l'obs
// Cette jointure de table est ignoré ci-dessous pour les recherches d'auteurs
// $req['join'][] = 'LEFT JOIN del_utilisateur AS dui ON dui.id_utilisateur = vdi.i_ce_utilisateur';
 
if(is_numeric($p['masque.auteur'])) {
$req['where'][] = sprintf('(du.id_utilisateur = %1$d OR vdi.id_utilisateur = %1$d)', $p['masque.auteur']);
}
elseif(preg_match(';^.{5,}@[a-z0-9-.]{5,}$;i', $p['masque.auteur'])) {
$req['where'][] = sprintf('(du.courriel LIKE %1$s OR vdi.courriel LIKE %1$s )',
$db->proteger($p['masque.auteur'] . '%'));
}
else {
DelTk::addAuteursConstraint($p['masque.auteur'], $db, $req['where']);
}
}
 
if(!empty($p['masque.date'])) {
if(is_integer($p['masque.date']) && $p['masque.date'] < 2030 && $p['masque.date'] > 1600) {
$req['where'][] = sprintf("YEAR(vdi.date_observation) = %d", $p['masque.date']);
}
else {
$req['where'][] = sprintf("DATE_FORMAT(vdi.date_observation, '%%Y-%%m-%%d') = %s",
$db->proteger(strftime('%Y-%m-%d', $p['masque.date'])));
}
}
 
// TODO: avoir des champs d'entrée distinct
if(!empty($p['masque.departement'])) {
$req['where'][] = sprintf("vdi.ce_zone_geo = %s", $db->proteger('INSEE-C:'.$p['masque.departement']));
}
if(!empty($p['masque.id_zone_geo'])) {
$req['where'][] = sprintf("vdi.ce_zone_geo = %s", $db->proteger($p['masque.id_zone_geo']));
}
if(!empty($p['masque.genre'])) {
$req['where'][] = 'vdi.nom_sel LIKE '.$db->proteger('%' . $p['masque.genre'].'% %');
}
if(!empty($p['masque.famille'])) {
$req['where'][] = 'vdi.famille = '.$db->proteger($p['masque.famille']);
}
if(!empty($p['masque.ns'])) {
$req['where'][] = 'vdi.nom_sel LIKE '.$db->proteger($p['masque.ns'].'%');
}
if(!empty($p['masque.nn'])) {
$req['where'][] = sprintf('(vdi.nom_sel_nn = %1$d OR vdi.nom_ret_nn = %1$d)', $p['masque.nn']);
}
if(!empty($p['masque.referentiel'])) {
$req['where'][] = sprintf('vdi.nom_referentiel LIKE %s', $db->proteger($p['masque.referentiel'].'%'));
}
if(!empty($p['masque.commune'])) {
$req['where'][] = 'vdi.zone_geo LIKE '.$db->proteger($p['masque.commune'].'%');
}
}
 
 
 
// formatage de réponse HTTP
static function makeJSONHeader($total, $params, $url_service) {
$prev_url = $next_url = NULL;
$url_service_sans_slash = substr($url_service, 0, -1);
 
// aplatissons les params! - une seule couche cela dit, après débrouillez-vous
$params_a_plat = $params;
foreach ($params_a_plat as $cle_plate => $pap) {
if (is_array($pap)) {
$params_a_plat[$cle_plate] = implode(array_keys($pap), ',');
}
}
 
$next_offset = $params['navigation.depart'] + $params['navigation.limite'];
if($next_offset < $total) {
$next_url = $url_service_sans_slash . '?' . http_build_query(array_merge($params_a_plat, array('navigation.depart' => $next_offset)));
}
 
$prev_offset = $params['navigation.depart'] - $params['navigation.limite'];
if($prev_offset >= 0) {
$prev_url = $url_service_sans_slash . '?' . http_build_query(array_merge($params_a_plat, array('navigation.depart' => $prev_offset)));
}
 
return array(
'masque' => http_build_query(array_diff_key($params, array_flip(array('navigation.depart', 'navigation.limite')))),
'total' => $total,
'depart' => $params['navigation.depart'],
'limite' => $params['navigation.limite'],
'href.precedent' => $prev_url,
'href.suivant' => $next_url
);
}
}
/tags/v1.1-helium/services/modules/0.1/motscles/MotClePictoflora.php
New file
0,0 → 1,37
<?php
/**
* @author Raphaël Droz <raphael@tela-botanica.org>
* @author Aurélien PERONNET <aurelien@tela-botanica.org>
* @copyright Copyright (c) 2013, Tela Botanica (accueil@tela-botanica.org)
* @license Licence CECILL http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt
* @license Licence GNU-GPL http://www.gnu.org/licenses/gpl.html
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images
*/
class MotClePictoflora {
 
// cf: images/VotesImage.php
static function updateStats($db, $id_image) {
$id_image = intval($id_image);
if(!$id_image) throw new Exception("Ne peut mettre à jour les statistiques de vote",
RestServeur::HTTP_CODE_ERREUR);
 
// on utilise toujours cette table de stats (ListeImages) pour les mots-clef "actif".
$db->requeter(sprintf('UPDATE del_image_stat SET nb_tags = (select COUNT(id_tag) FROM del_image_tag WHERE ce_image = %1$d AND actif = 1) WHERE ce_image = %1$d', $id_image));
}
 
//TODO: déplacer les fonctions ci dessus et dessous dans une classe
// utilitaire
static function normaliserMotCle($str, $charset='utf-8') {
$str = htmlentities($str, ENT_NOQUOTES, $charset);
$str = preg_replace('#&([A-za-z])(?:acute|cedil|circ|grave|orn|ring|slash|th|tilde|uml);#', '\1', $str);
$str = preg_replace('#&([A-za-z]{2})(?:lig);#', '\1', $str); // pour les ligatures e.g. '&oelig;'
$str = preg_replace('#&[^;]+;#', '', $str); // supprime les autres caractères
// supprime les espaces, tirets et simple-quotes en underscores
return str_replace(array(" ", "-", "'"),
array('_', '_', '_'),
$str);
return mb_strtolower($str);
}
}
/tags/v1.1-helium/services/modules/0.1/motscles/ListeMotsCles.php
New file
0,0 → 1,184
<?php
// declare(encoding='UTF-8');
/**
* Le web service image récupère des listes de mots clés associés aux images
*
* @category php 5.2
* @package del
* @subpackage motscles
* @author Aurélien PERONNET <aurelien@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images
*/
 
class ListeMotsCles {
private $conteneur;
private $navigation;
private $masque;
private $gestionBdd;
private $bdd;
private $parametres = array();
private $ressources = array();
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_mots_cles.ini');
$this->conteneur->chargerConfiguration('config_mapping_mots_cles.ini');
$this->navigation = $conteneur->getNavigation();
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
/**
* Méthode principale de la classe.
* Lance la récupération des images dans la base et les place dans un objet ResultatService
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function consulter($ressources, $parametres) {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
// Gestion des configuration du script
$this->configurer();
$this->verifierConfiguration();
// Lancement du service
$mots_cles = $this->chargerMotsCles();
$mots_cles = $this->formaterMotsCles($mots_cles);
$total = $this->compterMotsCles();
$this->navigation->setTotal($total);
 
$resultat = new ResultatService();
$resultat->corps = array('entete' => $this->conteneur->getEntete(), 'resultats' => $mots_cles);
return $resultat;
}
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
/*-------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
--------------------------------------------------------------------------------*/
/**
* Configuration du service en fonction du fichier de config config_del.ini
* */
public function configurer() {
$this->mappingMotsCles = $this->conteneur->getParametre('mapping_mots_cles');
$this->mappingFiltre = $this->conteneur->getParametre('mapping_masque');
}
/**
* Vérifier que le service est bien configuré
* */
public function verifierConfiguration() {
 
$erreurs = array();
$tableau_mots_cles = $this->conteneur->getParametre('motscles');
if (empty($tableau_mots_cles)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [motscles] ou celui-ci est vide ;';
} else {
if ($this->conteneur->getParametre('url_service') == null) {
$erreurs[] = '- paramètre "url_service" manquant ;';
}
}
if (empty($this->mappingFiltre)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [mapping_masque] ou celui-ci est vide ;';
}
if (!empty($erreurs)) {
$e = 'Erreur lors de la configuration : '."\n";
$e .= implode("\n", $erreurs);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
/**
* Charger la clause WHERE en fonction des paramètres de masque
* */
private function chargerClauseWhere() {
$where = array();
$where[] = ' actif = 1 ';
$tableauMasque = $this->masque->getMasque();
if (!empty($tableauMasque)) {
foreach($tableauMasque as $idMasque => $valeurMasque) {
//TODO: scinder ceci en fonctions réutilisables ?
// voir si c'est interessant par rapport à la recherche générale
$idMasque = str_replace('masque.', '', $idMasque);
switch ($idMasque) {
default:
$where[] = ' '.$this->mappingFiltre[$idMasque].' = '.$this->proteger($valeurMasque);
break;
}
}
}
if (!empty($where)) {
return ' WHERE '.implode('AND', $where);
} else {
return;
}
}
/*-------------------------------------------------------------------------------
CHARGEMENT DES MOTS CLES
--------------------------------------------------------------------------------*/
/**
* Chargement depuis la bdd de tous les mots clés
* */
private function chargerMotsCles() {
$requeteLiaisons = 'SELECT DISTINCT SQL_CALC_FOUND_ROWS * '.
'FROM '.$this->gestionBdd->formaterTable('del_image_tag', 'dit');
$requeteLiaisons .= $this->chargerClauseWhere();
return $this->bdd->recupererTous($requeteLiaisons);
}
/**
* Compter le nombre total de mots clés dans la base pour affichage dans en tete.
* */
private function compterMotsCles() {
$requete = 'SELECT FOUND_ROWS() AS nbre ';
$resultats = $this->bdd->recuperer($requete);
return (int) $resultats['nbre'];
}
/*-------------------------------------------------------------------------------
FORMATER ET METTRE EN FORME
--------------------------------------------------------------------------------*/
/**
* Formater les mots clés
* @param $mots clés les mots clés à mettre à jour
* @return $mots clés les mots clés mis à jour
* */
private function formaterMotsCles($mots_cles) {
$retour = array();
foreach ($mots_cles as $id => $mot_cle) {
$mapping = array();
foreach ($this->mappingMotsCles as $nomOriginal => $nomFinal) {
$mapping[$nomFinal] = $mot_cle[$nomOriginal];
}
$retour[$mot_cle['id_tag']] = $mapping;
}
return $retour;
}
private function proteger($valeur) {
if (is_array($valeur)) {
return $this->bdd->protegerTableau($valeur);
} else {
return $this->bdd->proteger($valeur);
}
}
}
?>
/tags/v1.1-helium/services/modules/0.1/motscles/SupprimerMotCle.php
New file
0,0 → 1,110
<?php
// declare(encoding='UTF-8');
/**
* Supprime un mot clé par son identifiant
*
* @category php 5.2
* @package del
* @subpackage images
* @author Aurélien PERONNET <aurelien@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images
*/
 
require_once('MotClePictoflora.php');
 
class SupprimerMotCle {
private $conteneur;
private $navigation;
private $masque;
private $gestionBdd;
private $bdd;
private $parametres = array();
private $ressources = array();
private $motCleId;
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->navigation = $conteneur->getNavigation();
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
/**
* Supprime un mot-clé si les objets fournis en paramètres sont valides
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function supprimer($ressources, $parametres) {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
// Gestion des configuration du script
$this->verifierConfiguration();
$insertion = $this->supprimerMotCle($this->motCleId);
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
return $resultat;
}
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
/*-------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
--------------------------------------------------------------------------------*/
/**
* Vérifier que le service est bien configuré
* */
public function verifierConfiguration() {
$erreurs = array();
if (!isset($this->ressources[0])) {
$erreurs[] = ' - impossible de supprimer un mot clé sans l\'identifiant associé ;';
} else if(!is_numeric($this->ressources[0])) {
$erreurs[] = ' - l\'identifiant de mot clé doit être un entier ;';
}
if (!empty($erreurs)) {
$e = 'Erreur de configuration :';
$e = implode("\n", $erreurs);
echo var_dump($e);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
} else {
$this->motCleId = $this->ressources[0];
}
}
/*-------------------------------------------------------------------------------
SUPPRESSION DES MOTS CLES
--------------------------------------------------------------------------------*/
/**
* Supprime un mot clé dans la table
* @param $id_mot_cle string identifiant de mot clé
* */
private function supprimerMotCle($id_mot_cle) {
$retour = $this->bdd->requeter(sprintf('UPDATE del_image_tag '.
'SET actif = 0, date_modification = NOW() '.
'WHERE id_tag = %d',
intval($id_mot_cle)));
 
if ($retour == null) {
$e = 'Erreur inopinée lors de la suppression';
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
 
MotClePictoflora::updateStats($this->bdd, $id_mot_cle);
return null;
}
}
?>
/tags/v1.1-helium/services/modules/0.1/motscles/AjouterMotCle.php
New file
0,0 → 1,134
<?php
// declare(encoding='UTF-8');
/**
* Ajoute un mot clé en l'associant à un identifiant d'image
*
* @category php 5.2
* @package del
* @subpackage images
* @author Aurélien PERONNET <aurelien@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images
*/
 
require_once('MotClePictoflora.php');
 
class AjouterMotCle {
private $conteneur;
private $navigation;
private $masque;
private $gestionBdd;
private $bdd;
private $parametres = array();
private $ressources = array();
private $commentaire;
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->navigation = $conteneur->getNavigation();
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
/**
* Ajoute un mot-clé si les objets fournis en paramètres sont valides
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function ajouter($ressources, $parametres) {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
// Gestion des configuration du script
$this->verifierConfiguration();
$insertion = $this->insererMotCle($this->parametres);
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
$resultat->corps = array('id_mot_cle' => $insertion);
return $resultat;
}
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
/*-------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
--------------------------------------------------------------------------------*/
/**
* Vérifier que le service est bien configuré
* */
public function verifierConfiguration() {
$erreurs = array();
if (!isset($this->parametres['image'])) {
$erreurs[] = ' - impossible d\'ajouter un mot clé sans image associée ;';
} else if(!is_numeric($this->parametres['image'])) {
$erreurs[] = ' - l\'identifiant d\'image doit être un entier ;';
}
if (!isset($this->parametres['mot_cle'])) {
$erreurs[] = ' - impossible d\'ajouter un mot clé sans le mot clé ;';
}
if (!isset($this->parametres['auteur.id'])) {
$erreurs[] = ' - impossible d\'ajouter un mot clé sans auteur associé ;';
}
if (!empty($erreurs)) {
$e = 'Erreur de configuration :';
$e = implode("\n", $erreurs);
echo var_dump($e);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
/*-------------------------------------------------------------------------------
INSERTION DES MOTS CLES
--------------------------------------------------------------------------------*/
/**
* Insère un mot clé dans la table
* @param $mot_cle array la liste des paramètres
* */
private function insererMotCle($mot_cle) {
$id_image = intval($mot_cle['image']);
$id_auteur = $mot_cle['auteur.id'];
$mots_cles = explode(",", $mot_cle['mot_cle']);
array_walk($mots_cles, create_function('&$val', '$val = trim($val);'));
 
$valeurs_a_inserer = array();
foreach ($mots_cles as $mot_cle_a_inserer) {
$mot_cle_normalise = MotClePictoflora::normaliserMotCle($mot_cle_a_inserer);
$valeurs_a_inserer[] = sprintf('(%d, %s, %s, %s, NOW(), 1, NOW())',
$id_image,
$this->bdd->proteger($id_auteur),
$this->bdd->proteger(trim($mot_cle_a_inserer)),
$this->bdd->proteger($mot_cle_normalise));
}
 
$retour = $this->bdd->requeter(sprintf(
'INSERT INTO del_image_tag (ce_image, ce_utilisateur, tag, tag_normalise, date, actif, date_modification) VALUES %s ',
implode(",", $valeurs_a_inserer)));
 
if ($retour == null) {
$e = 'Erreur inopinée lors de l\insertion';
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
 
MotClePictoflora::updateStats($this->bdd, $mot_cle['image']);
//TODO: voir si cela a vraiment du sens lors de l'ajout de plusieurs mots clés
return null;
}
 
}
?>
/tags/v1.1-helium/services/modules/0.1/Images.php
New file
0,0 → 1,254
<?php
/**
* Description :
* Classe principale de chargement des services d'eFlore.
*
* Encodage en entrée : utf8
* Encodage en sortie : utf8
* @package eflore-projets
* @author Jennifer DHÉ <jennifer.dhe@tela-botanica.org>
* @author Delphine CAUQUIL <delphine@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version 0.1
* @copyright 1999-2011 Tela Botanica (accueil@tela-botanica.org)
*/
class Images extends RestService {
 
/*
* url possibles :
* http://localhost/del/services/0.1/images/ => toutes les images, appel à la classe ListeImages
* http://localhost/del/services/0.1/images/#id => une image donnée => en test pour remplacer les appels à eflore/cel
* http://localhost/del/services/0.1/images/#id/votes/ => tous les votes d'une image classés par protocole
* http://localhost/del/services/0.1/images/#id/votes/protocole/#id => tous les votes d'une image et d'un protocole donné
* http://localhost/del/services/0.1/images/#id/votes/#id => un vote donné pour une image donnée.
* */
private $parametres = array();
private $ressources = array();
private $methode = null;
private $projetNom = array();
private $serviceNom = array();
private $cheminCourant = null;
 
private $conteneur;
/** Indique si oui (true) ou non (false), on veut utiliser les paramètres bruts. */
protected $utilisationParametresBruts = true;
 
public function __construct() {
$this->cheminCourant = dirname(__FILE__).DS;
}
 
public function consulter($ressources, $parametres) {
$this->methode = 'consulter';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
$reponseHttp->setResultatService($resultat);
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
}
$reponseHttp->emettreLesEntetes();
$corps = $reponseHttp->getCorps();
return $corps;
}
public function ajouter($ressources, $requeteDonnees) {
$this->methode = 'ajouter';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $requeteDonnees);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
$reponseHttp->setResultatService($resultat);
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
}
$corps = $reponseHttp->getCorps();
return $corps;
}
public function modifier($ressources, $requeteDonnees) {
$this->methode = 'modifier';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $requeteDonnees);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
$reponseHttp->emettreLesEntetes();
echo $reponseHttp->getCorps();
}
}
public function supprimer($ressources) {
$requeteDonnees = array();
$this->methode = 'supprimer';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $requeteDonnees);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
$reponseHttp->emettreLesEntetes();
echo $reponseHttp->getCorps();
}
}
 
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function traiterRessources() {
$retour = '';
$this->initialiserProjet();
if ($this->avoirRessourceService()) {
$retour = $this->initialiserService();
}
return $retour;
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU PROJET
------------------------------------------------------------------------------------------------------------------*/
private function initialiserProjet() {
$this->chargerNomDuProjet();
$this->chargerConfigProjet();
 
}
 
private function chargerNomDuProjet() {
$this->projetNom = 'images';
}
 
private function chargerConfigProjet() {
$projet = $this->projetNom;
$chemin = Config::get('chemin_configurations')."config_$projet.ini";
Config::charger($chemin);
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
------------------------------------------------------------------------------------------------------------------*/
private function avoirRessourceService() {
/*
* url possibles :
* http://localhost/del/services/0.1/images/ => toutes les images, appel à la classe ListeImages
* http://localhost/del/services/0.1/images/#id => une image donnée => en test pour remplacer les appels à eflore/cel
* http://localhost/del/services/0.1/images/#id/votes/ => tous les votes d'une image classés par protocole
* http://localhost/del/services/0.1/images/#id/votes/protocole/#id => tous les votes d'une image et d'un protocole donné
* http://localhost/del/services/0.1/images/#id/votes/#id => un vote donné pour une image donnée.
* */
$presenceRessourceService = false;
if (isset($this->ressources[0])) {
if ($this->etreRessourceIdentifiant(0)) {
if (isset($this->ressources[1])) {
$presenceRessourceService = $this->avoirRessourceSousService();
} else {
$presenceRessourceService = true;
$this->serviceNom = 'liste-images';
}
}
} else {
$presenceRessourceService = true;
$this->serviceNom = 'liste-images';
}
return $presenceRessourceService;
}
private function avoirRessourceSousService() {
// TODO: utilité de votes-image et vote-image ?
// TODO: cette fonction est ignoble, la simplifier
$presenceRessourceService = false;
if (sizeof($this->ressources) >= 2) {
if ($this->ressources[1] == 'votes') {
$presenceRessourceService = true;
$this->serviceNom = 'votes-image';
} else {
$this->editerMessageErreurRessource();
}
} else {
if (isset($this->ressources[2]) && $this->etreRessourceIdentifiant(2)) {
$presenceRessourceService = true;
$this->serviceNom = 'vote-image';
} else {
$this->editerMessageErreurRessource();
}
}
return $presenceRessourceService;
}
private function editerMessageErreurRessource() {
$message = "Le service demandé '".$this->projetNom.'/'.implode('/', $this->ressources).
"' n'est pas disponible pour le projet ".$this->projetNom." !\n".
"Les services disponibles sont : images, images/#id/votes, images/#id/vote/#id_vote";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
private function etreRessourceIdentifiant($num) {
$presenceId = false;
if (is_numeric($this->ressources[$num])) {
$presenceId = true;
} else {
$message = "Le service demandé '$service' nécessite d'avoir un identifiant d'image valide";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
return $presenceId;
}
 
private function initialiserService() {
//$this->chargerNomDuService();
$classe = $this->obtenirNomClasseService($this->serviceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->projetNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
$this->conteneur->chargerConfiguration('config_'.$this->projetNom.'.ini');
require_once $chemin;
$service = new $classe($this->conteneur);
if ($this->methode == 'consulter') {
$retour = $service->consulter($this->ressources, $this->parametres);
} elseif ($this->methode == 'ajouter') {
$retour = $service->ajouter($this->ressources, $this->parametres);
} elseif ($this->methode == 'modifier') {
$retour = $service->modifier($this->ressources, $this->parametres);
} elseif ($this->methode == 'supprimer') {
$retour = $service->supprimer($this->ressources);
}
}
}
if (is_null($service)) {
$message = "Le service demandé '{$this->serviceNom}' n'existe pas dans le projet {$this->projetNom} !";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
return $retour;
}
 
private function obtenirNomClasseService($mot) {
$classeNom = str_replace(' ', '', ucwords(strtolower(str_replace('-', ' ', $mot))));
return $classeNom;
}
}
?>
/tags/v1.1-helium/services/modules/0.1/utilisateurs/Deconnecter.php
New file
0,0 → 1,36
<?php
// declare(encoding='UTF-8');
/**
* Le web service observations récupère toutes les observations et, pour chacune d'elle, les
* images qui lui sont associées.
*
* @category php 5.2
* @package del
* @subpackage images
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Observations
*/
 
class Deconnecter extends gestionUtilisateur {
/**
* Méthode principale de la classe.
* Lance la récupération des images dans la base et les place dans un objet ResultatService
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function consulter($ressources, $parametres) {
// supprimer cookie & session
$this->oublierUtilisateur();
// renvoyer identification anonyme
$utilisateur = $this->getUtilisateurAnonyme();
return $utilisateur;
}
}
?>
/tags/v1.1-helium/services/modules/0.1/utilisateurs/Connecter.php
New file
0,0 → 1,50
<?php
// declare(encoding='UTF-8');
/**
* Le web service observations récupère toutes les observations et, pour chacune d'elle, les
* images qui lui sont associées.
*
* @category php 5.2
* @package del
* @subpackage images
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Observations
*/
 
class Connecter extends gestionUtilisateur {
/**
* Méthode principale de la classe.
* Lance la récupération des images dans la base et les place dans un objet ResultatService
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function consulter($ressources, $parametres) {
$login = $ressources[0];
$motDePasse = $ressources[1];
$utilisateur = $this->identifierUtilisateur($login, $motDePasse);
$utilisateur = $this->verifierUtilisateur($utilisateur);
$utilisateur = $this->setUtilisateur($utilisateur);
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
$resultat->corps = $utilisateur;
return $resultat;
}
private function verifierUtilisateur($utilisateur) {
if ($utilisateur == null || sizeof($utilisateur) == 0 || sizeof($utilisateur) > 1) {
$e = 'Accès non autorisé';
throw new Exception($e, RestServeur::HTTP_CODE_ACCES_NON_AUTORISE);
} else {
return $utilisateur[0];
}
}
}
?>
/tags/v1.1-helium/services/modules/0.1/utilisateurs/IdentificationAnonyme.php
New file
0,0 → 1,42
<?php
// declare(encoding='UTF-8');
/**
* Le web service observations récupère toutes les observations et, pour chacune d'elle, les
* images qui lui sont associées.
*
* @category php 5.2
* @package del
* @subpackage images
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Observations
*/
 
class IdentificationAnonyme extends gestionUtilisateur {
/**
* Méthode principale de la classe.
* Lance la récupération des images dans la base et les place dans un objet ResultatService
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function consulter($ressources, $parametres) {
$utilisateur = $this->getUtilisateurAnonyme();
$utilisateurParCookie = $this->utilisateurEstIdentifie();
if ($utilisateurParCookie != null) {
$utilisateurParCookie['connecte'] = true;
$utilisateur = $utilisateurParCookie;
}
$resultat = new ResultatService();
$resultat->corps = $utilisateur;
return $resultat;
}
}
?>
/tags/v1.1-helium/services/modules/0.1/utilisateurs/Preferences.php
New file
0,0 → 1,112
<?php
// declare(encoding='UTF-8');
/**
* Web service de gestion des préférences utilisateur
*
* @category php 5.2
* @package del
* @subpackage images
* @author Aurélien PERONNET <aurelien@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Observations
*/
 
class Preferences {
private $conteneur;
private $gestionBdd;
private $bdd;
public function __construct(Conteneur $conteneur = null) {
session_start();
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_utilisateurs.ini');
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
/**
* Renvoie les préférences utilisateurs
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function consulter($ressources, $parametres) {
$id_utilisateur = $ressources[0];
$prefs = $this->obtenirPreferencesUtilisateur($id_utilisateur);
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
$resultat->corps = $prefs;
return $resultat;
}
/**
* Méthode principale de la classe.
* Modifie les préférences utilisateurs
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés dans le post
* */
public function modifier($ressources, $parametres) {
$id_utilisateur = $ressources[0];
$prefs = $this->modifierPreferencesUtilisateur($id_utilisateur, $parametres);
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
$resultat->corps = $prefs;
return $resultat;
}
private function obtenirPreferencesUtilisateur($id_utilisateur) {
$requete = 'SELECT * FROM del_utilisateur_infos WHERE id_utilisateur = '.$this->bdd->proteger($id_utilisateur);
$prefs_utilisateur = $this->bdd->recupererTous($requete);
if(empty($prefs_utilisateur)) {
$this->initialiserInfosUtilisateur($id_utilisateur);
$prefs_utilisateur = $this->renvoyerInfosUtilisateurDefaut($id_utilisateur);
} else {
$prefs_utilisateur = $prefs_utilisateur[0];
$prefs_utilisateur['preferences'] = json_decode($prefs_utilisateur['preferences']);
$prefs_utilisateur['admin'] = $prefs_utilisateur['admin'];
}
return $prefs_utilisateur;
}
private function modifierPreferencesUtilisateur($id_utilisateur, $prefs) {
$requete = 'UPDATE del_utilisateur_infos '.
'SET preferences = '.$this->bdd->proteger(json_encode($prefs)).' '.
'WHERE id_utilisateur = '.$this->bdd->proteger($id_utilisateur);
$resultat = $this->bdd->requeter($requete);
return $resultat;
}
private function initialiserInfosUtilisateur($id_utilisateur) {
$preferences_defaut = $this->obtenirTableauPreferenceDefaut();
$requete = 'INSERT INTO del_utilisateur_infos '.
'(id_utilisateur, admin, preferences, date_premiere_utilisation )'.
'VALUES '.
"(".$this->bdd->proteger($id_utilisateur).", 0, ".$this->bdd->proteger(json_encode($preferences_defaut)).", NOW()) ".
'ON DUPLICATE KEY UPDATE date_premiere_utilisation = NOW() ';
$resultat = $this->bdd->requeter($requete);
return $resultat;
}
private function renvoyerInfosUtilisateurDefaut($id_utilisateur) {
return array('id_utilisateur' => $id_utilisateur,
'admin' => "0",
'preferences' => $this->obtenirTableauPreferenceDefaut(),
'date_premiere_utilisation' => date('Y-m-d H:i:s'));
}
private function obtenirTableauPreferenceDefaut() {
return array('mail_notification_mes_obs' => "1",
'mail_notification_toutes_obs' => "0");
}
}
?>
/tags/v1.1-helium/services/modules/0.1/Nomstaxons.php
New file
0,0 → 1,122
<?php
/**
* Description :
* Classe principale de chargement des services d'eFlore.
*
* Encodage en entrée : utf8
* Encodage en sortie : utf8
* @package eflore-projets
* @author Jennifer DHÉ <jennifer.dhe@tela-botanica.org>
* @author Delphine CAUQUIL <delphine@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version 0.1
* @copyright 1999-2011 Tela Botanica (accueil@tela-botanica.org)
*/
class Nomstaxons extends RestService {
 
private $parametres = array();
private $ressources = array();
private $methode = null;
private $projetNom = array();
private $serviceNom = array();
private $cheminCourant = null;
 
private $conteneur;
/** Indique si oui (true) ou non (false), on veut utiliser les paramètres bruts. */
protected $utilisationParametresBruts = true;
 
public function __construct() {
$this->cheminCourant = dirname(__FILE__).DS;
}
 
public function consulter($ressources, $parametres) {
$this->methode = 'consulter';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
$reponseHttp->setResultatService($resultat);
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
}
$reponseHttp->emettreLesEntetes();
$corps = $reponseHttp->getCorps();
return $corps;
}
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function traiterRessources() {
$retour = '';
$this->initialiserProjet();
$retour = $this->initialiserService();
return $retour;
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU PROJET
------------------------------------------------------------------------------------------------------------------*/
private function initialiserProjet() {
$this->projetNom = 'nomstaxons';
$this->chargerConfigProjet();
}
 
private function chargerConfigProjet() {
$projet = $this->projetNom;
$chemin = Config::get('chemin_configurations')."config_$projet.ini";
Config::charger($chemin);
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
------------------------------------------------------------------------------------------------------------------*/
private function initialiserService() {
$this->chargerNomService();
$classe = $this->obtenirNomClasseService($this->serviceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->projetNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
$this->conteneur->chargerConfiguration('config_'.$this->projetNom.'.ini');
require_once $chemin;
$service = new $classe($this->conteneur);
if ($this->methode == 'consulter') {
$retour = $service->consulter($this->ressources, $this->parametres);
} else {
//TODO : throw exception
}
}
}
if (is_null($service)) {
$message = "Le service demandé '{$this->serviceNom}' n'existe pas dans le projet {$this->projetNom} !";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
return $retour;
}
private function chargerNomService() {
// si la méthode est POST, on ajouter un commentaire
$this->serviceNom = 'liste-taxons';
}
 
private function obtenirNomClasseService($mot) {
$classeNom = str_replace(' ', '', ucwords(strtolower(str_replace('-', ' ', $mot))));
return $classeNom;
}
}
?>
/tags/v1.1-helium/services/modules/0.1/Observations.php
New file
0,0 → 1,222
<?php
/**
* Description :
* Classe principale de chargement des services d'eFlore.
*
* Encodage en entrée : utf8
* Encodage en sortie : utf8
* @package eflore-projets
* @author Jennifer DHÉ <jennifer.dhe@tela-botanica.org>
* @author Delphine CAUQUIL <delphine@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version 0.1
* @copyright 1999-2011 Tela Botanica (accueil@tela-botanica.org)
*/
class Observations extends RestService {
 
/*
* url possibles :
* http://localhost/del/services/0.1/observations/ => toutes les observations (infos obs, infos images, infos propositions, infos nb commentaires)
* http://localhost/del/services/0.1/observations/#id => une observation donnée et ses images, SANS LES propositions & nombre de commentaire
* */
private $parametres = array();
private $ressources = array();
private $methode = null;
private $projetNom = array();
private $serviceNom = array();
private $cheminCourant = null;
 
private $conteneur;
/** Indique si oui (true) ou non (false), on veut utiliser les paramètres bruts. */
protected $utilisationParametresBruts = true;
 
public function __construct() {
$this->cheminCourant = dirname(__FILE__).DS;
}
 
public function consulter($ressources, $parametres) {
$this->methode = 'consulter';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
$reponseHttp->setResultatService($resultat);
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
}
$reponseHttp->emettreLesEntetes();
$corps = $reponseHttp->getCorps();
return $corps;
}
public function ajouter($ressources, $requeteDonnees) {
$this->methode = 'ajouter';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $requeteDonnees);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
$reponseHttp->emettreLesEntetes();
}
}
public function modifier($ressources, $requeteDonnees) {
$this->methode = 'modifier';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $requeteDonnees);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
$reponseHttp->emettreLesEntetes();
}
}
 
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function traiterRessources() {
$retour = '';
$this->initialiserProjet();
if ($this->avoirRessourceService()) {
$retour = $this->initialiserService();
}
return $retour;
}
private function avoirRessourceIdentifiant($num) {
$presenceId = false;
if (is_numeric($this->ressources[$num])) {
$presenceId = true;
} else {
$message = "Le service demandé '$service' nécessite d'avoir un identifiant d'image valide";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
return $presenceId;
}
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU PROJET
------------------------------------------------------------------------------------------------------------------*/
private function initialiserProjet() {
$this->chargerNomDuProjet();
$this->chargerConfigProjet();
 
}
 
private function chargerNomDuProjet() {
$this->projetNom = 'observations';
}
 
private function chargerConfigProjet() {
$projet = $this->projetNom;
$chemin = Config::get('chemin_configurations')."config_$projet.ini";
Config::charger($chemin);
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
------------------------------------------------------------------------------------------------------------------*/
private function avoirRessourceService() {
/*
* url possibles :
* http://localhost/del/services/0.1/observations/ => toutes les observations (infos obs, infos images, infos propositions, infos nb commentaires)
* http://localhost/del/services/0.1/observations/#id => une observation donnée et ses images, SANS LES propositions & nombre de commentaire
* */
$presenceRessourceService = false;
if (isset($this->ressources[0])) {
if ($this->avoirRessourceIdentifiant(0)) {
if (sizeof($this->ressources) == 1) {
$presenceRessourceService = true;
$this->serviceNom = 'observation';
} else {
if (isset($this->ressources[1])) {
$presenceRessourceService = $this->avoirRessourceSousService();
}
}
}
} else {
if (isset($this->parametres['retour.format']) && $this->parametres['retour.format'] == 'widget') {
$this->methode = 'consulter';
$presenceRessourceService = true;
$this->serviceNom = 'liste-observations-widget';
} else {
$presenceRessourceService = true;
$this->serviceNom = 'liste-observations';
}
}
return $presenceRessourceService;
}
private function avoirRessourceSousService() {
$presenceRessourceService = false;
$servicesDispo = Outils::recupererTableauConfig('servicesDispo');
if ($this->avoirRessourceIdentifiant(1)) {
$service = $this->ressources[2];
if (in_array($service, $servicesDispo)) {
$presenceRessourceService = true;
$this->serviceNom = 'vote-observation';
} else {
$message = "Le service demandé '$service' n'est pas disponible pour le projet {$this->projetNom} !\n".
"Les services disponibles sont : ".implode(', ', $servicesDispo);
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
}
return $presenceRessourceService;
}
 
private function initialiserService() {
//$this->chargerNomDuService();
$classe = $this->obtenirNomClasseService($this->serviceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->projetNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
$this->conteneur->chargerConfiguration('config_'.$this->projetNom.'.ini');
require_once $chemin;
$service = new $classe($this->conteneur);
if ($this->methode == 'consulter') {
$retour = $service->consulter($this->ressources, $this->parametres);
} elseif ($this->methode == 'ajouter') {
$retour = $service->ajouter($this->ressources, $this->parametres);
} elseif ($this->methode == 'modifier') {
$retour = $service->modifier($this->ressources, $this->parametres);
}
}
}
if (is_null($service)) {
$message = "Le service demandé '{$this->serviceNom}' n'existe pas dans le projet {$this->projetNom} !";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
return $retour;
}
 
private function obtenirNomClasseService($mot) {
$classeNom = str_replace(' ', '', ucwords(strtolower(str_replace('-', ' ', $mot))));
return $classeNom;
}
 
 
}
?>
/tags/v1.1-helium/services/modules/0.1/images/ListeImages2.php
New file
0,0 → 1,643
<?php
/**
* @author Raphaël Droz <raphael@tela-botanica.org>
* @copyright Copyright (c) 2013, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images
* @see http://www.tela-botanica.org/wikini/identiplante/wakka.php?wiki=IdentiPlante_PictoFlora_MoteurRecherche
*
* Backend pour PictoFlora (del.html#page_recherche_images)
*
*
* == Notes ==
*
* tri=votes et tri=tags: affectent le choix des images affichées (donc getIdImages())
* Cependant ce total ne nous intéresse même pas (MoyenneVotePresenteur.java s'en occupe).
* Seul tri=date_transmission nous évite l'AVG() + GROUP BY
*
* protocole: il affecte l'affichage des information, mais le JSON contient déjà
* l'intégralité (chercher les données de vote pour 1 ou plusieurs protocoles) est quasi-identique.
* Par contre, le tri par moyenne des votes, sous-entend "pour un protocole donné".
* Dès lors le choix d'un protocole doit avoir été fait afin de régler le JOIN et ainsi l'ORDER BY.
* (cf requestFilterParams())
*
* Histoire: auparavant (pré-r142x) un AVG + GROUP BY étaient utilisés pour générer on-the-fly les valeurs
* utilisées ensuite pour l'ORDER BY. La situation à base de del_image_stat
* est déjà bien meilleure sans être pour autant optimale. cf commentaire de sqlAddConstraint()
*
*
* Tags:
* Le comportement habituel dans le masque *général*: les mots sont séparés par des espaces,
* implod()ed par des AND (tous les mots doivent matcher).
* Et le test effectué doit matcher sur:
* %(les tags d'observations)% *OU* %(les tags d'images)% *OU* %(les tags publics)%
*
* Le comportement habituel dans le masque *tag*: les mots ne sont *pas* splittés (1 seule expression),
* Et le test effectué doit matcher sur:
* ^(expression)% *OU* %(expression)% [cf getConditionsImages()]
*
* Par défaut les tags sont comma-separated (OU logique).
* Cependant pour conserver le comportement du masque général qui sous-entend un ET logique sur
* des tags séparés par des espaces recherche
*
* TODO:
* -affiner la gestion de passage de mots-clefs dans le masque général.
* - subqueries dans le FROM pour les critère WHERE portant directement sur v_del_image
* plutôt que dans WHERE (qui nécessite dès lors un FULL-JOIN)
* (http://www.mysqlperformanceblog.com/2007/04/06/using-delayed-join-to-optimize-count-and-limit-queries/)
* - éviter de dépendre d'une jointure systématique sur `cel_obs`, uniquement pour `(date_)transmission
* (cf VIEW del_image)
* - poursuivre la réorganisation des méthodes statiques parmis Observation, ListeObservations et ListeImages2
* - *peut-être*: passer requestFilterParams() en méthode de classe
*
*
* MySQL sux:
* EXPLAIN SELECT id_image FROM v_del_image vdi WHERE vdi.id_image IN (SELECT ce_image FROM del_image_tag WHERE actif = 1 LIMIT 1);
* MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery
* EXPLAIN SELECT * FROM del_image WHERE id_image IN (SELECT 3);
* PRIMARY
* EXPLAIN SELECT * FROM del_image WHERE id_image IN (SELECT MIN(3));
* DEPENDENT SUBQUERY ... ... ... mwarf !
* EXPLAIN SELECT id_image FROM v_del_image vdi WHERE vdi.id_image IN (SELECT ce_image FROM del_image_tag WHERE actif = 1);
* 5.5: MATERIALIZED del_image_tag ALL ce_image NULL NULL NULL 38276 Using where
* 5.1: DEPENDENT SUBQUERY del_image_tag index_subquery ce_image ce_image 8 func 1 Using where
* FORCE INDEX/IGNORE INDEX semble incapable de résoudre le problème de l'optimiseur MySQL
*
*/
 
require_once(dirname(__FILE__) . '/../DelTk.php');
require_once(dirname(__FILE__) . '/../observations/Observation.php');
restore_error_handler();
restore_exception_handler();
error_reporting(E_ALL);
 
// del/services/0.1/images?navigation.depart=0&navigation.limite=12&tri=votes&ordre=desc
// del/services/0.1/images?navigation.depart=0&navigation.limite=12&tri=votes&ordre=desc&masque=plop
// del/services/0.1/images?navigation.depart=0&navigation.limite=12&tri=votes&ordre=desc&protocole=3
// del/services/0.1/images?navigation.depart=0&navigation.limite=12&tri=votes&ordre=desc&protocole=3&masque=plop
 
class ListeImages2 {
 
// TODO: PHP-x.y, ces variables devrait être des "const"
static $format_image_possible = array('O','CRX2S','CRS','CXS','CS','XS','S','M','L','XL','X2L','X3L');
 
static $tri_possible = array('date_transmission', 'date_observation', 'votes', 'tags');
 
// en plus de ceux dans DelTk
static $parametres_autorises = array('protocole', 'masque.tag_cel', 'masque.tag_pictoflora', 'masque.milieu');
 
static $default_params = array('navigation.depart' => 0, 'navigation.limite' => 10,
'tri' => 'date_transmission', 'ordre' => 'desc',
// spécifiques à PictoFlora:
'format' => 'XL');
 
static $default_proto = 3; // proto par défaut: capitalisation d'img (utilisé uniquement pour tri=(tags|votes))
 
static $mappings = array(
'observations' => array( // v_del_image
"id_observation" => 1,
"date_observation" => 1,
"date_transmission" => 1,
"famille" => "determination.famille",
"nom_sel" => "determination.ns",
"nom_sel_nn" => "determination.nn",
"nom_referentiel" => "determination.referentiel",
"nt" => "determination.nt",
"ce_zone_geo" => "id_zone_geo",
"zone_geo" => 1,
"lieudit" => 1,
"station" => 1,
"milieu" => 1,
"mots_cles_texte" => "mots_cles_texte",
"commentaire" => 1,
"ce_utilisateur" => "auteur.id",
"nom_utilisateur" => "auteur.nom",
"prenom_utilisateur" => "auteur.prenom",
),
'images' => array( // v_del_image
'id_image' => 1,
// l'alias suivant est particulier: in-fine il doit s'appeler mots_cles_texte
// mais nous afin d'éviter un conflit d'alias nous le renommons plus tard (reformateImagesDoubleIndex)
'i_mots_cles_texte' => 1
));
 
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_images.ini');
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
 
public function consulter($ressources, $parametres) {
/* Certes nous sélectionnons ici (nom|prenom|courriel)_utilisateur de cel_obs, mais il ne nous intéressent pas
Par contre, ci-dessous nous prenons i_(nom|prenom|courriel)_utilisateur.
Notons cependant qu'aucun moyen ne devrait permettre que i_*_utilisateur != *_utilisateur
Le propriétaire d'une obs et de l'image associée est *toujours* le même. */
array_walk(self::$mappings['observations'], create_function('&$val, $k', 'if($val==1) $val = $k;'));
array_walk(self::$mappings['images'], create_function('&$val, $k', 'if($val==1) $val = $k;'));
// pour les votes, les mappings de "Observation" nous suffisent
array_walk(Observation::$mappings['votes'], create_function('&$val, $k', 'if($val==1) $val = $k;'));
 
// la nécessité du 'groupby' dépend des 'join's utilisés (LEFT ou INNER) ainsi que de la cardinalité
// de `ce_image` dans ces tables jointes.
// Contrairement à IdentiPlantes, nous n'avons de HAVING pour PictoFlora, mais par contre un ORDER BY
$req = array('select' => array(), 'join' => array(), 'where' => array(), 'groupby' => array(), 'orderby' => array());
 
 
$db = $this->bdd;
 
// filtrage de l'INPUT général, on réutilise 90% de identiplante en terme de paramètres autorisés
// ($parametres_autorises) sauf... masque.type qui fait des modif' de WHERE sur les mots-clefs.
// Évitons ce genre de chose pour PictoFlora et les risques de conflits avec masque.tag
// même si ceux-ci sont improbables (pas d'<input> pour cela).
$params_ip = DelTk::requestFilterParams($parametres,
array_diff(DelTk::$parametres_autorises,
array('masque.type')),
$this->conteneur);
 
// notre propre filtrage sur l'INPUT
$params_pf = self::requestFilterParams($parametres,
array_merge(DelTk::$parametres_autorises,
self::$parametres_autorises));
 
/* filtrage des tags + sémantique des valeurs multiples:
Lorsqu'on utilise masque.tag* pour chercher des tags, ils sont
postulés comme séparés par des virgule, et l'un au moins des tags doit matcher. */
$params_pf['masque.tag_cel'] = DelTk::buildTagsAST(@$parametres['masque.tag_cel'], 'OR', ',');
$params_pf['masque.tag_pictoflora'] = DelTk::buildTagsAST(@$parametres['masque.tag_pictoflora'], 'OR', ',');
 
$params = array_merge(
DelTk::$default_params, // paramètre par défaut Identiplante
self::$default_params, // paramètres par défaut PictoFlora
$params_ip, // les paramètres passés, traités par Identiplante
$params_pf); // les paramètres passés, traités par PictoFlora
 
// XXX: temp tweak
/* $this->conteneur->setParametre('url_images', sprintf($this->conteneur->getParametre('images.url_images'),
"%09d", $params['format']));*/
 
// création des contraintes (génériques de DelTk)
DelTk::sqlAddConstraint($params, $db, $req);
// création des contraintes spécifiques (sur les tags essentiellement)
self::sqlAddConstraint($params, $db, $req, $this->conteneur);
// création des contraintes spécifiques impliquées par le masque général
self::sqlAddMasqueConstraint($params, $db, $req, $this->conteneur);
// l'ORDER BY s'avére complexe
self::sqlOrderBy($params, $db, $req);
 
// 1) grunt-work: *la* requête de récupération des id valides (+ SQL_CALC_FOUND_ROWS)
// $idobs_tab = ListeObservations::getIdObs($params, $req, $db);
$idobs_tab = self::getIdImages($params, $req, $db);
 
// Ce n'est pas la peine de continuer s'il n'y a pas eu de résultats dans la table del_obs_images
if(!$idobs_tab) {
$resultat = new ResultatService();
$resultat->corps = array('entete' => DelTk::makeJSONHeader(0, $params, Config::get('url_service')),
'resultats' => array());
return $resultat;
/*
header('HTTP/1.0 404 Not Found');
// don't die (phpunit)
throw(new Exception()); */
}
 
 
// idobs est une liste (toujours ordonnée) des id d'observations recherchées
$idobs = array_values(array_map(create_function('$a', 'return $a["id_image"];'), $idobs_tab));
$total = $db->recuperer('SELECT FOUND_ROWS() AS c'); $total = intval($total['c']);
 
$liaisons = self::chargerImages($db, $idobs);
 
/*
// Q&D
$images = array();
$o = new Observation($this->conteneur);
foreach($idobs as $i) {
$images[$i] = $o->consulter(array($i), array('justthrow' => 1));
}
*/
list($images, $images_keyed_by_id_image) = self::reformateImagesDoubleIndex(
$liaisons,
$this->conteneur->getParametre('images.url_images'),
$params['format']);
 
 
// on charge les votes pour ces images et pour *tous* les protocoles
$votes = Observation::chargerVotesImage($db, $liaisons, NULL);
 
// subtilité, nous passons ici le tableau d'images indexé par id_image qui est bien plus pratique pour
// associer les vote à un tableau, puisque nous ne connaissons pas les id d'observation.
// Mais magiquement (par référence), cela va remplir notre tableau indexé par couple d'id (id_image, id_observation)
// cf reformateImagesDoubleIndex() à qui revient la tâche de créer ces deux versions simultanément lorsque
// c'est encore possible.
if($votes) Observation::mapVotesToImages($votes, $images_keyed_by_id_image);
 
// les deux masques de tags sont transformés en AST dans le processus de construction de la requête.
// Reprenous les paramètres originaux non-nettoyés (ils sont valables car le nettoyage est déterministe)
$params_header = array_merge($params, array_filter(array('masque.tag_cel' => @$parametres['masque.tag_cel'],
'masque.tag_pictoflora' => @$parametres['masque.tag_pictoflora'])));
$resultat = new ResultatService();
$resultat->corps = array('entete' => DelTk::makeJSONHeader($total, $params_header, Config::get('url_service')),
'resultats' => $images);
return $resultat;
}
 
/**
* TODO: partie spécifique liées à la complexité de PictoFlora:
* génération de la clause ORDER BY (génère la valeur de la clef orderby' de $req)
* nécessaire ? tableau sprintf(key (tri) => value (ordre), key => value ...).
* Cependant il est impensable de joindre sur un AVG() des valeurs des votes pour
* *chaque* couple (id_image, protocole) de la base afin de trouver les images
* les "mieux notées", ou bien les images ayant le "plus de tags" (COUNT())
*/
static function sqlOrderBy($p, $db, &$req) {
// parmi self::$tri_possible
if($p['tri'] == 'votes') { // LEFT JOIN sur "dis" ci-dessous
$req['orderby'] = 'dis.moyenne ' . $p['ordre'] . ', dis.nb_votes ' . $p['ordre'];
return;
}
if($p['tri'] == 'tags') { // LEFT JOIN sur "dis" ci-dessous
$req['orderby'] = 'dis.nb_tags ' . $p['ordre'];
return;
}
 
if($p['tri'] == 'date_observation') {
$req['orderby'] = 'date_observation ' . $p['ordre'] . ', id_observation ' . $p['ordre'];
return;
}
 
// tri == 'date_transmission'
// avant cel:r1860, date_transmission pouvait être NULL
// or nous voulons de la consistence (notamment pour phpunit)
$req['orderby'] = 'date_transmission ' . $p['ordre'] . ', id_observation ' . $p['ordre'];
}
 
/*
* in $p: un tableau de paramètres, dont:
* - 'masque.tag_cel': *tableau* de mots-clefs à chercher parmi cel_image.mots_clefs_texte
* - 'masque.tag_pictoflora': *tableau* de mots-clefs à chercher parmi del_image_tag.tag_normalise
* - 'tag_explode_semantic': défini si les éléments sont tous recherchés ou NON
*
* in/ou: $req: un tableau de structure de requête MySQL
*
* Attention, le fait que nous cherchions masque.tag_cel OU/ET masque.tag_cel
* ne dépend pas de nous, mais du niveau supérieur de construction de la requête:
* Soit directement $this->consulter() si des masque.tag* sont passés
* (split sur ",", "AND" entre chaque condition, "OR" pour chaque valeur de tag)
* Soit via sqlAddMasqueConstraint():
* (pas de split, "OR" entre chaque condition) [ comportement historique ]
* équivalent à:
* (split sur " ", "OR" entre chaque condition, "AND" pour chaque valeur de tag)
*
*/
static function sqlAddConstraint($p, $db, &$req, Conteneur $c = NULL) {
// TODO implement dans DelTk ?
if(!empty($p['masque.milieu'])) {
$req['where'][] = 'vdi.milieu LIKE '.$db->proteger('%' . $p['masque.milieu'].'%');
}
 
 
/* Pour le tri par AVG() des votes nous avons toujours un protocole donné,
celui-ci indique sur quels votes porte l'AVG.
(c'est un *vote* qui porte sur un protocole et non l'image elle-même) */
/* TODO: perf problème:
1) SQL_CALC_FOUND_ROWS: fixable en:
- dissociant le comptage de la récup d'id + javascript async
- ou ne rafraîchir le total *que* pour les requête impliquant un changement de pagination
(paramètre booléen "with-total" par exemple)
2) jointure forcées: en utilisant `del_imagè`, nous forçons les 2 premiers
JOIN sur cel_obs_images et cel_obs pour filtrer sur "transmission".
Dénormaliser cette valeur et l'intégrer à `cel_images` ferait économiser cette couteuse
jointure, ... lorsqu'aucun masque portant sur `cel_obs` n'est utilisé
3) non-problème: l'ordre des joins est forcé par l'usage de la vue:
(cel_images/cel_obs_images/cel_obs/del_image_stat)
Cependant c'est à l'optimiseur de définir son ordre préféré. */
if($p['tri'] == 'votes') {
// $p['protocole'] *est* défini (cf requestFilterParams())
// petite optimisation: INNER JOIN si ordre DESC car les 0 à la fin
if($p['ordre'] == 'desc') {
// pas de group by nécessaire pour cette jointure
// PRIMARY KEY (`ce_image`, `ce_protocole`)
$req['join'][] = sprintf('INNER JOIN del_image_stat dis'.
' ON vdi.id_image = dis.ce_image'.
' AND dis.ce_protocole = %d',
$p['protocole']);
} else {
$req['join'][] = sprintf('LEFT JOIN del_image_stat dis'.
' ON vdi.id_image = dis.ce_image'.
' AND dis.ce_protocole = %d',
$p['protocole']);
// nécessaire (dup ce_image dans del_image_stat)
$req['groupby'][] = 'vdi.id_observation';
}
}
 
if($p['tri'] == 'tags') {
$req['join'][] = sprintf('%s JOIN del_image_stat dis ON vdi.id_image = dis.ce_image',
($p['ordre'] == 'desc') ? 'INNER' : 'LEFT');
// nécessaire (dup ce_image dans del_image_stat)
$req['groupby'][] = 'vdi.id_observation';
}
 
// car il ne sont pas traités par la générique requestFilterParams() les clefs "masque.tag_*"
// sont toujours présentes; bien que parfois NULL.
if($p['masque.tag_cel']) {
if(isset($p['masque.tag_cel']['AND'])) {
// TODO: utiliser les tables de mots clefs normaliées dans tb_cel ?
// et auquel cas laisser au client le choix du couteux "%" ?
$tags = $p['masque.tag_cel']['AND'];
array_walk($tags, create_function('&$val, $k, $db',
'$val = sprintf("CONCAT(vdi.mots_cles_texte,vdi.i_mots_cles_texte) LIKE %s",
$db->proteger("%".$val."%"));'),
$db);
$req['where'][] = '(' . implode(' AND ', $tags) . ')';
}
else {
$req['where'][] = sprintf("CONCAT(vdi.mots_cles_texte,vdi.i_mots_cles_texte) REGEXP %s",
$db->proteger(implode('|', $p['masque.tag_cel']['OR'])));
}
}
 
if($p['masque.tag_pictoflora']) {
// inutilisable pour l'instant
// self::sqlAddPictoFloraTagConstraint1($p, $db, $req);
 
// intéressante, mais problème d'optimiseur MySQL 5.5 (dependant subquery)
// self::sqlAddPictoFloraTagConstraint2($p, $db, $req);
 
// approche fiable mais sous-optimale
self::sqlAddPictoFloraTagConstraint3($p, $db, $req);
}
}
 
/* approche intéressante si les deux problèmes suivants peuvent être résolu:
- LEFT JOIN => dup => *gestion de multiples GROUP BY* (car in-fine un LIMIT est utilisé)
- dans le cas d'un ET logique, comment chercher les observations correspondantes ? */
static function sqlAddPictoFloraTagConstraint1($p, $db, &$req) {
// XXX: utiliser tag plutôt que tag_normalise ?
$req['join'][] = 'LEFT JOIN del_image_tag dit ON dit.ce_image = vdi.id_image';
$req['where'][] = 'dit.actif = 1';
$req['groupby'][] = 'vdi.id_image'; // TODO: nécessaire (car dup') mais risque de conflict en cas de tri (multiple GROUP BY)
// XXX: en cas de ET, possibilité du GROUP_CONCAT(), mais probablement sans grand intérêt, d'où une boucle
if(isset($p['masque.tag_pictoflora']['AND'])) {
// TODO/XXX : comment matcher les observations ayant tous les mots-clef passés ?
// ... le LEFT-JOIN n'y semble pas adapté
}
else {
$protected_tags = array();
foreach($p['masque.tag_pictoflora']['OR'] as $tag) $protected_tags[] = $db->proteger(strtolower($tag));
$req['where'][] = sprintf('tag_normalise IN (%s)', implode(',', $protected_tags));
}
}
 
// inutilisé pour l'instant pour cause de soucis d'optimiseur MySQL (cf commentaire en intro)
static function sqlAddPictoFloraTagConstraint2($p, $db, &$req) {
// Note à propos des 4 "@ instruction" ci-dessous (notamment sur recupererTous())
// REGEXP permet un puissant mécanisme de sélection des obs/image à qui sait
// l'utiliser, mais peut sortir une erreur en cas de REGEXP invalide
// ex: REGEX "^(".
// Pour l'heure nous ignorons ce type d'erreur car aucun de nos champ de recherche
// ne peuvent (ou ne devrait) comporter des meta-caractères
// ([])?*+\\
if(isset($p['masque.tag_pictoflora']['AND'])) {
// optimsation: en cas de "AND" on sort() l'input et le GROUP_CONCAT()
// donc nous utilisons des ".*" plutôt que de multiples conditions et "|"
sort($p['masque.tag_pictoflora']['AND']);
$req['where'][] = sprintf("vdi.id_image IN (SELECT ce_image FROM del_image_tag WHERE actif = 1".
" GROUP BY ce_image".
" HAVING GROUP_CONCAT(tag_normalise ORDER BY tag_normalise) REGEXP %s)",
$db->proteger(implode('.*', $p['masque.tag_pictoflora']['AND'])));
}
else {
$req['where'][] = sprintf("vdi.id_image IN (SELECT ce_image FROM del_image_tag WHERE actif = 1".
" GROUP BY ce_image".
" HAVING GROUP_CONCAT(tag_normalise) REGEXP %s)",
$db->proteger(implode('|', $p['masque.tag_pictoflora']['OR'])));
}
}
 
// si l'on est bassiné par les "DEPENDENT SUBQUERY", nous la faisons donc indépendemment via cette fonction
static function sqlAddPictoFloraTagConstraint3($p, $db, &$req) {
if(isset($p['masque.tag_pictoflora']['AND'])) {
// optimsation: en cas de "AND" on sort() l'input et le GROUP_CONCAT()
// donc nous utilisons des ".*" plutôt que de multiples conditions et "|"
sort($p['masque.tag_pictoflora']['AND']);
 
// plutôt que db->connexion->query->fetchColumn(), une API pourrie nous oblige à ...
$ids = @$db->recupererTous(sprintf(
"SELECT ce_image FROM del_image_tag WHERE actif = 1".
" GROUP BY ce_image".
" HAVING GROUP_CONCAT(tag_normalise ORDER BY tag_normalise) REGEXP %s",
$db->proteger(implode('.*', $p['masque.tag_pictoflora']['AND']))));
 
// puis:
$ids = @array_map(create_function('$e', 'return $e["ce_image"];'), $ids);
if($ids) $req['where'][] = sprintf("vdi.id_image IN (%s)", implode(',', $ids));
 
}
else {
$ids = @$db->recupererTous(sprintf(
"SELECT ce_image FROM del_image_tag WHERE actif = 1".
" GROUP BY ce_image".
" HAVING GROUP_CONCAT(tag_normalise) REGEXP %s",
$db->proteger(implode('|', $p['masque.tag_pictoflora']['OR']))));
 
$ids = @array_map(create_function('$e', 'return $e["ce_image"];'), $ids);
if($ids) $req['where'][] = sprintf("vdi.id_image IN (%s)", implode(',', $ids));
}
}
 
static function getIdImages($p, $req, $db) {
return $db->recupererTous(sprintf(
'SELECT SQL_CALC_FOUND_ROWS id_image' .
' FROM v_del_image vdi'.
' %s' . // LEFT JOIN if any
' WHERE %s'. // where-clause ou TRUE
' %s'. // group-by
' ORDER BY %s'.
' LIMIT %d, %d -- %s',
$req['join'] ? implode(' ', array_unique($req['join'])) : '',
$req['where'] ? implode(' AND ', $req['where']) : 'TRUE',
$req['groupby'] ? ('GROUP BY ' . implode(', ', array_unique($req['groupby']))) : '',
$req['orderby'],
$p['navigation.depart'], $p['navigation.limite'], __FILE__ . ':' . __LINE__));
 
}
 
static function chargerImages($db, $idImg) {
$obs_fields = DelTk::sqlFieldsToAlias(self::$mappings['observations'], NULL);
$image_fields = DelTk::sqlFieldsToAlias(self::$mappings['images'], NULL);
return $db->recupererTous(sprintf('SELECT '.
' CONCAT(id_image, "-", id_observation) AS jsonindex,'.
' %1$s, %2$s FROM v_del_image '.
' WHERE %3$s'.
' -- %4$s',
$obs_fields, $image_fields,
sprintf('id_image IN (%s)', implode(',', $idImg)),
__FILE__ . ':' . __LINE__));
 
}
 
/* "masque" ne fait jamais que faire une requête sur la plupart des champs, (presque) tous traités
de manière identique à la seule différence que:
1) ils sont combinés par des "OU" logiques plutôt que des "ET".
2) les tags sont traités différemment pour conserver la compatibilité avec l'utilisation historique:
Tous les mots-clefs doivent matcher et sont séparés par des espaces
(dit autrement, str_replace(" ", ".*", $mots-clefs-requête) =~ $mots-clefs-mysql)
Pour plus d'information: (ListeObservations|DelTk)::sqlAddMasqueConstraint() */
static function sqlAddMasqueConstraint($p, $db, &$req, Conteneur $c = NULL) {
if(!empty($p['masque'])) {
$or_params = array('masque.auteur' => $p['masque'],
'masque.departement' => $p['masque'],
'masque.commune' => $p['masque'], // TODO/XXX ?
'masque.id_zone_geo' => $p['masque'],
 
/* tous-deux remplacent masque.tag
mais sont traité séparément des requestFilterParams() */
// 'masque.tag_cel' => $p['masque'],
// 'masque.tag_pictoflora' => $p['masque'],
 
'masque.ns' => $p['masque'],
'masque.famille' => $p['masque'],
'masque.date' => $p['masque'],
'masque.genre' => $p['masque'],
'masque.milieu' => $p['masque'],
 
// tri est aussi nécessaire car affecte les contraintes de JOIN
'tri' => $p['tri'],
'ordre' => $p['ordre']);
 
/* Cependant les champs spécifiques ont priorité sur le masque général.
Pour cette raison nous supprimons la génération de SQL du masque général sur les
champ spécifiques qui feront l'objet d'un traitement avec une valeur propre. */
if(isset($p['masque.auteur'])) unset($or_params['masque.auteur']);
if(isset($p['masque.departement'])) unset($or_params['masque.departement']);
if(isset($p['masque.commune'])) unset($or_params['masque.commune']);
if(isset($p['masque.id_zone_geo'])) unset($or_params['masque.id_zone_geo']);
if(isset($p['masque.ns'])) unset($or_params['masque.ns']);
if(isset($p['masque.famille'])) unset($or_params['masque.famille']);
if(isset($p['masque.date'])) unset($or_params['masque.date']);
if(isset($p['masque.genre'])) unset($or_params['masque.genre']);
if(isset($p['masque.milieu'])) unset($or_params['masque.milieu']);
if(isset($p['masque.tag_cel'])) unset($or_params['masque.tag_cel']);
if(isset($p['masque.tag_pictoflora'])) unset($or_params['masque.tag_pictoflora']);
 
$or_masque = array_merge(
DelTk::requestFilterParams($or_params, NULL, $c /* pour masque.departement */),
self::requestFilterParams($or_params));
 
/* Lorsqu'on utilise le masque général pour chercher des tags, ils sont
postulés comme séparés par des espaces, et doivent être tous matchés. */
if(isset($or_params['masque.tag_cel']))
$or_masque['masque.tag_cel'] = DelTk::buildTagsAST($p['masque'], 'AND', ' ');
if(isset($or_params['masque.tag_pictoflora']))
$or_masque['masque.tag_pictoflora'] = DelTk::buildTagsAST($p['masque'], 'AND', ' ');
 
 
// pas de select, groupby & co ici: uniquement 'join' et 'where'
$or_req = array('join' => array(), 'where' => array());
DelTk::sqlAddConstraint($or_masque, $db, $or_req);
self::sqlAddConstraint($or_masque, $db, $or_req);
 
if($or_req['where']) {
$req['where'][] = '(' . implode(' OR ', $or_req['where']) . ')';
// utile au cas ou des jointures seraient rajoutées
$req['join'] = array_unique(array_merge($req['join'], $or_req['join']));
}
}
}
 
 
// cf Observation::reformateObservationSimpleIndex() et ListeObservations::reformateObservation()
// (trop de variétés de formatage, à unifier côté client pour unifier côté backend ...)
static function reformateImagesDoubleIndex($obs, $url_pattern = '', $image_format = 'XL') {
// XXX: cf Observation.php::consulter(), nous pourriouns ici
// conserver les valeurs vides (pour les phptests notamment, ou non)
// $obs = array_map('array_filter', $obs);
$obs_merged = $obs_keyed_by_id_image = array();
foreach($obs as $o) {
// ceci nous complique la tâche pour le reste du processing...
$id = $o['jsonindex'];
// ainsi nous utilisons deux tableaux: le final, indexé par couple d'id(image-obs)
// et celui indexé par simple id_image qui est fort utile pour mapVotesToImages()
// mais tout deux partage leur référence à "protocole"
$image = array(
'id_image' => $o['id_image'],
'binaire.href' => sprintf($url_pattern, $o['id_image'], $image_format),
'mots_cles_texte' => @$o['i_mots_cles_texte'], // @, peut avoir été filtré par array_map() ci-dessus
);
unset($o['id_image'], $o['i_mots_cles_texte'], $o['jsonindex']);
if(!isset($obs_merged[$id])) $obs_merged[$id] = $image;
$obs_merged[$id]['observation'] = $o;
$obs_merged[$id]['protocoles_votes'] = array();
$obs_keyed_by_id_image[$image['id_image']]['protocoles_votes'] = &$obs_merged[$id]['protocoles_votes'];
}
 
return array($obs_merged,$obs_keyed_by_id_image);
}
 
 
 
// complete & override DelTk::requestFilterParams() (même usage)
static function requestFilterParams(Array $params, $parametres_autorises = NULL) {
if($parametres_autorises) { // filtrage de toute clef inconnue
$params = array_intersect_key($params, array_flip($parametres_autorises));
}
 
$p = array();
$p['tri'] = DelTk::unsetIfInvalid($params, 'tri', self::$tri_possible);
$p['format'] = DelTk::unsetIfInvalid($params, 'format', self::$format_image_possible);
 
// "milieu" inutile pour IdentiPlantes ?
if(isset($params['masque.milieu'])) $p['masque.milieu'] = trim($params['masque.milieu']);
 
// compatibilité
if(isset($params['masque.tag'])) {
$params['masque.tag_cel'] = $params['masque.tag_pictoflora'] = $params['masque.tag'];
}
 
if($p['tri'] == 'votes' || $p['tri'] == 'tags') {
// ces critère de tri des image à privilégier ne s'applique qu'à un protocole donné
if(!isset($params['protocole']) || !is_numeric($params['protocole']))
$p['protocole'] = self::$default_proto;
else
$p['protocole'] = intval($params['protocole']);
}
 
return array_filter($p, create_function('$a','return !in_array($a, array("",false,null),true);'));
}
 
 
 
// met à jour *toutes* les stats de nombre de tags et de moyenne des votes
static function _update_statistics($db) {
$db->requeter("TRUNCATE TABLE del_image_stat");
$db->requeter(<<<EOF
INSERT INTO `del_image_stat` (
SELECT id_image, divo.ce_protocole, divo.moyenne, divo.nb_votes, dit.ctags
FROM `tb_cel`.`cel_images` ci
LEFT JOIN
( SELECT ce_image, ce_protocole, AVG(valeur) AS moyenne, COUNT(valeur) AS nb_votes FROM del_image_vote
GROUP BY ce_image, ce_protocole ) AS divo
ON ci.id_image = divo.ce_image
LEFT JOIN
( SELECT ce_image, COUNT(id_tag) as ctags FROM del_image_tag
GROUP BY ce_image ) AS dit
ON ci.id_image = dit.ce_image )
EOF
);
}
 
static function revOrderBy($orderby) {
return $orderby == 'asc' ? 'desc' : 'asc';
}
}
/tags/v1.1-helium/services/modules/0.1/images/VoteImage.php
New file
0,0 → 1,175
<?php
// declare(encoding='UTF-8');
/**
* Le web service image récupère toutes les données de la table del_obs_images
* pour retourner une liste d'images associée à une observation
*
* @category php 5.2
* @package del
* @subpackage images
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images
*/
 
class VoteImage {
private $imageIds = array();
private $conteneur;
private $navigation;
private $masque;
private $gestionBdd;
private $bdd;
private $ressources;
private $parametres;
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_votes.ini');
$this->conteneur->chargerConfiguration('config_mapping_votes.ini');
$this->navigation = $conteneur->getNavigation();
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
/**
* Méthode principale de la classe.
* Lance la récupération des images dans la base et les place dans un objet ResultatService
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function consulter($ressources, $parametres) {
// Gestion des configuration du script
$this->ressources = $ressources;
$this->parametres = $parametres;
$this->configurer();
$this->verifierConfiguration();
// Lancement du service
$votes = $this->chargerVotes();
$total = $this->compterVotes();
$this->navigation->setTotal($total);
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
$resultat->corps = $votes;
return $resultat;
}
/*-------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
--------------------------------------------------------------------------------*/
/**
* Configuration du service en fonction du fichier de config config_del.ini
* */
public function configurer() {
$this->mappingFiltre = $this->conteneur->getParametre('mapping_masque');
$this->mappingVotes = $this->conteneur->getParametre('mapping_votes');
}
/**
* Vérifier que le service est bien configuré
* */
public function verifierConfiguration() {
$erreurs = array();
$tableauImages = $this->conteneur->getParametre('images');
if (empty($tableauImages)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [images] ou celui-ci est vide ;';
} else {
if ($this->conteneur->getParametre('url_service') == null) {
$erreurs[] = '- paramètre "url_service" manquant ;';
}
}
 
if (empty($this->mappingVotes)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [mapping_observation] ou celui-ci est vide ;';
} else {
$champsMappingObs = array('ce_protocole','id_vote','valeur','ce_image', 'ce_utilisateur', 'nom', 'prenom');
foreach ($champsMappingObs as $champ) {
if (!isset($this->mappingVotes[$champ])) {
$erreurs[] = '- le mapping du champ "'.$champ.'" pour l\'observation est manquant ;';
}
}
}
if (!empty($erreurs)) {
$e = 'Erreur lors de la configuration : '."\n";
$e .= implode("\n", $erreurs);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
 
/**
* Charger la clause WHERE en fonction des paramètres de masque
* */
private function chargerClauseWhere() {
$where[] = 'WHERE ce_image = '.$this->proteger($this->ressources[0]);
$where[] = 'id_vote = '.$this->proteger($this->ressources[2]);
return implode(' AND ', $where);
}
/*-------------------------------------------------------------------------------
CHARGEMENT DES IMAGES
--------------------------------------------------------------------------------*/
/**
* Charger les votes pour chaque image
* */
private function chargerVotes() {
$requeteVotes = 'SELECT * FROM '.
$this->gestionBdd->formaterTable('del_image_vote').
$this->chargerClauseWhere();
$resultatsVotes = $this->bdd->recupererTous($requeteVotes);
$votes = $this->formaterVote($resultatsVotes[0]);
return $votes;
}
/**
* Compter le nombre total d'images dans la base pour affichage dans entete.
* */
private function compterVotes() {
$requete = 'SELECT FOUND_ROWS() AS nbre ';
$resultats = $this->bdd->recuperer($requete);
return (int) $resultats['nbre'];
}
 
 
/*-------------------------------------------------------------------------------
FORMATER ET METTRE EN FORME
--------------------------------------------------------------------------------*/
 
/**
* Formater une observation depuis une ligne liaison
* @param $liaison liaison issue de la recherche
* @return $observation l'observation mise en forme
* */
private function formaterVote($vote) {
$retour = array();
foreach ($vote as $p=>$valeur) {
$retour[$this->mappingVotes[$p]] = $valeur;
}
return $retour;
}
private function proteger($valeur) {
if (is_array($valeur)) {
return $this->bdd->protegerTableau($valeur);
} else {
return $this->bdd->proteger($valeur);
}
}
}
?>
/tags/v1.1-helium/services/modules/0.1/images/ListeImages.old.php
New file
0,0 → 1,1349
<?php
// declare(encoding='UTF-8');
/**
* Le web service image récupère toutes les données de la table del_obs_images
* pour retourner une liste d'images associée à une observation
*
* @category php 5.2
* @package del
* @subpackage images
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images
*/
 
 
/**
* FONCTION TEMPORAIRE de debug pour afficher le contenu d'une variable en format lisible
* @param $r la variable à afficher
* */
function debug($r) {
echo '<pre>'.print_r($r, true).'</pre>';
}
 
 
/**
* Le service ListeImages récupère les données des tables observation et images
* et les mets au format JSON pour identiplante / pictoflora
* */
class ListeImages {
// Variables :
// Configuration générale du service
private $conteneur;
private $navigation;
private $bdd;
private $gestionBdd;
// Parametres
private $ressources = array();
private $parametres = array();
private $masque;
private $tri = 'date_transmission';
private $directionTri = 'desc';
private $formatRetour = 'XL';
private $imageIds = array();
/**
* Constructeur de l'application
* Initialisation des variables générale de l'application
* @param Conteneu $conteneur le conteneur de classes de l'application
* */
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_departements_bruts.ini');
$this->conteneur->chargerConfiguration('config_mapping_votes.ini');
$this->conteneur->chargerConfiguration('config_images.ini');
$this->navigation = $conteneur->getNavigation();
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
/**
* Méthode principale de la classe.
* Lance la récupération des images dans la base et les place dans un objet ResultatService
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function consulter($ressources, $parametres) {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
$this->configurer();
$this->verifierConfiguration();
$this->verifierParametresTri();
$this->initialiserTri();
$this->verifierParametreFormatRetour();
$this->initialiserFormatRetour();
$parametres = $this->nettoyerParametres($parametres);
// En fonction des paramètres de recherche, on n'effectue
// pas la même requête, pour optimiser les jointures et les
// rapidités d'éxécution.
$type = $this->getTypeRequete($ressources, $parametres);
switch ($type) {
case 'obs' :
$liaisons = $this->chargerLiaisonsObs();
break;
case 'images' :
$liaisons = $this->chargerLiaisonsImages();
break;
case 'obs-images' :
$liaisons = $this->chargerLiaisons();
break;
case 'id':
$liaisons = $this->chargerLiaisonsParId();
break;
default : //case simple !
$liaisons = $this->chargerLiaisonsSimple();
}
$images = array();
if($liaisons) {
// Partie commune à tous les cas : on complète les liaisons avec les informations des votes
// et des images, puis on affiche sous forme de JSON
$images = $this->chargerImage($liaisons);
$images = $this->chargerVotes($images);
}
 
$resultat = new ResultatService();
if ($type == 'id') {
$clefsImages =array_keys($images);
$resultat->corps = $images[$clefsImages[0]];
} else {
$resultat->corps = array('entete' => $this->conteneur->getEntete(), 'resultats' => $images);
}
 
return $resultat;
}
/**************************************************************************************
* FONCTION LIEES AUX REQUETES *
**************************************************************************************/
/**
* Charger la clause WHERE en fonction des paramètres de masque
* */
private function chargerClauseWhere() {
 
$where = array();
$tableauMasque = $this->masque->getMasque();
if (!empty($tableauMasque)) {
foreach($tableauMasque as $idMasque => $valeurMasque) {
//TODO: scinder ceci en fonctions réutilisables ?
// voir si c'est interessant par rapport à la recherche générale
$idMasque = str_replace('masque.', '', $idMasque);
switch ($idMasque) {
// nom du masque => nom BDD
case 'auteur' :
$whereAuteur = ' '.$this->creerFiltreAuteur($this->masque->getMasque('auteur'));
if($whereAuteur != '') {
$where[] = $whereAuteur;
}
break;
case 'date' :
$whereDate = ' '.$this->creerFiltreDate($valeurMasque);
if($whereDate != '') {
$where[] = $whereDate;
}
break;
case 'departement' :
$where[] = ' '.$this->creerFiltreIdZoneGeo($valeurMasque);
break;
case 'genre' :
$where[] = ' '.$this->mappingFiltre['ns'].' LIKE '.$this->proteger($valeurMasque.' %');
break;
case 'tag' :
$where[] = ' '.$this->creerFiltreMotsCles($valeurMasque);
break;
case 'tag_cel' :
$where[] = ' '.$this->creerFiltreMotsClesCel($valeurMasque);
break;
case 'tag_pictoflora' :
$where[] = ' '.$this->creerFiltreMotsClesPictoflora($valeurMasque);
break;
case 'referentiel' :
$where[] = ' dob.nom_referentiel LIKE '.$this->proteger($valeurMasque.'%');
break;
case 'ns' :
$where[] = ' nom_sel LIKE '.$this->proteger($valeurMasque.'%');
break;
case 'nn' :
$num_noms = $valeurMasque;
$num_noms = explode(',', $num_noms);
$num_noms = array_map('intval', $num_noms);
$num_noms = array_filter($num_noms);
$num_noms = implode(',', $num_noms);
$where[] = "(nom_sel_nn IN ($num_noms) OR nom_ret_nn IN ($num_noms)) ";
break;
case 'commune' :
$where[] = ' '.$this->mappingFiltre[$idMasque].' LIKE '.$this->proteger(str_replace(array('-',' '), '_', $valeurMasque).'%');
break;
case 'masque' :
$where[] = ' '.$this->creerFiltreMasqueGeneral($valeurMasque);
break;
default:
$where[] = ' '.$this->mappingFiltre[$idMasque].' = '.$this->proteger($valeurMasque);
break;
}
}
}
if (!empty($where)) {
return ' WHERE '.implode('AND', $where);
} else {
return;
}
}
/**
* Créer un masque général lorsque l'on souhaite utiliser le passe partout
* @param la valeur du passe partout
* */
private function creerFiltreMasqueGeneral($valeurMasque) {
//TODO: affecter d'aborder les variables, puis les tester pour les
// ajouter à la chaine
$whereAuteur = $this->creerFiltreAuteur($valeurMasque);
$whereIdZoneGeo = $this->creerFiltreIdZoneGeo($valeurMasque);
$masqueGeneral = '( '.
(($whereAuteur != '') ? $whereAuteur.' OR ' : '' ).
(($whereIdZoneGeo != '') ? $whereIdZoneGeo.' OR ' : '' ).
'zone_geo LIKE '.$this->proteger($this->remplacerParJokerCaractere($valeurMasque).'%').' OR '.
$this->creerFiltreMotsCles($valeurMasque).' OR '.
'nom_sel LIKE '.$this->proteger($valeurMasque.'%').' OR '.
'famille LIKE '.$this->proteger($valeurMasque.'%').' OR '.
'milieu LIKE '.$this->proteger($valeurMasque).' OR '.
$this->mappingFiltre['ns'].' LIKE '.$this->proteger('%'.$valeurMasque.'% %').' OR '.
$this->creerFiltreDate($valeurMasque).
') ';
return $masqueGeneral;
}
/**
* Créer le filtre auteur en recherchant dans son nom, prénom, adresse email en fonction
* de la chaine donnée
* @param la valeur recherchée
* */
private function creerFiltreAuteur($valeurMasque) {
$masque = '';
$auteurId = $valeurMasque;
if (is_numeric($auteurId)) {
$masque = ' ce_utilisateur = '.$auteurId;
} else {
if (strpos($auteurId, '@') === false) {
$tableauNomPrenom = explode(' ',$auteurId, 2);
if(count($tableauNomPrenom) == 2) {
// on teste potentiellement un nom prenom ou bien un prénom nom
$masque = '('.
'(nom LIKE '.$this->proteger($tableauNomPrenom[0].'%').' AND '.
'prenom LIKE '.$this->proteger($tableauNomPrenom[1].'%').') OR '.
'(nom LIKE '.$this->proteger($tableauNomPrenom[1].'%').' AND '.
'prenom LIKE '.$this->proteger($tableauNomPrenom[0].'%').') OR '.
'(dob.nom_utilisateur LIKE '.$this->proteger($tableauNomPrenom[0].'%').' AND '.
'dob.prenom_utilisateur LIKE '.$this->proteger($tableauNomPrenom[1].'%').') OR '.
'(dob.nom_utilisateur LIKE '.$this->proteger($tableauNomPrenom[1].'%').' AND '.
'dob.prenom_utilisateur LIKE '.$this->proteger($tableauNomPrenom[0].'%').') OR '.
'(nom LIKE '.$this->proteger($valeurMasque.'%').') OR '.
'(prenom LIKE '.$this->proteger($valeurMasque.'%').') OR '.
'(dob.nom_utilisateur LIKE '.$this->proteger($valeurMasque.'%').') OR '.
'(dob.prenom_utilisateur LIKE '.$this->proteger($valeurMasque.'%').') '.
')';
} else {
$masque = '(
(nom LIKE '.$this->proteger($auteurId.'%').' OR '.
'prenom LIKE '.$this->proteger($auteurId.'%').' OR '.
'dob.nom_utilisateur LIKE '.$this->proteger($auteurId.'%').' OR '.
'dob.prenom_utilisateur LIKE '.$this->proteger($auteurId.'%').')'.
')';
}
} else {
$masque = " ( courriel LIKE ".$this->proteger($valeurMasque.'%').
" OR dob.courriel_utilisateur LIKE ".$this->proteger($valeurMasque.'%').") ";
}
}
return $masque;
}
/**
* Obtenir une chaine de caractère concaténant nom et prénom séparé par une virgule
* @param String $auteurId l'identifiant de l'auteur
* @return String la chaine de concaténation
* */
private function getChaineNomPrenom($auteurId) {
$nomPrenom = explode(' ', $auteurId);
$nomPrenom = $this->proteger($nomPrenom);
$chaineNomPrenom = implode(', ', $nomPrenom);
return $chaineNomPrenom;
}
/**
* Créer le filtre de recherche par zone géographique en fonction du masque
* @param $valeurMasque le terme de la recherche
* */
private function creerFiltreIdZoneGeo($valeurMasque) {
$masque = '';
$dept = $valeurMasque;
if (is_numeric($dept)) {
$dept = sprintf('%02s', $dept);
$dept = sprintf("%-'_5s", $dept);
$masque = " ce_zone_geo LIKE ".$this->proteger('INSEE-C:'.$dept);
} else {
$deptId = $this->conteneur->getParametre($dept);
if ($deptId != null) {
$masque = " ce_zone_geo LIKE ".$this->proteger('INSEE-C:'.$deptId.'%');
} else {
$id = $this->obtenirIdDepartement($valeurMasque);
$masque = " ce_zone_geo LIKE ".$this->proteger('INSEE-C:'.$id.'%');
}
}
return $masque;
}
/**
* Générer la chaine de recherche pour la date en fonction du masque
* @param $valeurMasque la date recherchée (AAAA ou JJ/MM/AAAA)
* */
private function creerFiltreDate($valeurMasque) {
//TODO: définir dans le fichier de config un tableau contenant plusieurs format de date
// autorisés pour la recherche, qui seraient ajoutés au OR
$masque = '(';
$masque .= (is_numeric($valeurMasque)) ? ' YEAR(date_observation) = '.$this->proteger($valeurMasque).' OR ' : '';
$masque .= " DATE_FORMAT(date_observation, '%d/%m/%Y') = ".$this->proteger($valeurMasque).' '.
')';
return $masque;
}
/**
* Générer la chaine de recherche dans les mots clés en fonction du masque
* @param $valeurMasque le mot clé recherché
* */
private function creerFiltreMotsCles($valeurMasque) {
$mots_cles = explode(' ', $valeurMasque);
$requeteMotsClesImg = array();
$requeteMotsClesObs = array();
$requeteMotsClesImgPublic = array();
foreach($mots_cles as $mot_cle) {
//TODO: rechercher sur les mots clés normalisés dans tous les cas ?
$requeteMotsCles = $this->proteger('%'.$mot_cle.'%');
$motsCleProtege = $this->proteger($this->normaliserMotCle('%'.$mot_cle.'%'));
$requeteMotsClesImgPublic[] = 'di.id_image IN (SELECT ce_image FROM del_image_tag WHERE tag_normalise LIKE '.$motsCleProtege.' AND actif = 1)';
$requeteMotsClesImg[] = 'di.mots_cles_texte LIKE '.$requeteMotsCles;
$requeteMotsClesObs[] = 'dob.mots_cles_texte LIKE '.$requeteMotsCles;
}
$requeteMotsClesImgPublic = implode(' AND ', $requeteMotsClesImgPublic);
$requeteMotsClesImg = implode(' AND ', $requeteMotsClesImg);
$requeteMotsClesObs = implode(' AND ', $requeteMotsClesObs);
$masque = '('.
'('.$requeteMotsClesImgPublic.') OR '.
'('.$requeteMotsClesImg.') OR '.
'('.$requeteMotsClesObs.') '.
')';
return $masque;
}
/**
* Générer la chaine de recherche dans les mots clés en fonction du masque
* @param $valeurMasque le mot clé recherché
* */
private function creerFiltreMotsClesPictoflora($valeurMasque) {
$mots_cles = explode(' ', $valeurMasque);
$requeteMotsClesImg = array();
$requeteMotsClesObs = array();
$requeteMotsClesImgPublic = array();
foreach($mots_cles as $mot_cle) {
//TODO: rechercher sur les mots clés normalisés dans tous les cas ?
$requeteMotsCles = $this->proteger('%'.$mot_cle.'%');
$motsCleProtege = $this->proteger($this->normaliserMotCle('%'.$mot_cle.'%'));
$requeteMotsClesImgPublic[] = 'di.id_image IN (SELECT ce_image FROM del_image_tag WHERE tag_normalise LIKE '.$motsCleProtege.' AND actif = 1)';
}
$requeteMotsClesImgPublic = implode(' AND ', $requeteMotsClesImgPublic);
$masque = '('.$requeteMotsClesImgPublic.') ';
return $masque;
}
private function creerFiltreMotsClesCel($valeurMasque) {
$mots_cles = explode(' ', $valeurMasque);
$requeteMotsClesImg = array();
$requeteMotsClesObs = array();
foreach($mots_cles as $mot_cle) {
//TODO: rechercher sur les mots clés normalisés dans tous les cas ?
$requeteMotsCles = $this->proteger('%'.$mot_cle.'%');
$motsCleProtege = $this->proteger($this->normaliserMotCle('%'.$mot_cle.'%'));
$requeteMotsClesImg[] = 'di.mots_cles_texte LIKE '.$requeteMotsCles;
$requeteMotsClesObs[] = 'dob.mots_cles_texte LIKE '.$requeteMotsCles;
}
$requeteMotsClesImg = implode(' AND ', $requeteMotsClesImg);
$requeteMotsClesObs = implode(' AND ', $requeteMotsClesObs);
$masque = '('.
'('.$requeteMotsClesImg.') OR '.
'('.$requeteMotsClesObs.') '.
')';
return $masque;
}
// ??
private function assemblercomptageOccurencesMotsClesCel() {
$chaineMotsClesAffiches = $this->conteneur->getParametre('mots_cles_cel_affiches');
$tabMotsClesAffiches = explode(',',$chaineMotsClesAffiches);
$chaineSql = '';
// Comptage du nombre de mots clés officiels présents dans la chaine mots clés texte
foreach ($tabMotsClesAffiches as $motCle) {
if($chaineSql != '') {
$chaineSql .= ' + ';
}
$chaineSql .= 'IF(FIND_IN_SET('.$this->proteger($motCle).',di.mots_cles_texte) != 0, 1, 0)';
}
return '('.$chaineSql.')';
}
private function getTri() {
$order = '';
if($this->doitJoindreTableVotes()) {
$order = ' GROUP BY dvote.ce_image, dob.id_observation ORDER BY total_votes '.$this->directionTri.', date_transmission desc ';
} else if($this->doitJoindreTableTags()) {
$order = ' GROUP BY doi.id_image ORDER BY total_tags '.$this->directionTri.', date_transmission desc ';
} else {
$order = ' ORDER BY '.$this->tri.' '.$this->directionTri.' ';
}
return $order;
}
/**
* Compter le nombre total d'images dans la base pour affichage dans entete.
* */
private function getFoundRows() {
$requete = 'SELECT FOUND_ROWS() AS nbre ';
$resultats = $this->bdd->recuperer($requete);
return (int) $resultats['nbre'];
}
/**
* En fonction des paramètres, générer les conditions de recherche
* des observations
* */
private function getConditionsObs() {
$conditionsObs = array();
$masques = $this->masque->getMasque();
if (isset($masques['masque'])) {
$passe = $masques['masque'];
// Si on a saisi le masque passe partout, alors on doit chercher dans tous les champs
// de la table observation (OR)
$conditionLibre = array();
if (!isset($masques['masque.ns'])) {
$conditionsLibre[] = "nom_sel LIKE '$passe%'";
}
if (!isset($masques['masque.famille'])) {
$conditionsLibre[] = "famille LIKE '$passe%'";
}
if (!isset($masques['masque.milieu'])) {
$conditionsLibre[] = "nom_sel LIKE '$passe%'";
}
if (!isset($masques['masque.date'])) {
$conditionsLibre[] = $this->creerFiltreDate($passe);
}
if (!isset($masques['masque.auteur'])) {
$conditionsLibre[] = $this->creerFiltreAuteur($passe);
}
/*
* FIXME : remplacer par motcle projet !
* if (!isset($masques['masque.tag'])) {
$conditionsLibre[] = "mots_cles_texte LIKE '%$passe%'";
}*/
$conditionsObs[] = implode(' OR ', $conditionsLibre);
}
 
// referentiel
if (isset($masques['masque.referentiel'])) {
$ref = $masques['masque.referentiel'];
$conditionsObs[] = "dob.nom_referentiel LIKE '$ref%'";
}
// nom sel
if (isset($masques['masque.ns'])) {
$nom_sel = $masques['masque.ns'];
$conditionsObs[] = "nom_sel LIKE '$nom_sel%'";
}
// num nom
if (isset($masques['masque.nn'])) {
$num_noms = $masques['masque.nn'];
$num_noms = explode(',', $num_noms);
$num_noms = array_map('intval', $num_noms);
$num_noms = array_filter($num_noms);
$num_noms = implode(',', $num_noms);
$conditionsObs[] = "(nom_sel_nn IN ($num_noms) OR nom_ret_nn IN ($num_noms)) ";
}
// num taxon
if (isset($masques['masque.nt'])) {
$num_taxon = $masques['masque.nt'];
$conditionsObs[] = 'nt = '.intval($num_taxon);
}
// famille
if (isset($masques['masque.famille'])) {
$famille = $masques['masque.famille'];
$conditionsObs[] = "famille LIKE '$famille%'";
}
// genre
if (isset($masques['masque.genre'])) {
$genre = $masques['masque.genre'];
$conditionsObs[] = "nom_sel LIKE '$genre%'";
}
// milieu
if (isset($masques['masque.milieu'])) {
$milieu = $masques['masque.milieu'];
$conditionsObs[] = "nom_sel LIKE '$milieu%'";
}
// date
if (isset($masques['masque.date'])) {
$date = $masques['masque.date'];
$conditionsObs[] = $this->creerFiltreDate($date);
}
// utilisateur
if (isset($masques['masque.auteur'])) {
$auteur = $masques['masque.auteur'];
$conditionsObs[] = $this->creerFiltreAuteur($auteur);
}
// commune
if (isset($masques['masque.commune'])) {
$commune = $masques['masque.commune'];
$conditionsObs[] = " zone_geo LIKE ".$this->proteger(str_replace(array('-',' '), '_', $commune).'%');
}
// commune
if (isset($masques['masque.departement'])) {
$dept = $masques['masque.departement'];
$conditionsObs[] = $this->creerFiltreIdZoneGeo($dept);
}
if (isset($masques['masque.tag_cel'])) {
$motsCles = $masques['masque.tag_cel'];
$conditionsObs[] = $this->creerFiltreMotsClesCel($motsCles);
}
 
return $conditionsObs;
}
/**
* Obtenir le tableu de chaines de condition de requete images en fonction des masques
* */
private function getConditionsImages() {
$conditionsImg = array();
$masques = $this->masque->getMasque();
if (isset($masques['masque.tag_pictoflora'])) {
$tag = $masques['masque.tag_pictoflora'];
$conditionsImg[] = $this->creerFiltreMotsClesPictoflora($tag);
}
return $conditionsImg;
}
/*-------------------------------------------------------------------------------
CHARGEMENT DES IMAGES
--------------------------------------------------------------------------------*/
/**
* Chargement depuis la bdd de toutes les liaisons entre images et observations
* Méthode appelée uniquement lorsque les paramètres sont vides
* */
private function chargerLiaisonsSimple() {
// On récupère d'abord les N images de del_obs_image, éventuellement triées,
// Et on complète avec les informations des observations associées
$requeteImages = ' SELECT *, di.mots_cles_texte as mots_cles_texte_image '.
' FROM del_obs_image doi '.
' INNER JOIN del_image di ON doi.id_image = di.id_image ';
 
// Si le tri se fait par date d'observation, on récupère les identifiants de N observations triées
if (isset($this->parametres['tri']) && $this->parametres['tri'] == 'date_observation') {
$ordre = isset($this->parametres['ordre']) ? $this->parametres['ordre'] : 'DESC';
$requeteIdObs = ' SELECT doi.id_image as id_image '.
' FROM del_obs_image doi '.
' INNER JOIN del_observation dob ON dob.id_observation = doi.id_observation '.
' INNER JOIN del_image di ON doi.id_image = di.id_image '.
' ORDER BY date_observation '.$ordre.', dob.id_observation '.$ordre;
$requeteIdObs .= $this->gestionBdd->getLimitSql();
// Récupérer les N observations triées par date
$observations = $this->bdd->recupererTous($requeteIdObs . ' -- ' . __FILE__ . ':' . __LINE__);
$idsImages = array();
foreach ($observations as $observation) {
$idsImages[] = $observation['id_image'];
}
$chaineIdImages = implode(',', $idsImages);
$requeteImages .= ' WHERE doi.id_image IN ('.$chaineIdImages.') '.
' GROUP BY doi.id_image, doi.id_observation '.
' ORDER BY FIELD(doi.id_image, '.$chaineIdImages.')'.
' LIMIT '.$this->navigation->getLimite(); // On limite sur le nombre car les obs peuvent avoir plusieurs images
} else {
$requeteImages .= ' GROUP BY doi.id_image, doi.id_observation ';
$requeteImages .= ' ORDER BY doi.id_observation DESC';
$requeteImages .= $this->gestionBdd->getLimitSql();
}
$liaisons = $this->bdd->recupererTous($requeteImages . ' -- ' . __FILE__ . ':' . __LINE__);
// Ce n'est pas la peine de continuer s'il n'y a pas eu de résultats dans la table del_obs_images
if (!empty($liaisons)) {
$idsObservations = array();
foreach ($liaisons as $image) {
$idObs = $image['id_observation'];
$idsObservations[$idObs] = $idObs;
}
$chaineIdObs = implode(',', $idsObservations);
// On récupère les observations qui complètent la requête précédente
$requeteObservations = ' SELECT * '.
' FROM del_observation dob '.
' LEFT JOIN del_utilisateur du ON dob.ce_utilisateur = du.id_utilisateur '.
' WHERE id_observation IN ('.$chaineIdObs.')';
$resultatsObservations = $this->bdd->recupererTous($requeteObservations . ' -- ' . __FILE__ . ':' . __LINE__);
// FIXME : Ca ne doit pas arriver, mais que se passe-t-il s'il n'y a pas d'observation pour l'image ?!
// On range les observations dans un tableau pour pouvoir les retrouver par leur id :
$observations = array();
foreach ($resultatsObservations as $id => $observation) {
$idObs = $observation['id_observation'];
$observations[$idObs] = $observation;
}
// Enfin, pour chaque image préalablement récupérées, on complète avec les informations de l'observation
// FIXME : peut-être peut-on utiliser un array_merge ici ?
foreach ($liaisons as $id => $liaison) {
$idObs = $liaison['id_observation'];
$observation = $observations[$idObs];
foreach ($observation as $cle => $valeur) {
$liaisons[$id][$cle] = $valeur;
}
}
// On compte à part les images issues de la jointure de del_obs_image et del_image car la fonction
// SQL_CALC_FOUND_ROWS dans la fonction requete image fait passer le temps d'éxécution de 0.0011 à 15s !
$requeteNbImages = 'SELECT SUM(t.nb) as nb FROM (SELECT count(DISTINCT doi.id_image) as nb '.
'FROM del_obs_image doi '.
'INNER JOIN del_image di '.
'ON di.id_image = doi.id_image '.
'GROUP BY doi.id_image, doi.id_observation) t ';
$resultatNbImages = $this->bdd->recupererTous($requeteNbImages . ' -- ' . __FILE__ . ':' . __LINE__);
 
$total = (int) $resultatNbImages[0]['nb'];
$this->navigation->setTotal($total);
}
 
return $liaisons;
}
 
/**
* Charge les liaisons pour une seule image dont l'id est spécifié dans l'URL
* Copie de chargerLiaisonsObs avec critère sur l'id_image uniquement
* Supporte seulement le masque sur referentiel
*/
private function chargerLiaisonsParId() {
 
$idImage = $this->ressources[0];
 
// Récupérer les liaisons
$requeteObs = ' SELECT SQL_CALC_FOUND_ROWS dob.id_observation as id_observation, dob.nom_referentiel, nom_sel, nom_sel_nn, nt, famille, ce_zone_geo, zone_geo, lieudit, station, milieu, '.
' date_observation, dob.mots_cles_texte as mots_cles_texte, dob.commentaire as commentaire, di.mots_cles_texte as mots_cles_texte_image , date_transmission, '.
' doi.id_image as id_image, di.ce_utilisateur as ce_utilisateur, prenom, nom, courriel, dob.prenom_utilisateur, dob.nom_utilisateur, dob.courriel_utilisateur, nom_original '.
'FROM del_observation dob '.
' INNER JOIN del_obs_image doi ON dob.id_observation = doi.id_observation '.
' INNER JOIN del_image di ON doi.id_image = di.id_image '.
' LEFT JOIN del_utilisateur du ON dob.ce_utilisateur = du.id_utilisateur '.
' WHERE doi.id_image = '.intval($idImage);
 
if (isset($this->parametres['masque.referentiel'])) {
$requeteObs .= " AND dob.nom_referentiel LIKE '" . $this->parametres['masque.referentiel'] . "%'";
}
 
$observations = $this->bdd->recupererTous($requeteObs . ' -- ' . __FILE__ . ':' . __LINE__);
 
$total = $this->getFoundRows();
$this->navigation->setTotal($total);
 
return $observations;
}
 
/**
* Chargement depuis la bdd de toutes les liaisons entre images et observations
* Méthode appelée uniquement lorsque les paramètres concernent une observation
* */
private function chargerLiaisonsObs() {
// Récupérer les liaisons
$requeteObs = ' SELECT SQL_CALC_FOUND_ROWS dob.id_observation as id_observation, dob.nom_referentiel, nom_sel, nom_sel_nn, nt, famille, ce_zone_geo, zone_geo, lieudit, station, milieu, '.
' date_observation, dob.mots_cles_texte as mots_cles_texte, dob.commentaire as commentaire, di.mots_cles_texte as mots_cles_texte_image , date_transmission, '.
' doi.id_image as id_image, di.ce_utilisateur as ce_utilisateur, prenom, nom, courriel, dob.prenom_utilisateur, dob.nom_utilisateur, dob.courriel_utilisateur, nom_original '.
'FROM del_observation dob '.
' INNER JOIN del_obs_image doi ON dob.id_observation = doi.id_observation '.
' INNER JOIN del_image di ON doi.id_image = di.id_image '.
' LEFT JOIN del_utilisateur du ON dob.ce_utilisateur = du.id_utilisateur ';
// Récupérer les conditions sous forme de tableau
$conditionsObs = $this->getConditionsObs();
if (!empty($conditionsObs)) {
$where = ' WHERE '.implode(' AND ', $conditionsObs);
$requeteObs .= $where;
}
// Gérer le tri (uniquement si c'est date_observation)
if (isset($this->parametres['tri']) && $this->parametres['tri'] == 'date_observation') {
$ordre = isset($this->parametres['ordre']) ? $this->parametres['ordre'] : 'DESC';
$tri = ' ORDER BY '.$this->parametres['tri'].' '.$ordre.', doi.id_observation '.$ordre.' ';
$requeteObs .= $tri;
}
$requeteObs .= $this->gestionBdd->getLimitSql();
$observations = $this->bdd->recupererTous($requeteObs . ' -- ' . __FILE__ . ':' . __LINE__);
 
$total = $this->getFoundRows();
$this->navigation->setTotal($total);
 
return $observations;
}
/**
* Chargement depuis la bdd de toutes les liaisons entre images et observations
* Méthode appelée uniquement lorsque les paramètres concernent les images
* */
private function chargerLiaisonsImages() {
// FIXME : si on faisait une requete à part pour compter, ca irait plus vite
// Récupérer tous les ID d'image en fonction des paramètres de recherche
$requeteImages = ' SELECT SQL_CALC_FOUND_ROWS '.
' doi.id_image as id_image, dob.id_observation as id_observation, dob.nom_referentiel, nom_sel, nom_sel_nn, nt, famille, ce_zone_geo, zone_geo, lieudit, station, milieu, '.
' date_observation, dob.mots_cles_texte as mots_cles_texte, dob.commentaire as commentaire, di.mots_cles_texte as mots_cles_texte_image , date_transmission, '.
' di.ce_utilisateur as ce_utilisateur, prenom, nom, courriel, dob.prenom_utilisateur, dob.nom_utilisateur, dob.courriel_utilisateur, nom_original '.
' FROM del_obs_image doi '.
' INNER JOIN del_image di ON doi.id_image = di.id_image '.
' INNER JOIN del_observation dob ON dob.id_observation = doi.id_observation '.
' LEFT JOIN del_image_tag dit ON dit.ce_image = di.id_image '.
' LEFT JOIN del_utilisateur du ON du.id_utilisateur = di.ce_utilisateur ';
 
$conditionsImg = $this->getConditionsImages();
 
if (!empty($conditionsImg)) {
$where = ' WHERE ('.implode(' OR ', $conditionsImg).') ';
$where .= ' AND dit.actif = 1 ';
$requeteImages .= $where;
}
// Gérer le tri, sur les votes ou sur les tags
if (isset($this->parametres['tri'])) {
$chaineTri = '';
$chaineOrdre = '';
if ($this->parametres['tri'] == 'votes') {
$protocole = isset($this->parametres['protocole']) ? $this->parametres['protocole'] : 1;
$requeteVotes = ' SELECT doi.id_image as id_image, IF(divo.ce_protocole = '.$protocole.', AVG(divo.valeur), 0) as total_votes '.
' FROM del_obs_image doi '.
' INNER JOIN del_image di ON doi.id_image = di.id_image '.
' INNER JOIN del_observation dob ON dob.id_observation = doi.id_observation '.
' LEFT JOIN del_image_vote divo ON doi.id_image = divo.ce_image '.
' AND ce_protocole = '.$protocole.' ';
// Et si on a cherché par tag ?
if (isset($this->parametres['masque.tag'])) {
$tag = $this->parametres['masque.tag'];
$requeteVotes .= ' LEFT JOIN del_image_tag dit ON dit.ce_image = di.id_image ';
$requeteVotes .= " WHERE (dit.tag_normalise LIKE '$tag%' OR di.mots_cles_texte LIKE '%$tag%') AND dit.actif = 1 ";
}
$requeteVotes .= ' GROUP BY doi.id_image, doi.id_observation '.
' ORDER by total_votes '.$this->directionTri .', doi.id_observation '.$this->directionTri.' '.
$this->gestionBdd->getLimitSql();
 
$resultatsVotes = $this->bdd->recupererTous($requeteVotes . ' -- ' . __FILE__ . ':' . __LINE__);
$tabVotes = array();
foreach ($resultatsVotes as $vote) {
$tabVotes[] = $vote['id_image'];
}
$strVotes = empty($tabVotes) ? "''" : implode(',', $tabVotes);
// Et si on a cherché par tag ?
if (isset($this->parametres['masque.tag'])) {
$chaineTri .= ' AND ';
} else {
$chaineTri .= ' WHERE ';
}
$chaineTri .= ' doi.id_image IN ('.$strVotes.') ';
$chaineOrdre = ' ORDER BY FIELD(doi.id_image, '.$strVotes.') ';
}
if ($this->parametres['tri'] == 'tags') {
$requetetags = ' SELECT SQL_CALC_FOUND_ROWS doi.id_image, COUNT(id_tag) as total_tags '.
' FROM del_obs_image doi LEFT JOIN del_image_tag dit ON dit.ce_image = doi.id_image AND dit.actif = 1 '.
' INNER JOIN del_image di ON doi.id_image = di.id_image '.
' INNER JOIN del_observation dob ON dob.id_observation = doi.id_observation ';
 
if (isset($this->parametres['masque.tag_pictoflora'])) {
// Et si on a cherché par tag ?
$tag = $this->parametres['masque.tag_pictoflora'];
$requetetags .= " WHERE (dit.tag_normalise LIKE '$tag%' OR di.mots_cles_texte LIKE '%$tag%') ";
}
$requetetags .= ' GROUP BY doi.id_image, doi.id_observation '.
' ORDER by total_tags '.$this->directionTri.', doi.id_observation '.$this->directionTri.
$this->gestionBdd->getLimitSql();
 
$resultatstags = $this->bdd->recupererTous($requetetags . ' -- ' . __FILE__ . ':' . __LINE__);
$tabtags = array();
foreach ($resultatstags as $tag) {
$tabtags[] = $tag['id_image'];
}
$strtags = empty($tabtags) ? "''" : implode(',', $tabtags);
// Et si on a cherché par tag ?
if (isset($this->parametres['masque.tag_pictoflora'])) {
$chaineTri .= ' AND ';
} else {
$chaineTri .= ' WHERE ';
}
$chaineTri .= ' doi.id_image IN ('.$strtags.') ';
$chaineOrdre = ' ORDER BY FIELD(doi.id_image, '.$strtags.') ';
}
$requeteImages .= $chaineTri.' GROUP BY doi.id_image, doi.id_observation '.$chaineOrdre;
} else {
$requeteImages .= ' GROUP BY doi.id_image, doi.id_observation'; // des fois, on a plusieurs observations pour la même image ...
$requeteImages .= $this->gestionBdd->getLimitSql();
}
 
$retour = $this->bdd->recupererTous($requeteImages . ' -- ' . __FILE__ . ':' . __LINE__);
$total = $this->getFoundRows();
$this->navigation->setTotal($total);
return $retour;
}
/**
* Chargement depuis la bdd de toutes les liaisons entre images et observations
* */
private function chargerLiaisons() {
$champs = array('dob.id_observation as id_observation', 'nom_sel', 'nom_sel_nn', 'nt', 'famille', 'dob.nom_referentiel', 'ce_zone_geo', 'zone_geo',
'lieudit', 'station', 'milieu', 'date_observation', 'dob.mots_cles_texte as mots_cles_texte', 'dob.commentaire as commentaire',
'di.mots_cles_texte as mots_cles_texte_image ', 'date_transmission', 'di.id_image as id_image', 'di.ce_utilisateur as ce_utilisateur',
'prenom', 'nom', 'courriel', 'dob.prenom_utilisateur', 'dob.nom_utilisateur', 'dob.courriel_utilisateur', 'nom_original');
// Attention le LEFT JOIN est indispensable pour ramener les images n'ayant pas de votes
// en cas de tri par votes
$requeteLiaisons = 'SELECT DISTINCT SQL_CALC_FOUND_ROWS '.implode(', ',$champs).' '.
($this->doitJoindreTableVotes() ?
', IF(dvote.ce_protocole = '.$this->parametres['protocole'].', AVG(dvote.valeur), 0) as total_votes ' :
''
).
($this->doitJoindreTableTags() ?
// attention le DISTINCT est indispensable !
', (COUNT(DISTINCT dtag.id_tag) + '.$this->assemblercomptageOccurencesMotsClesCel().') as total_tags ' :
''
).
'FROM '.$this->gestionBdd->formaterTable('del_obs_image', 'doi').
'INNER JOIN del_image di '.
'ON doi.id_image = di.id_image '.
'INNER JOIN del_observation dob '.
'ON doi.id_observation = dob.id_observation '.
'LEFT JOIN del_utilisateur du '.
'ON du.id_utilisateur = di.ce_utilisateur '.
($this->doitJoindreTableTags() ?
'LEFT JOIN del_image_tag dtag '.
'ON doi.id_image = dtag.ce_image AND dtag.actif = 1 ' :
''
).
($this->doitJoindreTableVotes() ?
'LEFT JOIN del_image_vote dvote '.
'ON doi.id_image = dvote.ce_image AND dvote.ce_protocole = '.$this->parametres['protocole'] :
''
);
$requeteLiaisons .= $this->chargerClauseWhere();
$requeteLiaisons .= $this->getTri();
$requeteLiaisons .= $this->gestionBdd->getLimitSql();
 
$retour = $this->bdd->recupererTous($requeteLiaisons . ' -- ' . __FILE__ . ':' . __LINE__);
$total = $this->getFoundRows();
$this->navigation->setTotal($total);
return $retour;
}
/**
* Retourner un tableau d'images formaté en fonction des liaisons trouvées
* @param $liaisons les liaisons de la table del_obs_images
* */
private function chargerImage($liaisons) {
$images = array();
foreach ($liaisons as $liaison) {
$idImage = $liaison['id_image'];
if($liaison['ce_utilisateur'] == 0) {
$liaison['prenom'] = $liaison['prenom_utilisateur'];
$liaison['nom'] = $liaison['nom_utilisateur'];
}
// On enregistre l'ID de l'image pour n'effectuer qu'une seule requête par la suite
$this->imageIds[] = $idImage;
$index = $liaison['id_image'].'-'.$liaison['id_observation'];
$images[$index] = array('id_image' => $idImage, 'binaire.href' => $this->formaterLienImage($idImage),
'protocoles_votes' => array(),
'mots_cles_texte' => $liaison['mots_cles_texte_image'], 'observation' => $this->formaterObservation($liaison));
}
return $images;
}
/**
* Charger les votes pour chaque image
* */
private function chargerVotes($images) {
$requeteVotes = 'SELECT v.*, p.* FROM '.
$this->gestionBdd->formaterTable('del_image_vote', 'v').
' INNER JOIN del_image_protocole p '.
'ON v.ce_protocole = p.id_protocole '.
$this->chargerClauseWhereVotes();
$resultatsVotes = $this->bdd->recupererTous($requeteVotes . ' -- ' . __FILE__ . ':' . __LINE__);
//TODO : faire une méthode formater vote
$votes = $this->formaterVotes($resultatsVotes);
foreach ($images as $id => $image) {
if (isset($votes[$image['id_image']])) {
$images[$id]['protocoles_votes'] = $votes[$image['id_image']];
}
}
return $images;
}
private function chargerClauseWhereVotes() {
if (sizeof($this->imageIds) > 0) {
$chaineImageIds = implode(',', $this->imageIds);
$where[] = 'v.ce_image IN ('.$chaineImageIds.')';
}
if (isset($this->parametres['protocole'])) {
$where[] = 'v.ce_protocole = '.$this->proteger($this->parametres['protocole']);
}
$where = (!empty($where)) ? 'WHERE '.implode(' AND ', $where) : '';
return $where;
}
/**************************************************************************************
* FONCTION DE CONFIGURATION ET UTILITAIRES *
***************************************************************************************/
/**
* Enregistrer dans les variables de classe les paramètres et ressources
* @param $ressources
* @param $parametres de recherche
* */
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
/**
* Configuration du service en fonction du fichier de config config_del.ini
* */
public function configurer() {
$this->mappingFiltre = $this->conteneur->getParametre('mapping_masque');
$this->mappingObservation = $this->conteneur->getParametre('mapping_observation');
$this->mappingVotes = $this->conteneur->getParametre('mapping_votes');
}
/**
* Vérifier que le service est bien configuré
* */
public function verifierConfiguration() {
$erreurs = array();
$tableauImages = $this->conteneur->getParametre('images');
if (empty($tableauImages)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [images] ou celui-ci est vide ;';
} else {
if ($this->conteneur->getParametre('url_service') == null) {
$erreurs[] = '- paramètre "url_service" manquant ;';
}
if ($this->conteneur->getParametre('url_images') == null) {
$erreurs[] = '- paramètre "url_images" manquant ;';
}
}
if (empty($this->mappingObservation)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [mapping_observation] ou celui-ci est vide ;';
} else {
$champsMappingObs = array('id_observation', 'date_observation', 'date_transmission', 'famille', 'nom_sel', 'nom_sel_nn', 'nt',
'ce_zone_geo', 'lieudit', 'station', 'milieu', 'ce_utilisateur', 'nom', 'prenom');
foreach ($champsMappingObs as $champ) {
if (!isset($this->mappingObservation[$champ])) {
$erreurs[] = '- le mapping du champ "'.$champ.'" pour l\'observation est manquant ;';
}
}
}
if (empty($this->mappingFiltre)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [mapping_masque] ou celui-ci est vide ;';
} else {
$champsMappingFiltre = array('famille', 'ns', 'nn', 'date', 'tag', 'commune');
foreach ($champsMappingFiltre as $champ) {
if (!isset($this->mappingFiltre[$champ])) {
$erreurs[] = '- le mapping du champ "'.$champ.'" pour l\'observation est manquant ;';
}
}
}
$tris_possibles = $this->conteneur->getParametre('tris_possibles');
if (empty($tris_possibles)) {
$erreurs[] = '- le fichier de configuration ne contient pas le parametre tris_possibles ou celui-ci est vide ;';
}
if (!empty($erreurs)) {
$e = 'Erreur lors de la configuration : '."\n";
$e .= implode("\n", $erreurs);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
/**
* Verifier que les paramètres de tri sont bien autorisés et qu'ils sont au bon format.
*/
private function verifierParametresTri() {
$erreurs = array();
$tris_possibles = $this->conteneur->getParametre('tris_possibles');
$tris_possibles_tableau = explode(',', $tris_possibles);
if(isset($this->parametres['tri']) && !in_array($this->parametres['tri'], $tris_possibles_tableau)) {
$erreurs[] = '- le type de tri demandé est incorrect, les valeurs possibles sont '.$tris_possibles.' ;';
}
if(isset($this->parametres['tri']) && $this->parametres['tri'] == "votes") {
if(!isset($this->parametres['protocole']) || !is_numeric($this->parametres['protocole'])) {
$erreurs[] = '- Le paramètre protocole est obligatoire en cas de tri par vote et doit être un entier ;';
}
}
$directions_tri = array('asc', 'desc');
if(isset($this->parametres['ordre']) && !in_array($this->parametres['ordre'], $directions_tri)) {
$erreurs[] = '- la direction du tri demandé est incorrecte, les valeurs supportées sont asc ou desc ;';
}
if (!empty($erreurs)) {
$e = 'Erreur lors de l\'analyse des parametres du tri : '."\n";
$e .= implode("\n", $erreurs);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
private function verifierParametreFormatRetour() {
$erreurs = array();
$formats_possibles_str = $this->conteneur->getParametre('formats_possibles');
$formats_possibles = explode(',',$formats_possibles_str);
 
if(isset($this->parametres['format']) && !in_array($this->parametres['format'], $formats_possibles)) {
$erreurs[] = "- le format d'image demandé n'est pas supporté ; Les format supportés sont : ".$formats_possibles_str;
}
if (!empty($erreurs)) {
$e = 'Erreur lors de l\'analyse du format de retour demandé : '."\n";
$e .= implode("\n", $erreurs);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
private function initialiserFormatRetour() {
$this->formatRetour = isset($this->parametres['format']) ? $this->parametres['format'] : $this->formatRetour;
}
 
/**
* Initialiser les variables de tri depuis les paramètres
* */
private function initialiserTri() {
$this->tri = isset($this->parametres['tri']) ? $this->parametres['tri'] : $this->tri;
$this->directionTri = isset($this->parametres['ordre']) ? $this->parametres['ordre'] : $this->directionTri;
}
/** Pour eviter les requêtes trop gourmandes, on supprime les caractères passe-partout
* @param les paramètres de l'application
* */
public function nettoyerParametres($parametres) {
$parametresRetour = array();
foreach ($parametres as $cle => $valeur) {
$valSansPourcent = trim($valeur, "% ");
if ($valSansPourcent != '') {
$parametresRetour[$cle] = $valeur;
}
}
return $parametresRetour;
}
/**
* Nettoyer les jokers
* @param la valeur du masque
* */
private function remplacerParJokerCaractere($valeurMasque) {
return str_replace(array('-',' '), '_', $valeurMasque);
}
 
//TODO: déplacer les fonctions ci dessus et dessous dans une classe
// utilitaire
/**
* Supprimer les accents des chaines de caractères
* */
function supprimerAccents($str, $charset='utf-8')
{
$str = htmlentities($str, ENT_NOQUOTES, $charset);
$str = preg_replace('#&([A-za-z])(?:acute|cedil|circ|grave|orn|ring|slash|th|tilde|uml);#', '\1', $str);
$str = preg_replace('#&([A-za-z]{2})(?:lig);#', '\1', $str); // pour les ligatures e.g. '&oelig;'
$str = preg_replace('#&[^;]+;#', '', $str); // supprime les autres caractères
return $str;
}
/**
* Normaliser en supprimant les accents et en mettant en minuscule
* @param $mot_cle le mot recherché
* */
private function normaliserMotCle($mot_cle) {
return mb_strtolower($this->supprimerAccents(trim($mot_cle)));
}
/**
* Récupérer le numéro du département d'un fichier de configuration
* */
private function obtenirIdDepartement($nomDpt) {
$nomDpt = $this->supprimerAccents($nomDpt);
$nomDpt = strtolower(str_replace(' ','-',$nomDpt));
$idDpt = $this->conteneur->getParametre($nomDpt);
if($idDpt == null || $idDpt == ' ') {
$idDpt = ' ';
}
return $idDpt;
}
/**
* Obtenir le type de requête à exécuter en fonction des paramètres de recherche
* @param $parametres les paramètres de l'application
* */
private function getTypeRequete($ressources, $parametres) {
 
// une image par id
if ((count($ressources) == 1) && is_numeric($ressources[0])) {
return 'id';
}
 
$typeRequete = 'simple';
// Dans ce cas précis, les informations concernant le depart, la limite ou l'ordre ne
// rentre pas en compte dans le type de requête ; ce ne sont que des compléments.
unset($parametres['navigation.depart']);
unset($parametres['navigation.limite']);
unset($parametres['ordre']);
// En revanche, chaque masque est associé à un type de requête particulier.
$masquesObservation = array('masque', 'masque.departement', 'masque.ns', 'masque.genre', 'masque.date', 'masque.commune', 'masque.famille', 'masque.auteur', 'masque.nn', 'masque.referentiel', 'masque.tag_cel');
$masquesImage = array('masque', 'masque.tag_pictoflora');
// Le type de requête est défini par les tables qu'il doit inclure (observation, image, ou les deux)
$requeteSimple = false;
$pourObservation = false;
$pourImage = false;
// S'il n'y a aucun paramètre, on lance une requête simple
if (empty($parametres)) {
$requeteSimple = true;
}
// Si l'un des masques demandé concerne l'observation
foreach ($masquesObservation as $masque) {
if (isset($parametres[$masque])) {
$pourObservation = true;
break;
}
}
// Si l'un des masques demandé concerne les images
foreach ($masquesImage as $masque) {
if (isset($parametres[$masque])) {
$pourImage = true;
break;
}
}
// Selon les tri
if (isset($parametres['tri'])) {
switch ($parametres['tri']) {
case 'votes' :
case 'tags' :
$pourImage = true;
break;
default : //case 'date_observation' :
if (sizeof($parametres) > 1) {
$pourObservation = true;
}
}
}
// Vérifier la combinaison des booléens pour en déduire le type de requête
if ($pourObservation && $pourImage) {
$typeRequete = 'obs-images';
} else {
if ($pourImage) {
$typeRequete = 'images';
} else if ($pourObservation) {
$typeRequete = 'obs';
} else { // if ($requeteSimple)
$typeRequete = 'simple';
}
}
return $typeRequete;
}
private function doitJoindreTableVotes() {
return ($this->tri == 'votes');
}
private function doitJoindreTableTags() {
return ($this->tri == 'tags');
}
 
/*-------------------------------------------------------------------------------
FORMATER ET METTRE EN FORME
--------------------------------------------------------------------------------*/
/**
* Formater une observation depuis une ligne liaison
* @param $liaison liaison issue de la recherche
* @return $observation l'observation mise en forme
* */
private function formaterObservation($liaison) {
$observation = array();
foreach ($this->mappingObservation as $nomOriginal => $nomFinal) {
$observation[$nomFinal] = $liaison[$nomOriginal];
}
 
return $observation;
}
/**
* Formater une observation depuis une ligne liaison
* @param $liaison liaison issue de la recherche
* @return $observation l'observation mise en forme
* */
private function formaterVotes($votes) {
$retour = array();
foreach ($votes as $vote) {
$retour_vote = array();
foreach ($vote as $param=>$valeur) {
if (strpos($this->mappingVotes[$param], 'protocole.') === 0) {
$retour_protocole[$this->mappingVotes[$param]] = $valeur;
} else {
$retour_vote[$this->mappingVotes[$param]] = $valeur;
}
}
if (!isset($retour[$vote['ce_image']][$vote['ce_protocole']])) {
$retour[$vote['ce_image']][$vote['ce_protocole']] = $retour_protocole;
}
$retour[$vote['ce_image']][$vote['ce_protocole']]['votes'][$vote['id_vote']] = $retour_vote;
}
return $retour;
}
/**
* Formater le lien de l'image en fonction du fichier de config et de l'identifiant de l'image
* */
private function formaterLienImage($idImage) {
$idImage = sprintf('%09s', $idImage);
$url = $this->conteneur->getParametre('url_images');
$urlImage = sprintf($url, $idImage, $this->formatRetour);
return $urlImage;
}
private function proteger($valeur) {
if (is_array($valeur)) {
return $this->bdd->protegerTableau($valeur);
} else {
return $this->bdd->proteger($valeur);
}
}
}
?>
/tags/v1.1-helium/services/modules/0.1/images/VotesImage.php
New file
0,0 → 1,332
<?php
// declare(encoding='UTF-8');
/**
* Le web service image récupère toutes les données de la table del_obs_images
* pour retourner une liste d'images associée à une observation
*
* @category php 5.2
* @package del
* @subpackage images
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images
*/
 
class VotesImage {
private $imageIds = array();
private $conteneur;
private $navigation;
private $masque;
protected $gestionBdd;
protected $bdd;
private $ressources;
private $parametres;
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_votes.ini');
$this->conteneur->chargerConfiguration('config_mapping_votes.ini');
$this->navigation = $conteneur->getNavigation();
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
/**
* Méthode principale de la classe.
* Lance la récupération des images dans la base et les place dans un objet ResultatService
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function consulter($ressources, $parametres) {
// Gestion des configuration du script
$this->ressources = $ressources;
$this->parametres = $parametres;
$this->configurer();
$this->verifierConfiguration();
// Lancement du service
$votes = $this->chargerVotes();
$total = $this->compterVotes();
$this->navigation->setTotal($total);
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
$resultat->corps = array('entete' => $this->conteneur->getEntete(), 'resultats' => $votes);
return $resultat;
}
public function ajouter($ressources, $parametres) {
$this->verifierParametresAjoutModif($ressources, $parametres);
$insertion = 'INSERT INTO del_image_vote '.
'(ce_image, ce_protocole, ce_utilisateur, valeur, date) '.
'VALUES ('.
$this->proteger($ressources[0]).','.
$this->proteger($parametres['protocole']).','.
$this->proteger($parametres['utilisateur']).','.
$this->proteger($parametres['valeur']).', '.
'NOW()'.
');';
 
$resultat = $this->bdd->requeter($insertion);
if ($resultat == false) {
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
} else {
$retour = $this->bdd->recupererIdDernierAjout();
$resultat = new ResultatService();
$resultat->corps = array('id_vote' => $retour);
self::updateStats($this->bdd, $ressources[0],$parametres['protocole']);
 
return $resultat;
}
}
public function modifier($ressources, $parametres) {
$this->verifierParametresAjoutModif($ressources, $parametres);
//TODO: est il nécessaire de tester si ça existe et renoyer une erreur 404
// si l'on vote ? Cela peut ralentir considérablement les choses
// une contrainte d'unicité sur le triplet image, protocole, vote existe,
// ça suffira pour provoquer une erreur 500
$modification = 'UPDATE del_image_vote '.
'SET valeur = '.$this->proteger($parametres['valeur']).', '.
' date = NOW() '.
'WHERE '.
'ce_image = '.$this->proteger($ressources[0]).' AND '.
'ce_protocole = '.$this->proteger($parametres['protocole']).' AND '.
'ce_utilisateur = '.$this->proteger($parametres['utilisateur']).' ';
$resultat = $this->bdd->requeter($modification);
if ($resultat == false) {
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
} else {
self::updateStats($this->bdd, $ressources[0],$parametres['protocole']);
RestServeur::envoyerEnteteStatutHttp(RestServeur::HTTP_CODE_OK);
}
}
public function supprimer($ressources) {
$id_image = $ressources[0];
$id_vote = $ressources[2];
$id_vote_p = $this->proteger($id_vote);
 
$requete_infos_vote = 'SELECT * FROM del_image_vote '.
'WHERE id_vote = '.$id_vote_p;
$infos_vote = $this->bdd->recuperer($requete_infos_vote);
if ($infos_vote == false) {
throw new Exception("Aucun vote ne correspond à cet identifiant", RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
}
$controle_acces = new ControleAcces($this->conteneur);
$utilisateur = $controle_acces->getInfosUtilisateurConnecte();
if($utilisateur['id_utilisateur'] != $infos_vote['ce_utilisateur'] &&
$controle_acces->getIdAnonymeTemporaire() != $infos_vote['ce_utilisateur']) {
throw new Exception("Vous n'êtes pas autorisé à supprimer ce vote",
RestServeur::HTTP_CODE_ACCES_NON_AUTORISE);
}
$suppression = 'DELETE FROM del_image_vote '.
'WHERE id_vote = '.$id_vote_p;
$resultat = $this->bdd->requeter($suppression);
if ($resultat == false) {
throw new Exception("Impossible de supprimer le vote", RestServeur::HTTP_CODE_ERREUR);
} else {
self::updateStats($this->bdd, $ressources[0],$infos_vote['ce_protocole']);
}
}
static function updateStats($db, $id_image, $id_proto) {
$id_image = intval($id_image);
$id_proto = intval($id_proto);
if(!$id_image || !$id_proto) throw new Exception("Ne peut mettre à jour les statistiques de vote",
RestServeur::HTTP_CODE_ERREUR);
/* REPLACE ... SELECT: réinitalise les champs non-défini (MySQL 5.1)
REPLACE ... SET a=b, c=d: idem ou plusieurs requête
Du coup il faut récupérer les données actuelles mais REPLACE ne le permet pas
(http://dev.mysql.com/doc/refman/5.5/en/replace.html :
You cannot refer to values from the current row and use them in the new row.)
D'où INSERT ... ON DUPLICATE KEY UPDATE. Notons que VALUES() récupère la valeur
*associée* au champ passé en paramètre, c'est à dire VALUES(moyenne) == divo.moyenne */
$db->requeter(sprintf('INSERT INTO del_image_stat (ce_image, ce_protocole, moyenne, nb_votes)'.
' SELECT ce_image, ce_protocole, AVG(valeur) AS moyenne, COUNT(valeur) AS nb_votes'.
' FROM del_image_vote divo'.
' WHERE ce_image = %d AND ce_protocole = %d GROUP BY ce_image, ce_protocole'.
' ON DUPLICATE KEY UPDATE moyenne = VALUES(moyenne), nb_votes = VALUES(nb_votes)',
$id_image, $id_proto));
 
}
 
/*-------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
--------------------------------------------------------------------------------*/
/**
* Configuration du service en fonction du fichier de config config_del.ini
* */
public function configurer() {
$this->mappingFiltre = $this->conteneur->getParametre('mapping_masque');
$this->mappingVotes = $this->conteneur->getParametre('mapping_votes');
}
/**
* Vérifier que le service est bien configuré
* */
public function verifierConfiguration() {
$erreurs = array();
$tableauImages = $this->conteneur->getParametre('images');
if (empty($tableauImages)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [images] ou celui-ci est vide ;';
} else {
if ($this->conteneur->getParametre('url_service') == null) {
$erreurs[] = '- paramètre "url_service" manquant ;';
}
}
 
if (empty($this->mappingVotes)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [mapping_votes] ou celui-ci est vide ;';
} else {
$champsMappingObs = array('ce_protocole','id_vote','valeur','ce_image', 'ce_utilisateur', 'nom', 'prenom');
foreach ($champsMappingObs as $champ) {
if (!isset($this->mappingVotes[$champ])) {
$erreurs[] = '- le mapping du champ "'.$champ.'" pour le vote est manquant ;';
}
}
}
if (!empty($erreurs)) {
$e = 'Erreur lors de la configuration : '."\n";
$e .= implode("\n", $erreurs);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
public function verifierParametresAjoutModif($ressources, $parametres) {
$erreurs = array();
if (!is_numeric($ressources[0])) {
$erreurs[] = '- le paramètre indiquant l\'identifiant de l\'image doit être numérique ;';
}
if (!isset($parametres['utilisateur'])) {
$erreurs[] = '- paramètre "utilisateur" manquant ;';
}
if (!isset($parametres['protocole'])) {
$erreurs[] = '- paramètre "id_protocole" manquant ;';
} else {
if (!is_numeric($parametres['protocole'])) {
$erreurs[] = '- le paramètre "protocole" doit être numérique ;';
}
}
if (!isset($parametres['valeur'])) {
$erreurs[] = '- paramètre "valeur" manquant ;';
} else {
if (!is_numeric($parametres['valeur'])) {
$erreurs[] = '- le paramètre "valeur" doit être numérique ;';
}
}
if (!empty($erreurs)) {
$e = 'Erreur lors de la configuration : '."\n";
$e .= implode("\n", $erreurs);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
public function verifierParametresSuppression($ressources, $parametres) {
$erreurs = array();
if (!is_numeric($ressources[0])) {
$erreurs[] = '- le paramètre indiquant l\'identifiant de l\'image doit être numérique ;';
}
/*if (!is_numeric($parametres['id_protocole'])) {
$erreurs[] = '- le paramètre indiquant l\'identifiant du vote doit être numérique ;';
}*/
if (!empty($erreurs)) {
$e = 'Erreur lors de la configuration : '."\n";
$e .= implode("\n", $erreurs);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
/**
* Charger la clause WHERE en fonction des paramètres de masque
* */
private function chargerClauseWhere() {
$where[] = 'WHERE ce_image = '.$this->proteger($this->ressources[0]);
if (isset($this->parametres['protocole'])) {
$where[] = 'ce_protocole = '.$this->proteger($this->parametres['protocole']);
}
return implode(' AND ', $where);
}
/*-------------------------------------------------------------------------------
CHARGEMENT DES IMAGES
--------------------------------------------------------------------------------*/
/**
* Charger les votes pour chaque image
* */
private function chargerVotes() {
$requeteVotes = 'SELECT * FROM '.
$this->gestionBdd->formaterTable('del_image_vote').
$this->chargerClauseWhere();
$resultatsVotes = $this->bdd->recupererTous($requeteVotes);
$votes = $this->formaterVotes($resultatsVotes);
return $votes;
}
/**
* Compter le nombre total d'images dans la base pour affichage dans entete.
* */
private function compterVotes() {
$requete = 'SELECT FOUND_ROWS() AS nbre ';
$resultats = $this->bdd->recuperer($requete);
return (int) $resultats['nbre'];
}
 
/*-------------------------------------------------------------------------------
FORMATER ET METTRE EN FORME
--------------------------------------------------------------------------------*/
/**
* Formater une observation depuis une ligne liaison
* @param $liaison liaison issue de la recherche
* @return $observation l'observation mise en forme
* */
private function formaterVotes($votes) {
$retour = array();
foreach ($votes as $vote) {
foreach ($vote as $p=>$valeur) {
$retour[$vote['id_vote']][$this->mappingVotes[$p]] = $valeur;
}
}
return $retour;
}
private function proteger($valeur) {
if (is_array($valeur)) {
return $this->bdd->protegerTableau($valeur);
} else {
return $this->bdd->proteger($valeur);
}
}
}
?>
/tags/v1.1-helium/services/modules/0.1/images/ListeImages.php
New file
0,0 → 1,649
<?php
/**
* @author Raphaël Droz <raphael@tela-botanica.org>
* @copyright Copyright (c) 2013, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images
* @see http://www.tela-botanica.org/wikini/identiplante/wakka.php?wiki=IdentiPlante_PictoFlora_MoteurRecherche
*
* Backend pour PictoFlora (del.html#page_recherche_images)
*
*
* == Notes ==
*
* tri=votes et tri=tags: affectent le choix des images affichées (donc getIdImages())
* Cependant ce total ne nous intéresse même pas (MoyenneVotePresenteur.java s'en occupe).
* Seul tri=date_transmission nous évite l'AVG() + GROUP BY
*
* protocole: il affecte l'affichage des information, mais le JSON contient déjà
* l'intégralité (chercher les données de vote pour 1 ou plusieurs protocoles) est quasi-identique.
* Par contre, le tri par moyenne des votes, sous-entend "pour un protocole donné".
* Dès lors le choix d'un protocole doit avoir été fait afin de régler le JOIN et ainsi l'ORDER BY.
* (cf requestFilterParams())
*
* Histoire: auparavant (pré-r142x) un AVG + GROUP BY étaient utilisés pour générer on-the-fly les valeurs
* utilisées ensuite pour l'ORDER BY. La situation à base de del_image_stat
* est déjà bien meilleure sans être pour autant optimale. cf commentaire de sqlAddConstraint()
*
*
* Tags:
* Le comportement habituel dans le masque *général*: les mots sont séparés par des espaces,
* implod()ed par des AND (tous les mots doivent matcher).
* Et le test effectué doit matcher sur:
* %(les tags d'observations)% *OU* %(les tags d'images)% *OU* %(les tags publics)%
*
* Le comportement habituel dans le masque *tag*: les mots ne sont *pas* splittés (1 seule expression),
* Et le test effectué doit matcher sur:
* ^(expression)% *OU* %(expression)% [cf getConditionsImages()]
*
* Par défaut les tags sont comma-separated (OU logique).
* Cependant pour conserver le comportement du masque général qui sous-entend un ET logique sur
* des tags séparés par des espaces recherche
*
* TODO:
* -affiner la gestion de passage de mots-clefs dans le masque général.
* - subqueries dans le FROM pour les critère WHERE portant directement sur v_del_image
* plutôt que dans WHERE (qui nécessite dès lors un FULL-JOIN)
* (http://www.mysqlperformanceblog.com/2007/04/06/using-delayed-join-to-optimize-count-and-limit-queries/)
* - éviter de dépendre d'une jointure systématique sur `cel_obs`, uniquement pour `(date_)transmission
* (cf VIEW del_image)
* - poursuivre la réorganisation des méthodes statiques parmis Observation, ListeObservations et ListeImages2
* - *peut-être*: passer requestFilterParams() en méthode de classe
*
*
* MySQL sux:
* EXPLAIN SELECT id_image FROM v_del_image vdi WHERE vdi.id_image IN (SELECT ce_image FROM del_image_tag WHERE actif = 1 LIMIT 1);
* MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery
* EXPLAIN SELECT * FROM del_image WHERE id_image IN (SELECT 3);
* PRIMARY
* EXPLAIN SELECT * FROM del_image WHERE id_image IN (SELECT MIN(3));
* DEPENDENT SUBQUERY ... ... ... mwarf !
* EXPLAIN SELECT id_image FROM v_del_image vdi WHERE vdi.id_image IN (SELECT ce_image FROM del_image_tag WHERE actif = 1);
* 5.5: MATERIALIZED del_image_tag ALL ce_image NULL NULL NULL 38276 Using where
* 5.1: DEPENDENT SUBQUERY del_image_tag index_subquery ce_image ce_image 8 func 1 Using where
* FORCE INDEX/IGNORE INDEX semble incapable de résoudre le problème de l'optimiseur MySQL
*
*/
 
require_once(dirname(__FILE__) . '/../DelTk.php');
require_once(dirname(__FILE__) . '/../observations/Observation.php');
restore_error_handler();
restore_exception_handler();
error_reporting(E_ALL);
 
// del/services/0.1/images?navigation.depart=0&navigation.limite=12&tri=votes&ordre=desc
// del/services/0.1/images?navigation.depart=0&navigation.limite=12&tri=votes&ordre=desc&masque=plop
// del/services/0.1/images?navigation.depart=0&navigation.limite=12&tri=votes&ordre=desc&protocole=3
// del/services/0.1/images?navigation.depart=0&navigation.limite=12&tri=votes&ordre=desc&protocole=3&masque=plop
 
class ListeImages {
 
// TODO: PHP-x.y, ces variables devrait être des "const"
static $format_image_possible = array('O','CRX2S','CRS','CXS','CS','XS','S','M','L','XL','X2L','X3L');
 
static $tri_possible = array('date_transmission', 'date_observation', 'votes', 'tags');
 
// en plus de ceux dans DelTk
static $parametres_autorises = array('protocole', 'masque.tag_cel', 'masque.tag_pictoflora', 'masque.milieu');
 
static $default_params = array('navigation.depart' => 0, 'navigation.limite' => 10,
'tri' => 'date_transmission', 'ordre' => 'desc',
// spécifiques à PictoFlora:
'format' => 'XL');
 
static $default_proto = 3; // proto par défaut: capitalisation d'img (utilisé uniquement pour tri=(tags|votes))
 
static $mappings = array(
'observations' => array( // v_del_image
"id_observation" => 1,
"date_observation" => 1,
"date_transmission" => 1,
"famille" => "determination.famille",
"nom_sel" => "determination.ns",
"nom_sel_nn" => "determination.nn",
"nom_referentiel" => "determination.referentiel",
"nt" => "determination.nt",
"ce_zone_geo" => "id_zone_geo",
"zone_geo" => 1,
"lieudit" => 1,
"station" => 1,
"milieu" => 1,
"mots_cles_texte" => "mots_cles_texte",
"commentaire" => 1,
"ce_utilisateur" => "auteur.id",
"nom_utilisateur" => "auteur.nom",
"prenom_utilisateur" => "auteur.prenom",
),
'images' => array( // v_del_image
'id_image' => 1,
// l'alias suivant est particulier: in-fine il doit s'appeler mots_cles_texte
// mais nous afin d'éviter un conflit d'alias nous le renommons plus tard (reformateImagesDoubleIndex)
'i_mots_cles_texte' => 1
));
 
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_images.ini');
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
 
public function consulter($ressources, $parametres) {
/* Certes nous sélectionnons ici (nom|prenom|courriel)_utilisateur de cel_obs, mais il ne nous intéressent pas
Par contre, ci-dessous nous prenons i_(nom|prenom|courriel)_utilisateur.
Notons cependant qu'aucun moyen ne devrait permettre que i_*_utilisateur != *_utilisateur
Le propriétaire d'une obs et de l'image associée est *toujours* le même. */
array_walk(self::$mappings['observations'], create_function('&$val, $k', 'if($val==1) $val = $k;'));
array_walk(self::$mappings['images'], create_function('&$val, $k', 'if($val==1) $val = $k;'));
// pour les votes, les mappings de "Observation" nous suffisent
array_walk(Observation::$mappings['votes'], create_function('&$val, $k', 'if($val==1) $val = $k;'));
 
// la nécessité du 'groupby' dépend des 'join's utilisés (LEFT ou INNER) ainsi que de la cardinalité
// de `ce_image` dans ces tables jointes.
// Contrairement à IdentiPlantes, nous n'avons de HAVING pour PictoFlora, mais par contre un ORDER BY
$req = array('select' => array(), 'join' => array(), 'where' => array(), 'groupby' => array(), 'orderby' => array());
 
 
$db = $this->bdd;
 
// filtrage de l'INPUT général, on réutilise 90% de identiplante en terme de paramètres autorisés
// ($parametres_autorises) sauf... masque.type qui fait des modif' de WHERE sur les mots-clefs.
// Évitons ce genre de chose pour PictoFlora et les risques de conflits avec masque.tag
// même si ceux-ci sont improbables (pas d'<input> pour cela).
$params_ip = DelTk::requestFilterParams($parametres,
array_diff(DelTk::$parametres_autorises,
array('masque.type')),
$this->conteneur);
 
// notre propre filtrage sur l'INPUT
$params_pf = self::requestFilterParams($parametres,
array_merge(DelTk::$parametres_autorises,
self::$parametres_autorises));
 
/* filtrage des tags + sémantique des valeurs multiples:
Lorsqu'on utilise masque.tag* pour chercher des tags, ils sont
postulés comme séparés par des virgule, et l'un au moins des tags doit matcher. */
$params_pf['masque.tag_cel'] = DelTk::buildTagsAST(@$parametres['masque.tag_cel'], 'OR', ',');
if(!isset($parametres['masque.tag_pictoflora']) && isset($parametres['masque.tag'])) {
$parametres['masque.tag_pictoflora'] = $parametres['masque.tag'];
}
$params_pf['masque.tag_pictoflora'] = DelTk::buildTagsAST(@$parametres['masque.tag_pictoflora'], 'OR', ',');
 
$params = array_merge(
DelTk::$default_params, // paramètre par défaut Identiplante
self::$default_params, // paramètres par défaut PictoFlora
$params_ip, // les paramètres passés, traités par Identiplante
$params_pf); // les paramètres passés, traités par PictoFlora
 
if(isset($parametres['format'])) {
$params['format'] = $parametres['format'];
}
 
// création des contraintes (génériques de DelTk)
DelTk::sqlAddConstraint($params, $db, $req);
// création des contraintes spécifiques (sur les tags essentiellement)
self::sqlAddConstraint($params, $db, $req, $this->conteneur);
// création des contraintes spécifiques impliquées par le masque général
self::sqlAddMasqueConstraint($params, $db, $req, $this->conteneur);
// l'ORDER BY s'avére complexe
self::sqlOrderBy($params, $db, $req);
 
// 1) grunt-work: *la* requête de récupération des id valides (+ SQL_CALC_FOUND_ROWS)
// $idobs_tab = ListeObservations::getIdObs($params, $req, $db);
$idobs_tab = self::getIdImages($params, $req, $db);
 
// Ce n'est pas la peine de continuer s'il n'y a pas eu de résultats dans la table del_obs_images
if(!$idobs_tab) {
$resultat = new ResultatService();
$resultat->corps = array('entete' => DelTk::makeJSONHeader(0, $params, Config::get('url_service')),
'resultats' => array());
return $resultat;
/*
header('HTTP/1.0 404 Not Found');
// don't die (phpunit)
throw(new Exception()); */
}
 
 
// idobs est une liste (toujours ordonnée) des id d'observations recherchées
$idobs = array_values(array_map(create_function('$a', 'return $a["id_image"];'), $idobs_tab));
$total = $db->recuperer('SELECT FOUND_ROWS() AS c'); $total = intval($total['c']);
 
$liaisons = self::chargerImages($db, $idobs);
/*
// Q&D
$images = array();
$o = new Observation($this->conteneur);
foreach($idobs as $i) {
$images[$i] = $o->consulter(array($i), array('justthrow' => 1));
}
*/
list($images, $images_keyed_by_id_image) = self::reformateImagesDoubleIndex(
$liaisons,
$this->conteneur->getParametre('images.url_images'),
$params['format']);
 
// on charge les votes pour ces images et pour *tous* les protocoles
$votes = Observation::chargerVotesImage($db, $liaisons, NULL);
 
// subtilité, nous passons ici le tableau d'images indexé par id_image qui est bien plus pratique pour
// associer les vote à un tableau, puisque nous ne connaissons pas les id d'observation.
// Mais magiquement (par référence), cela va remplir notre tableau indexé par couple d'id (id_image, id_observation)
// cf reformateImagesDoubleIndex() à qui revient la tâche de créer ces deux versions simultanément lorsque
// c'est encore possible.
if($votes) Observation::mapVotesToImages($votes, $images_keyed_by_id_image);
 
// les deux masques de tags sont transformés en AST dans le processus de construction de la requête.
// Reprenous les paramètres originaux non-nettoyés (ils sont valables car le nettoyage est déterministe)
$params_header = array_merge($params, array_filter(array('masque.tag_cel' => @$parametres['masque.tag_cel'],
'masque.tag_pictoflora' => @$parametres['masque.tag_pictoflora'])));
$resultat = new ResultatService();
$resultat->corps = array('entete' => DelTk::makeJSONHeader($total, $params_header, Config::get('url_service')),
'resultats' => $images);
return $resultat;
}
 
/**
* TODO: partie spécifique liées à la complexité de PictoFlora:
* génération de la clause ORDER BY (génère la valeur de la clef orderby' de $req)
* nécessaire ? tableau sprintf(key (tri) => value (ordre), key => value ...).
* Cependant il est impensable de joindre sur un AVG() des valeurs des votes pour
* *chaque* couple (id_image, protocole) de la base afin de trouver les images
* les "mieux notées", ou bien les images ayant le "plus de tags" (COUNT())
*/
static function sqlOrderBy($p, $db, &$req) {
// parmi self::$tri_possible
if($p['tri'] == 'votes') { // LEFT JOIN sur "dis" ci-dessous
$req['orderby'] = 'dis.moyenne ' . $p['ordre'] . ', dis.nb_votes ' . $p['ordre'];
return;
}
if($p['tri'] == 'tags') { // LEFT JOIN sur "dis" ci-dessous
$req['orderby'] = 'dis.nb_tags ' . $p['ordre'];
return;
}
 
if($p['tri'] == 'date_observation') {
$req['orderby'] = 'date_observation ' . $p['ordre'] . ', id_observation ' . $p['ordre'];
return;
}
 
// tri == 'date_transmission'
// avant cel:r1860, date_transmission pouvait être NULL
// or nous voulons de la consistence (notamment pour phpunit)
$req['orderby'] = 'date_transmission ' . $p['ordre'] . ', id_observation ' . $p['ordre'];
}
 
/*
* in $p: un tableau de paramètres, dont:
* - 'masque.tag_cel': *tableau* de mots-clefs à chercher parmi cel_image.mots_clefs_texte
* - 'masque.tag_pictoflora': *tableau* de mots-clefs à chercher parmi del_image_tag.tag_normalise
* - 'tag_explode_semantic': défini si les éléments sont tous recherchés ou NON
*
* in/ou: $req: un tableau de structure de requête MySQL
*
* Attention, le fait que nous cherchions masque.tag_cel OU/ET masque.tag_cel
* ne dépend pas de nous, mais du niveau supérieur de construction de la requête:
* Soit directement $this->consulter() si des masque.tag* sont passés
* (split sur ",", "AND" entre chaque condition, "OR" pour chaque valeur de tag)
* Soit via sqlAddMasqueConstraint():
* (pas de split, "OR" entre chaque condition) [ comportement historique ]
* équivalent à:
* (split sur " ", "OR" entre chaque condition, "AND" pour chaque valeur de tag)
*
*/
static function sqlAddConstraint($p, $db, &$req, Conteneur $c = NULL) {
// TODO implement dans DelTk ?
if(!empty($p['masque.milieu'])) {
$req['where'][] = 'vdi.milieu LIKE '.$db->proteger('%' . $p['masque.milieu'].'%');
}
 
 
/* Pour le tri par AVG() des votes nous avons toujours un protocole donné,
celui-ci indique sur quels votes porte l'AVG.
(c'est un *vote* qui porte sur un protocole et non l'image elle-même) */
/* TODO: perf problème:
1) SQL_CALC_FOUND_ROWS: fixable en:
- dissociant le comptage de la récup d'id + javascript async
- ou ne rafraîchir le total *que* pour les requête impliquant un changement de pagination
(paramètre booléen "with-total" par exemple)
2) jointure forcées: en utilisant `del_imagè`, nous forçons les 2 premiers
JOIN sur cel_obs_images et cel_obs pour filtrer sur "transmission".
Dénormaliser cette valeur et l'intégrer à `cel_images` ferait économiser cette couteuse
jointure, ... lorsqu'aucun masque portant sur `cel_obs` n'est utilisé
3) non-problème: l'ordre des joins est forcé par l'usage de la vue:
(cel_images/cel_obs_images/cel_obs/del_image_stat)
Cependant c'est à l'optimiseur de définir son ordre préféré. */
if($p['tri'] == 'votes') {
// $p['protocole'] *est* défini (cf requestFilterParams())
// petite optimisation: INNER JOIN si ordre DESC car les 0 à la fin
if($p['ordre'] == 'desc') {
// pas de group by nécessaire pour cette jointure
// PRIMARY KEY (`ce_image`, `ce_protocole`)
$req['join'][] = sprintf('INNER JOIN del_image_stat dis'.
' ON vdi.id_image = dis.ce_image'.
' AND dis.ce_protocole = %d',
$p['protocole']);
} else {
$req['join'][] = sprintf('LEFT JOIN del_image_stat dis'.
' ON vdi.id_image = dis.ce_image'.
' AND dis.ce_protocole = %d',
$p['protocole']);
// nécessaire (dup ce_image dans del_image_stat)
$req['groupby'][] = 'vdi.id_observation';
}
}
 
if($p['tri'] == 'tags') {
$req['join'][] = sprintf('%s JOIN del_image_stat dis ON vdi.id_image = dis.ce_image',
($p['ordre'] == 'desc') ? 'INNER' : 'LEFT');
// nécessaire (dup ce_image dans del_image_stat)
$req['groupby'][] = 'vdi.id_observation';
}
 
// car il ne sont pas traités par la générique requestFilterParams() les clefs "masque.tag_*"
// sont toujours présentes; bien que parfois NULL.
if($p['masque.tag_cel']) {
if(isset($p['masque.tag_cel']['AND'])) {
// TODO: utiliser les tables de mots clefs normaliées dans tb_cel ?
// et auquel cas laisser au client le choix du couteux "%" ?
$tags = $p['masque.tag_cel']['AND'];
array_walk($tags, create_function('&$val, $k, $db',
'$val = sprintf("CONCAT(vdi.mots_cles_texte,vdi.i_mots_cles_texte) LIKE %s",
$db->proteger("%".$val."%"));'),
$db);
$req['where'][] = '(' . implode(' AND ', $tags) . ')';
}
else {
$req['where'][] = sprintf("CONCAT(vdi.mots_cles_texte,vdi.i_mots_cles_texte) REGEXP %s",
$db->proteger(implode('|', $p['masque.tag_cel']['OR'])));
}
}
 
if($p['masque.tag_pictoflora']) {
// inutilisable pour l'instant
// self::sqlAddPictoFloraTagConstraint1($p, $db, $req);
 
// intéressante, mais problème d'optimiseur MySQL 5.5 (dependant subquery)
// self::sqlAddPictoFloraTagConstraint2($p, $db, $req);
 
// approche fiable mais sous-optimale
self::sqlAddPictoFloraTagConstraint3($p, $db, $req);
}
}
 
/* approche intéressante si les deux problèmes suivants peuvent être résolu:
- LEFT JOIN => dup => *gestion de multiples GROUP BY* (car in-fine un LIMIT est utilisé)
- dans le cas d'un ET logique, comment chercher les observations correspondantes ? */
static function sqlAddPictoFloraTagConstraint1($p, $db, &$req) {
// XXX: utiliser tag plutôt que tag_normalise ?
$req['join'][] = 'LEFT JOIN del_image_tag dit ON dit.ce_image = vdi.id_image';
$req['where'][] = 'dit.actif = 1';
$req['groupby'][] = 'vdi.id_image'; // TODO: nécessaire (car dup') mais risque de conflict en cas de tri (multiple GROUP BY)
// XXX: en cas de ET, possibilité du GROUP_CONCAT(), mais probablement sans grand intérêt, d'où une boucle
if(isset($p['masque.tag_pictoflora']['AND'])) {
// TODO/XXX : comment matcher les observations ayant tous les mots-clef passés ?
// ... le LEFT-JOIN n'y semble pas adapté
}
else {
$protected_tags = array();
foreach($p['masque.tag_pictoflora']['OR'] as $tag) $protected_tags[] = $db->proteger(strtolower($tag));
$req['where'][] = sprintf('tag_normalise IN (%s)', implode(',', $protected_tags));
}
}
 
// inutilisé pour l'instant pour cause de soucis d'optimiseur MySQL (cf commentaire en intro)
static function sqlAddPictoFloraTagConstraint2($p, $db, &$req) {
// Note à propos des 4 "@ instruction" ci-dessous (notamment sur recupererTous())
// REGEXP permet un puissant mécanisme de sélection des obs/image à qui sait
// l'utiliser, mais peut sortir une erreur en cas de REGEXP invalide
// ex: REGEX "^(".
// Pour l'heure nous ignorons ce type d'erreur car aucun de nos champ de recherche
// ne peuvent (ou ne devrait) comporter des meta-caractères
// ([])?*+\\
if(isset($p['masque.tag_pictoflora']['AND'])) {
// optimsation: en cas de "AND" on sort() l'input et le GROUP_CONCAT()
// donc nous utilisons des ".*" plutôt que de multiples conditions et "|"
sort($p['masque.tag_pictoflora']['AND']);
$req['where'][] = sprintf("vdi.id_image IN (SELECT ce_image FROM del_image_tag WHERE actif = 1".
" GROUP BY ce_image".
" HAVING GROUP_CONCAT(tag_normalise ORDER BY tag_normalise) REGEXP %s)",
$db->proteger(implode('.*', $p['masque.tag_pictoflora']['AND'])));
}
else {
$req['where'][] = sprintf("vdi.id_image IN (SELECT ce_image FROM del_image_tag WHERE actif = 1".
" GROUP BY ce_image".
" HAVING GROUP_CONCAT(tag_normalise) REGEXP %s)",
$db->proteger(implode('|', $p['masque.tag_pictoflora']['OR'])));
}
}
 
// si l'on est bassiné par les "DEPENDENT SUBQUERY", nous la faisons donc indépendemment via cette fonction
static function sqlAddPictoFloraTagConstraint3($p, $db, &$req) {
if(isset($p['masque.tag_pictoflora']['AND'])) {
// optimsation: en cas de "AND" on sort() l'input et le GROUP_CONCAT()
// donc nous utilisons des ".*" plutôt que de multiples conditions et "|"
sort($p['masque.tag_pictoflora']['AND']);
 
// plutôt que db->connexion->query->fetchColumn(), une API pourrie nous oblige à ...
$ids = @$db->recupererTous(sprintf(
"SELECT ce_image FROM del_image_tag WHERE actif = 1".
" GROUP BY ce_image".
" HAVING GROUP_CONCAT(tag_normalise ORDER BY tag_normalise) REGEXP %s",
$db->proteger(implode('.*', $p['masque.tag_pictoflora']['AND']))));
 
// puis:
$ids = @array_map(create_function('$e', 'return $e["ce_image"];'), $ids);
$ids = !empty($ids) ? implode(',', $ids) : 'SELECT ce_image FROM del_image_tag WHERE false';
$req['where'][] = sprintf("vdi.id_image IN (%s)", $ids);
 
}
else {
$ids = @$db->recupererTous(sprintf(
"SELECT ce_image FROM del_image_tag WHERE actif = 1".
" GROUP BY ce_image".
" HAVING GROUP_CONCAT(tag_normalise) REGEXP %s",
$db->proteger(implode('|', $p['masque.tag_pictoflora']['OR']))));
 
$ids = @array_map(create_function('$e', 'return $e["ce_image"];'), $ids);
$ids = !empty($ids) ? implode(',', $ids) : 'SELECT ce_image FROM del_image_tag WHERE false';
$req['where'][] = sprintf("vdi.id_image IN (%s)", $ids);
}
}
 
static function getIdImages($p, $req, $db) {
return $db->recupererTous(sprintf(
'SELECT SQL_CALC_FOUND_ROWS id_image' .
' FROM v_del_image vdi'.
' %s' . // LEFT JOIN if any
' WHERE %s'. // where-clause ou TRUE
' %s'. // group-by
' ORDER BY %s'.
' LIMIT %d, %d -- %s',
$req['join'] ? implode(' ', array_unique($req['join'])) : '',
$req['where'] ? implode(' AND ', $req['where']) : 'TRUE',
$req['groupby'] ? ('GROUP BY ' . implode(', ', array_unique($req['groupby']))) : '',
$req['orderby'],
$p['navigation.depart'], $p['navigation.limite'], __FILE__ . ':' . __LINE__));
}
 
static function chargerImages($db, $idImg) {
$obs_fields = DelTk::sqlFieldsToAlias(self::$mappings['observations'], NULL);
$image_fields = DelTk::sqlFieldsToAlias(self::$mappings['images'], NULL);
return $db->recupererTous(sprintf('SELECT '.
' CONCAT(id_image, "-", id_observation) AS jsonindex,'.
' %1$s, %2$s FROM v_del_image '.
' WHERE %3$s'.
' -- %4$s',
$obs_fields, $image_fields,
sprintf('id_image IN (%s)', implode(',', $idImg)),
__FILE__ . ':' . __LINE__));
 
}
 
/* "masque" ne fait jamais que faire une requête sur la plupart des champs, (presque) tous traités
de manière identique à la seule différence que:
1) ils sont combinés par des "OU" logiques plutôt que des "ET".
2) les tags sont traités différemment pour conserver la compatibilité avec l'utilisation historique:
Tous les mots-clefs doivent matcher et sont séparés par des espaces
(dit autrement, str_replace(" ", ".*", $mots-clefs-requête) =~ $mots-clefs-mysql)
Pour plus d'information: (ListeObservations|DelTk)::sqlAddMasqueConstraint() */
static function sqlAddMasqueConstraint($p, $db, &$req, Conteneur $c = NULL) {
if(!empty($p['masque'])) {
$or_params = array('masque.auteur' => $p['masque'],
'masque.departement' => $p['masque'],
'masque.commune' => $p['masque'], // TODO/XXX ?
'masque.id_zone_geo' => $p['masque'],
 
/* tous-deux remplacent masque.tag
mais sont traité séparément des requestFilterParams() */
// 'masque.tag_cel' => $p['masque'],
// 'masque.tag_pictoflora' => $p['masque'],
 
'masque.ns' => $p['masque'],
'masque.famille' => $p['masque'],
'masque.date' => $p['masque'],
'masque.genre' => $p['masque'],
'masque.milieu' => $p['masque'],
'masque.tag_cel' => $p['masque'],
'masque.tag_pictoflora' => $p['masque'],
 
// tri est aussi nécessaire car affecte les contraintes de JOIN
'tri' => $p['tri'],
'ordre' => $p['ordre']);
 
/* Cependant les champs spécifiques ont priorité sur le masque général.
Pour cette raison nous supprimons la génération de SQL du masque général sur les
champ spécifiques qui feront l'objet d'un traitement avec une valeur propre. */
if(isset($p['masque.auteur'])) unset($or_params['masque.auteur']);
if(isset($p['masque.departement'])) unset($or_params['masque.departement']);
if(isset($p['masque.commune'])) unset($or_params['masque.commune']);
if(isset($p['masque.id_zone_geo'])) unset($or_params['masque.id_zone_geo']);
if(isset($p['masque.ns'])) unset($or_params['masque.ns']);
if(isset($p['masque.famille'])) unset($or_params['masque.famille']);
if(isset($p['masque.date'])) unset($or_params['masque.date']);
if(isset($p['masque.genre'])) unset($or_params['masque.genre']);
if(isset($p['masque.milieu'])) unset($or_params['masque.milieu']);
if(isset($p['masque.tag_cel'])) unset($or_params['masque.tag_cel']);
if(isset($p['masque.tag_pictoflora'])) unset($or_params['masque.tag_pictoflora']);
 
$or_masque = array_merge(
DelTk::requestFilterParams($or_params, NULL, $c /* pour masque.departement */),
self::requestFilterParams($or_params));
 
/* Lorsqu'on utilise le masque général pour chercher des tags, ils sont
postulés comme séparés par des espaces, et doivent être tous matchés. */
if(isset($or_params['masque.tag_cel']))
$or_masque['masque.tag_cel'] = DelTk::buildTagsAST($p['masque'], 'AND', ' ');
if(isset($or_params['masque.tag_pictoflora']))
$or_masque['masque.tag_pictoflora'] = DelTk::buildTagsAST($p['masque'], 'AND', ' ');
 
 
// pas de select, groupby & co ici: uniquement 'join' et 'where'
$or_req = array('join' => array(), 'where' => array());
DelTk::sqlAddConstraint($or_masque, $db, $or_req);
self::sqlAddConstraint($or_masque, $db, $or_req);
 
if($or_req['where']) {
$req['where'][] = '(' . implode(' OR ', $or_req['where']) . ')';
// utile au cas ou des jointures seraient rajoutées
$req['join'] = array_unique(array_merge($req['join'], $or_req['join']));
}
}
}
 
 
// cf Observation::reformateObservationSimpleIndex() et ListeObservations::reformateObservation()
// (trop de variétés de formatage, à unifier côté client pour unifier côté backend ...)
static function reformateImagesDoubleIndex($obs, $url_pattern = '', $image_format = 'XL') {
// XXX: cf Observation.php::consulter(), nous pourriouns ici
// conserver les valeurs vides (pour les phptests notamment, ou non)
// $obs = array_map('array_filter', $obs);
$obs_merged = $obs_keyed_by_id_image = array();
foreach($obs as $o) {
// ceci nous complique la tâche pour le reste du processing...
$id = $o['jsonindex'];
// ainsi nous utilisons deux tableaux: le final, indexé par couple d'id(image-obs)
// et celui indexé par simple id_image qui est fort utile pour mapVotesToImages()
// mais tout deux partage leur référence à "protocole"
$image = array(
'id_image' => $o['id_image'],
'binaire.href' => sprintf($url_pattern, $o['id_image'], $image_format),
'mots_cles_texte' => @$o['i_mots_cles_texte'], // @, peut avoir été filtré par array_map() ci-dessus
);
unset($o['id_image'], $o['i_mots_cles_texte'], $o['jsonindex']);
if(!isset($obs_merged[$id])) $obs_merged[$id] = $image;
$obs_merged[$id]['observation'] = $o;
$obs_merged[$id]['protocoles_votes'] = array();
$obs_keyed_by_id_image[$image['id_image']]['protocoles_votes'] = &$obs_merged[$id]['protocoles_votes'];
}
 
return array($obs_merged,$obs_keyed_by_id_image);
}
 
 
 
// complete & override DelTk::requestFilterParams() (même usage)
static function requestFilterParams(Array $params, $parametres_autorises = NULL) {
if($parametres_autorises) { // filtrage de toute clef inconnue
$params = array_intersect_key($params, array_flip($parametres_autorises));
}
 
$p = array();
$p['tri'] = DelTk::unsetIfInvalid($params, 'tri', self::$tri_possible);
$p['format'] = DelTk::unsetIfInvalid($params, 'format', self::$format_image_possible);
 
// "milieu" inutile pour IdentiPlantes ?
if(isset($params['masque.milieu'])) $p['masque.milieu'] = trim($params['masque.milieu']);
 
// compatibilité
if(isset($params['masque.tag'])) {
$params['masque.tag_cel'] = $params['masque.tag_pictoflora'] = $params['masque.tag'];
}
 
if($p['tri'] == 'votes' || $p['tri'] == 'tags') {
// ces critère de tri des image à privilégier ne s'applique qu'à un protocole donné
if(!isset($params['protocole']) || !is_numeric($params['protocole']))
$p['protocole'] = self::$default_proto;
else
$p['protocole'] = intval($params['protocole']);
}
 
return array_filter($p, create_function('$a','return !in_array($a, array("",false,null),true);'));
}
 
 
 
// met à jour *toutes* les stats de nombre de tags et de moyenne des votes
static function _update_statistics($db) {
$db->requeter("TRUNCATE TABLE del_image_stat");
$db->requeter(<<<EOF
INSERT INTO `del_image_stat` (
SELECT id_image, divo.ce_protocole, divo.moyenne, divo.nb_votes, dit.ctags
FROM `tb_cel`.`cel_images` ci
LEFT JOIN
( SELECT ce_image, ce_protocole, AVG(valeur) AS moyenne, COUNT(valeur) AS nb_votes FROM del_image_vote
GROUP BY ce_image, ce_protocole ) AS divo
ON ci.id_image = divo.ce_image
LEFT JOIN
( SELECT ce_image, COUNT(id_tag) as ctags FROM del_image_tag
GROUP BY ce_image ) AS dit
ON ci.id_image = dit.ce_image )
EOF
);
}
 
static function revOrderBy($orderby) {
return $orderby == 'asc' ? 'desc' : 'asc';
}
}
/tags/v1.1-helium/services/modules/0.1/nomstaxons/ListeTaxons.php
New file
0,0 → 1,88
<?php
// declare(encoding='UTF-8');
/**
* Le web service récupère une liste de noms suivant un référentiel et un masque donné
*
* @category php 5.2
* @package del
* @subpackage images
* @author Aurélien Peronnet <aurelien@tela-botanica.org>
* @author Grégoire Duché <gregoire@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images
*/
 
class ListeTaxons {
private $conteneur;
private $navigation;
private $masque;
private $gestionBdd;
private $bdd;
private $parametres = array();
private $ressources = array();
private $requete = null;
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_nomstaxons.ini');
$this->navigation = $conteneur->getNavigation();
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
/**
* Méthode principale de la classe.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function consulter($ressources, $parametres) {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
// Lancement du service
$taxons = $this->chargerNoms($this->masque->getMasque('referentiel'), $this->masque->getMasque('nom'));
$total = $this->compterNoms($taxons);
$this->navigation->setTotal($total);
$this->conteneur->setSansLimite();
$resultat = new ResultatService();
$resultat->corps = array('entete' => $this->conteneur->getEntete(), 'resultats' => $taxons);
return $resultat;
}
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
/*-------------------------------------------------------------------------------
CHARGEMENT DES COMMENTAIRES
--------------------------------------------------------------------------------*/
/**
* Chargement depuis le serveur de tous les noms
* */
private function chargerNoms($referentiel, $requete) {
$url = sprintf($this->conteneur->getParametre('url_service_completion_base'), $referentiel, urlencode($requete));
$res = json_decode(@file_get_contents($url),true);
$res = (array)$res;
$res_fmt = array();
if(isset($res['resultat'])) {
foreach($res['resultat'] as $nn => $info_nom) {
$res_fmt[] = array($info_nom['nom_sci_complet'], (string)$nn);
}
}
return $res_fmt;
}
/**
* Compter le nombre total de noms pour affichage dans entete.
* */
private function compterNoms($taxons) {
return sizeof($taxons);
}
}
?>
/tags/v1.1-helium/services/modules/0.1/Syndication.php
New file
0,0 → 1,175
<?php
/**
* Description :
* Classe principale de chargement des services de syndication
*
* Encodage en entrée : utf8
* Encodage en sortie : utf8
* @package del-service
* @author Aurélien PERONNET <aurelien@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version 0.1
* @copyright 1999-2011 Tela Botanica (accueil@tela-botanica.org)
*/
class Syndication extends RestService {
 
private $parametres = array();
private $ressources = array();
private $methode = null;
private $projetNom = array();
private $serviceNom = array();
private $cheminCourant = null;
private $squelette_dossier = null;
private $formats_autorises = null;
 
private $conteneur;
/** Indique si oui (true) ou non (false), on veut utiliser les paramètres bruts. */
protected $utilisationParametresBruts = true;
 
public function __construct() {
$this->cheminCourant = dirname(__FILE__).DS;
$this->squelette_dossier = dirname(__FILE__).DIRECTORY_SEPARATOR.'syndication'.DIRECTORY_SEPARATOR.'squelettes'.DIRECTORY_SEPARATOR;
}
 
public function consulter($ressources, $parametres) {
$this->methode = 'consulter';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserProjet();
$this->initialiserRessourcesEtParametres($ressources, $parametres);
$this->conteneur = new Conteneur($this->parametres);
$this->verifierRessourcesEtParametres();
$resultat = $this->traiterRessources();
$reponseHttp->setResultatService($this->creerResultatService($resultat));
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
}
$reponseHttp->emettreLesEntetes();
$corps = $reponseHttp->getCorps();
return $corps;
}
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
private function verifierRessourcesEtParametres() {
$servicesDispos = Config::get('servicesDispo');
if (!isset($this->ressources[0]) || !in_array($this->ressources[0], explode(',',$servicesDispos))) {
$message = "Vous devez indiquer un nom de service valide, les services disponibles sont ".$servicesDispos;
$code = RestServeur::HTTP_CODE_ERREUR;
throw new Exception($message, $code);
}
$chaineFormatsAutorises = Config::get('formatsRss');
$this->formats_autorises = explode(',', $chaineFormatsAutorises);
if (!isset($this->ressources[1]) || !in_array($this->ressources[1], $this->formats_autorises)) {
$message = "Vous devez indiquer un format de flux valide, les formats acceptés sont ".$chaineFormatsAutorises;
$code = RestServeur::HTTP_CODE_ERREUR;
throw new Exception($message, $code);
} else {
$this->format = $this->ressources[1];
}
}
 
private function traiterRessources() {
$retour = '';
$retour = $this->initialiserService();
 
return $retour;
}
private function creerResultatService($donnees) {
$resultat = new ResultatService();
$resultat->mime = $this->getTypeMime();
$resultat->corps = SquelettePhp::analyser($this->squelette_dossier.$this->format.'.tpl.xml', $donnees);
return $resultat;
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU PROJET
------------------------------------------------------------------------------------------------------------------*/
private function initialiserProjet() {
$this->projetNom = 'syndication';
$this->chargerConfigProjet();
}
 
private function chargerConfigProjet() {
$projet = $this->projetNom;
$chemin = Config::get('chemin_configurations')."config_$projet.ini";
Config::charger($chemin);
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
------------------------------------------------------------------------------------------------------------------*/
private function initialiserService() {
$this->chargerNomService();
$classe = $this->obtenirNomClasseService($this->serviceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->projetNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
$this->conteneur->chargerConfiguration('config_'.$this->projetNom.'.ini');
require_once $chemin;
$service = new $classe($this->conteneur);
if ($this->methode == 'consulter') {
$retour = $service->consulter($this->ressources, $this->parametres);
}
}
}
if (is_null($service)) {
$message = "Le service demandé '{$this->serviceNom}' n'existe pas dans le projet {$this->projetNom} !";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
return $retour;
}
private function chargerNomService() {
if (!isset($this->ressources[0])) {
$message = "Vous devez indiquer un nom de service";
$code = RestServeur::HTTP_CODE_ERREUR;
throw new Exception($message, $code);
} else {
$this->serviceNom = $this->ressources[0];
}
}
 
private function obtenirNomClasseService($mot) {
$classeNom = 'Syndication'.ucwords($mot);
return $classeNom;
}
private function getTypeMime() {
$mime = '';
switch ($this->format) {
case 'atom' :
$mime = 'application/atom+xml';
break;
case 'rss1' :
case 'rss2' :
$mime = 'application/rss+xml';
break;
case 'opml' :
$mime = 'text/x-opml';
break;
default:
$mime = 'text/html';
}
return $mime;
}
}
?>
/tags/v1.1-helium/services/modules/0.1/Determinations.php
New file
0,0 → 1,201
<?php
/**
* Description :
* Classe principale de chargement des services d'eFlore.
*
* Encodage en entrée : utf8
* Encodage en sortie : utf8
* @package eflore-projets
* @author Jennifer DHÉ <jennifer.dhe@tela-botanica.org>
* @author Delphine CAUQUIL <delphine@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version 0.1
* @copyright 1999-2011 Tela Botanica (accueil@tela-botanica.org)
*/
class Determinations extends RestService {
 
/*
* url possibles :
* http://localhost/del/services/0.1/images/ => toutes les images, appel à la classe ListeImages
* http://localhost/del/services/0.1/images/#id => une image donnée => non utilisé sur DEL pour l'instant
* http://localhost/del/services/0.1/images/#id/votes/ => tous les votes d'une image classés par protocole
* http://localhost/del/services/0.1/images/#id/votes/protocole/#id => tous les votes d'une image et d'un protocole donné
* http://localhost/del/services/0.1/images/#id/votes/#id => un vote donné pour une image donnée.
* */
private $parametres = array();
private $ressources = array();
private $methode = null;
private $projetNom = array();
private $serviceNom = array();
private $cheminCourant = null;
 
private $conteneur;
/** Indique si oui (true) ou non (false), on veut utiliser les paramètres bruts. */
protected $utilisationParametresBruts = true;
 
public function __construct() {
$this->cheminCourant = dirname(__FILE__).DS;
}
 
public function consulter($ressources, $parametres) {
$this->methode = 'consulter';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
$reponseHttp->setResultatService($resultat);
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
}
$reponseHttp->emettreLesEntetes();
$corps = $reponseHttp->getCorps();
return $corps;
}
public function ajouter($ressources, $requeteDonnees) {
$this->methode = 'ajouter';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $requeteDonnees);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
$reponseHttp->emettreLesEntetes();
echo $reponseHttp->getCorps();
}
}
public function modifier($ressources, $requeteDonnees) {
$this->methode = 'modifier';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $requeteDonnees);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
$reponseHttp->emettreLesEntetes();
echo $reponseHttp->getCorps();
}
}
 
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function traiterRessources() {
$retour = '';
$this->initialiserProjet();
if ($this->avoirRessourceService()) {
$retour = $this->initialiserService();
}
return $retour;
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU PROJET
------------------------------------------------------------------------------------------------------------------*/
private function initialiserProjet() {
$this->chargerNomDuProjet();
$this->chargerConfigProjet();
 
}
 
private function chargerNomDuProjet() {
$this->projetNom = 'determinations';
}
 
private function chargerConfigProjet() {
$projet = $this->projetNom;
$chemin = Config::get('chemin_configurations')."config_$projet.ini";
Config::charger($chemin);
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
------------------------------------------------------------------------------------------------------------------*/
private function avoirRessourceService() {
$presenceRessourceService = false;
if (isset($this->ressources[0])) {
if($this->ressources[0] == 'images-determinations-probables') {
$presenceRessourceService = true;
$this->serviceNom = 'liste-images-determinations-probables';
} else if($this->ressources[0] == 'valider-determination') {
$presenceRessourceService = true;
$this->serviceNom = 'valider-determination';
} else {
$this->editerMessageErreurRessource();
}
}
return $presenceRessourceService;
}
private function editerMessageErreurRessource() {
$message = "Le service demandé '".$this->projetNom.'/'.implode('/', $this->ressources).
"' n'est pas disponible pour le projet ".$this->projetNom." !\n".
"Les services disponibles sont : images, images/#id/votes, images/#id/vote/#id_vote";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
private function etreRessourceIdentifiant($num) {
$presenceId = false;
if (is_numeric($this->ressources[$num])) {
$presenceId = true;
} else {
$message = "Le service demandé '$service' nécessite d'avoir un identifiant d'image valide";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
return $presenceId;
}
 
private function initialiserService() {
$classe = $this->obtenirNomClasseService($this->serviceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->projetNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
$this->conteneur->chargerConfiguration('config_'.$this->projetNom.'.ini');
require_once $chemin;
$service = new $classe($this->conteneur);
if ($this->methode == 'consulter') {
$retour = $service->consulter($this->ressources, $this->parametres);
} elseif ($this->methode == 'ajouter') {
$retour = $service->ajouter($this->ressources, $this->parametres);
} elseif ($this->methode == 'modifier') {
$retour = $service->modifier($this->ressources, $this->parametres);
}
}
}
if (is_null($service)) {
$message = "Le service demandé '{$this->serviceNom}' n'existe pas dans le projet {$this->projetNom} !";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
return $retour;
}
 
private function obtenirNomClasseService($mot) {
$classeNom = str_replace(' ', '', ucwords(strtolower(str_replace('-', ' ', $mot))));
return $classeNom;
}
}
?>
/tags/v1.1-helium/services/modules/0.1/Commentaires.php
New file
0,0 → 1,178
<?php
/**
* Description :
* Classe principale de chargement des services d'eFlore.
*
* Encodage en entrée : utf8
* Encodage en sortie : utf8
* @package eflore-projets
* @author Jennifer DHÉ <jennifer.dhe@tela-botanica.org>
* @author Delphine CAUQUIL <delphine@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version 0.1
* @copyright 1999-2011 Tela Botanica (accueil@tela-botanica.org)
*/
class Commentaires extends RestService {
 
private $parametres = array();
private $ressources = array();
private $methode = null;
private $projetNom = array();
private $serviceNom = array();
private $cheminCourant = null;
 
private $conteneur;
/** Indique si oui (true) ou non (false), on veut utiliser les paramètres bruts. */
protected $utilisationParametresBruts = true;
 
public function __construct() {
$this->cheminCourant = dirname(__FILE__).DS;
}
 
public function consulter($ressources, $parametres) {
$this->methode = 'consulter';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
$reponseHttp->setResultatService($resultat);
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
}
$reponseHttp->emettreLesEntetes();
$corps = $reponseHttp->getCorps();
return $corps;
}
public function ajouter($ressources, $parametres) {
$this->methode = 'ajouter';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
$reponseHttp->setResultatService($resultat);
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
}
$corps = $reponseHttp->getCorps();
return $corps;
}
public function supprimer($ressources) {
$this->methode = 'supprimer';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->ressources = $ressources;
$this->conteneur = new Conteneur();
$resultat = $this->traiterRessources();
$reponseHttp->setResultatService($resultat);
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
$reponseHttp->emettreLesEntetes();
echo $reponseHttp->getCorps();
}
}
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function traiterRessources() {
$retour = '';
$this->initialiserProjet();
$retour = $this->initialiserService();
return $retour;
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU PROJET
------------------------------------------------------------------------------------------------------------------*/
private function initialiserProjet() {
$this->projetNom = 'commentaires';
$this->chargerConfigProjet();
}
 
private function chargerConfigProjet() {
$projet = $this->projetNom;
$chemin = Config::get('chemin_configurations')."config_$projet.ini";
Config::charger($chemin);
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
------------------------------------------------------------------------------------------------------------------*/
private function initialiserService() {
$this->chargerNomService();
$classe = $this->obtenirNomClasseService($this->serviceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->projetNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
$this->conteneur->chargerConfiguration('config_'.$this->projetNom.'.ini');
require_once $chemin;
$service = new $classe($this->conteneur);
if ($this->methode == 'consulter') {
$retour = $service->consulter($this->ressources, $this->parametres);
} elseif ($this->methode == 'ajouter') {
$retour = $service->ajouter($this->ressources, $this->parametres);
} elseif ($this->methode == 'supprimer') {
$retour = $service->supprimer($this->ressources, $this->parametres);
}
}
}
if (is_null($service)) {
$message = "Le service demandé '{$this->serviceNom}' n'existe pas dans le projet {$this->projetNom} !";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
return $retour;
}
private function chargerNomService() {
// si la méthode est POST, on ajouter un commentaire
if ($this->methode == 'ajouter') {
$this->serviceNom = 'ajouter-commentaire';
} else if ($this->methode == 'supprimer') {
$this->serviceNom = 'supprimer-commentaire';
}
else {
//S'il n'y a pas de ressources => tous les commentaires
if (!isset($this->ressources) || empty($this->ressources)) {
$this->serviceNom = 'liste-commentaires';
} else {
if (!is_numeric($this->ressources[0])) {
$message = "La première ressource doit être un identifiant";
$code = RestServeur::HTTP_CODE_ERREUR;
throw new Exception($message, $code);
} else {
$this->serviceNom = 'consulter-commentaire';
}
}
}
}
 
private function obtenirNomClasseService($mot) {
$classeNom = str_replace(' ', '', ucwords(strtolower(str_replace('-', ' ', $mot))));
return $classeNom;
}
}
?>
/tags/v1.1-helium/services/modules/0.1/Communes.php
New file
0,0 → 1,122
<?php
/**
* Description :
* Classe principale de chargement des services d'eFlore.
*
* Encodage en entrée : utf8
* Encodage en sortie : utf8
* @package eflore-projets
* @author Jennifer DHÉ <jennifer.dhe@tela-botanica.org>
* @author Delphine CAUQUIL <delphine@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version 0.1
* @copyright 1999-2011 Tela Botanica (accueil@tela-botanica.org)
*/
class Communes extends RestService {
 
private $parametres = array();
private $ressources = array();
private $methode = null;
private $projetNom = array();
private $serviceNom = array();
private $cheminCourant = null;
 
private $conteneur;
/** Indique si oui (true) ou non (false), on veut utiliser les paramètres bruts. */
protected $utilisationParametresBruts = true;
 
public function __construct() {
$this->cheminCourant = dirname(__FILE__).DS;
}
 
public function consulter($ressources, $parametres) {
$this->methode = 'consulter';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
$reponseHttp->setResultatService($resultat);
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
}
$reponseHttp->emettreLesEntetes();
$corps = $reponseHttp->getCorps();
return $corps;
}
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function traiterRessources() {
$retour = '';
$this->initialiserProjet();
$retour = $this->initialiserService();
return $retour;
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU PROJET
------------------------------------------------------------------------------------------------------------------*/
private function initialiserProjet() {
$this->projetNom = 'communes';
$this->chargerConfigProjet();
}
 
private function chargerConfigProjet() {
$projet = $this->projetNom;
$chemin = Config::get('chemin_configurations')."config_$projet.ini";
Config::charger($chemin);
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
------------------------------------------------------------------------------------------------------------------*/
private function initialiserService() {
$this->chargerNomService();
$classe = $this->obtenirNomClasseService($this->serviceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->projetNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
$this->conteneur->chargerConfiguration('config_'.$this->projetNom.'.ini');
require_once $chemin;
$service = new $classe($this->conteneur);
if ($this->methode == 'consulter') {
$retour = $service->consulter($this->ressources, $this->parametres);
} else {
//TODO : throw exception
}
}
}
if (is_null($service)) {
$message = "Le service demandé '{$this->serviceNom}' n'existe pas dans le projet {$this->projetNom} !";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
return $retour;
}
private function chargerNomService() {
// si la méthode est POST, on ajouter un commentaire
$this->serviceNom = 'liste-communes';
}
 
private function obtenirNomClasseService($mot) {
$classeNom = str_replace(' ', '', ucwords(strtolower(str_replace('-', ' ', $mot))));
return $classeNom;
}
}
?>
/tags/v1.1-helium/services/modules/0.1/observations/VoteObservation.php
New file
0,0 → 1,279
<?php
// declare(encoding='UTF-8');
/**
* Les web service permet d'ajouter ou de modifier les votes associés aux propositions d'une observation
*
* @category php 5.2
* @package del
* @subpackage images
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Images
*/
 
class VoteObservation extends RestService {
protected $conteneur;
protected $gestionBdd;
protected $bdd;
protected $navigation;
 
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
$this->navigation = $conteneur->getNavigation();
$this->conteneur->chargerConfiguration('config_mapping_votes.ini');
}
 
/**
* Configuration du service en fonction du fichier de config config_del.ini
* */
private function configurer() {
$this->mappingVotes = $this->conteneur->getParametre('mapping_votes');
}
 
/**
* Méthode seulement présente pour interdire proprement l'accès à la consultation
* */
public function consulter($ressources, $parametres) {
 
$this->configurer();
 
//TODO: faut il vérifier quelque chose, si on n'a pas renseigné les valeurs correctement
// dans ressource, le service n'est même pas appelé
$votes = $this->chargerVotes($ressources[1]);
$this->conteneur->getNavigation()->setTotal(count($votes));
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
$resultat->corps = array('entete' => $this->conteneur->getEntete(), 'resultats' => $votes);
return $resultat;
}
 
private function chargerVotes($id_commentaire) {
$requeteVotes = 'SELECT * FROM '.
$this->gestionBdd->formaterTable('del_commentaire_vote').
'WHERE ce_proposition = '.$this->proteger($id_commentaire);
$resultatsVotes = $this->bdd->recupererTous($requeteVotes);
$votes = array();
foreach ($resultatsVotes as $vote) {
$votes[$vote['id_vote']] = $this->formaterVotes($vote);
$utilisateur = $this->chercherUtilisateur($vote['ce_utilisateur']);
if($utilisateur) {
$votes[$vote['id_vote']] = array_merge($votes[$vote['id_vote']], $utilisateur);
}
}
return $votes;
}
 
/**
* Trouver l'utilisateur en fonction des paramètres ou de la base de données si le nom, prénom et courriel ne sont pas donnés
* @return le tableau utilisateur
* */
private function chercherUtilisateur($id) {
$utilisateur = array();
$requete = "SELECT id_utilisateur as 'auteur.id', nom as 'auteur.nom', prenom as 'auteur.prenom', courriel as 'auteur.courriel' ".
'FROM '.$this->gestionBdd->formaterTable('del_utilisateur').
'WHERE id_utilisateur = '.$this->bdd->proteger($id);
$utilisateur = $this->bdd->recuperer($requete);
 
return $utilisateur;
}
 
/**
* Formater un vote en fonction du fichier de configuration config_votes.ini
* @param $votes array()
* */
private function formaterVotes($vote) {
$retour = array();
foreach ($vote as $param => $valeur) {
$retour[$this->mappingVotes[$param]] = $valeur;
}
return $retour;
}
 
/**
* Ajoute un vote à une proposition grâce aux informations passées en paramètres
* @param array $ressources tableau des informations contenues dans l'url après le nom du service
* @param array $parametres contenu du post
*
* @return void
*
* */
public function ajouter($ressources, $parametres) {
 
$this->verifierParametresAjoutModif($ressources, $parametres);
 
// Vérifie si la proposition existe, et la crée sinon
// (cas du vote sur la proposition fabriquée à partir de l'observation originale)
if($ressources[1] == 0) {
$ressources[1] = $this->renvoyerIdOuCreerPropositionDeterminationInitiale($ressources[0]);
}
 
$insertion = 'INSERT INTO del_commentaire_vote '.
'(ce_proposition , ce_utilisateur , valeur , date) '.
'VALUES ('.$this->proteger($ressources[1]).','.$this->proteger($parametres['utilisateur']).','.
$this->proteger($parametres['valeur']).', NOW());';
$resultatsVotes = $this->bdd->requeter($insertion);
if ($resultatsVotes == false) {
RestServeur::envoyerEnteteStatutHttp(RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
} else {
RestServeur::envoyerEnteteStatutHttp(RestServeur::HTTP_CODE_CREATION_OK);
}
}
 
private function renvoyerIdPropositionObservation($id_observation) {
 
$id_commentaire = null;
// Récupération de l'utilisateur + nom sel de l'observation originale
$requete_selection_obs = 'SELECT ce_utilisateur, nom_sel '.
'FROM del_observation '.
'WHERE id_observation ='.$this->proteger($id_observation);
 
$obs = $this->bdd->recuperer($requete_selection_obs);
 
if(is_array($obs) && isset($obs['ce_utilisateur'])) {
// On considère que la proposition faite par le même utilisateur et ayant le même
// nom sélectionné est bien la proposition composée à partir de l'obs originale
$requete_selection_comm = 'SELECT id_commentaire FROM del_commentaire '.
'WHERE ce_observation = '.$this->proteger($id_observation).' '.
' AND nom_sel = '.$this->proteger($obs['nom_sel']).' AND '.
' ce_utilisateur = '.$this->proteger($obs['ce_utilisateur']);
 
$commentaire = $this->bdd->recuperer($requete_selection_comm);
$id_commentaire = (is_array($commentaire) && $commentaire['id_commentaire'] != null) ? $commentaire['id_commentaire'] : null;
}
 
return $id_commentaire;
}
 
private function renvoyerIdOuCreerPropositionDeterminationInitiale($id_observation) {
$proposition_existe = $this->propositionInitialeExiste($id_observation);
if(!$proposition_existe) {
$id_proposition = $this->creerPropositionAPartirObservation($id_observation);
} else {
$requete = "SELECT id_commentaire FROM del_commentaire WHERE ce_observation = ".$id_observation." ".
"AND proposition_initiale = 1";
$resultat = $this->bdd->recuperer($requete);
$id_proposition = $resultat['id_commentaire'];
}
return $id_proposition;
}
 
private function propositionInitialeExiste($id_observation) {
 
$requete = "SELECT COUNT(*) >= 1 as existe FROM del_commentaire WHERE ce_observation = ".$id_observation." ".
"AND proposition_initiale = 1";
$resultat = $this->bdd->recuperer($requete);
return $resultat['existe'] == 1;
}
 
private function creerPropositionAPartirObservation($id_observation) {
 
$insertion = 'INSERT IGNORE INTO del_commentaire '.
'(ce_observation, ce_utilisateur, utilisateur_prenom, utilisateur_nom, utilisateur_courriel, '.
'nom_sel, nom_sel_nn, nom_ret, nom_ret_nn, nt, famille, nom_referentiel, date, proposition_initiale) '.
'SELECT id_observation, ce_utilisateur, prenom, nom, '.
' courriel, nom_sel, nom_sel_nn, nom_ret, nom_ret_nn, '.
" nt, famille, 'bdtfx_v1', NOW(), '1' ".
'FROM del_observation do '.
' LEFT JOIN del_utilisateur du ON '.
'do.ce_utilisateur = du.id_utilisateur '.
'WHERE id_observation = '.$this->proteger($id_observation);
 
$resultat = $this->bdd->requeter($insertion);
// Attention à l'abstraction utilisée, récupérer le dernier id en mysql ou msqli ça marche bien, mais pour d'autres moins
$id = $this->bdd->recupererIdDernierAjout();
 
return $id;
}
 
/**
* Modifie un vote associé à une proposition grâce aux informations passées en paramètres
* @param array $ressources tableau des informations contenues dans l'url après le nom du service
* @param array $parametres contenu du post
*
* @return void
*
* */
public function modifier($ressources, $parametres) {
 
$this->verifierParametresAjoutModif($ressources, $parametres);
 
// Si l'identifiant de proposition vaut 0, c'est un vote sur une proposition
// fabriquée à partir de l'observation originale, dont on doit obtenir l'id
// (cas où l'on vient de voter pour celle et cela a créé la proposition, puis
// on revote pour celle ci en changeant d'avis sans recharger la page)
if($ressources[1] == 0) {
$id_proposition = $this->renvoyerIdOuCreerPropositionDeterminationInitiale($ressources[0]);
if($id_proposition == null) {
$this->envoyerMessageErreurIdProposition();
exit;
} else {
$ressources[1] = $id_proposition;
}
}
 
$modification = 'UPDATE del_commentaire_vote '.
'SET valeur ='.$this->proteger($parametres['valeur']).', '.
'date = NOW() '.
'WHERE '.
'ce_proposition = '.$this->proteger($ressources[1]).' AND '.
'ce_utilisateur = '.$this->proteger($parametres['utilisateur']);
 
$resultatsVotes = $this->bdd->requeter($modification);
if ($resultatsVotes == false) {
RestServeur::envoyerEnteteStatutHttp(RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
} else {
RestServeur::envoyerEnteteStatutHttp(RestServeur::HTTP_CODE_OK);
}
}
 
public function verifierParametresAjoutModif($ressources, $parametres) {
$erreurs = array();
if (!is_numeric($ressources[1])) {
$erreurs[] = '- le paramètre indiquant l\'identifiant de la proposition doit être numérique ;';
}
 
if (!isset($parametres['utilisateur'])) {
$erreurs[] = '- paramètre "utilisateur" manquant ;';
}
 
if (!isset($parametres['valeur'])) {
$erreurs[] = '- paramètre "valeur" manquant ;';
} else {
if (!is_numeric($parametres['valeur'])) {
$erreurs[] = '- le paramètre "valeur" doit être numérique ;';
} elseif($parametres['valeur'] != 0 && $parametres['valeur'] != 1) {
$erreurs[] = '- le paramètre "valeur" ne peut prendre que la valeur 0 ou 1 ;';
}
}
 
if (!empty($erreurs)) {
$e = 'Erreur lors de la configuration : '."\n";
$e .= implode("\n", $erreurs);
RestServeur::ajouterMessage($e);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
 
protected function envoyerMessageErreurIdProposition() {
$erreurs = array('Aucun identifiant de proposition n\'est lié à cette observation');
$e = 'Erreur lors de la configuration : '."\n";
$e .= implode("\n", $erreurs);
RestServeur::ajouterMessage($e);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
 
protected function proteger($valeur) {
if (is_array($valeur)) {
return $this->bdd->protegerTableau($valeur);
} else {
return $this->bdd->proteger($valeur);
}
}
}
?>
/tags/v1.1-helium/services/modules/0.1/observations/Observation.php
New file
0,0 → 1,347
<?php
/**
* Le web service observations récupère toutes les information pour une observation:
* images, votes sur image et protocole, commentaires, votes sur commentaires, ...
*
* @category php 5.2
* @author Raphaël Droz <raphael@tela-botanica.org>
* @copyright Copyright (c) 2013, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Observations
*
* @config-depend: "url_image" (dans configurations/config_observations.ini)
* ex: http://www.tela-botanica.org/appli:cel-img:%09dXL.jpg
*/
 
// http://localhost/del/services/0.1/observations/#id => une observation donnée et ses images, SANS LES propositions & nombre de commentaire
 
require_once(dirname(__FILE__) . '/../DelTk.php');
 
class Observation {
 
/* Map les champs MySQL vers les champs utilisés dans le JSON pour les clients pour
chacune des différentes tables utilisées pour le chargement de résultats ci-dessous.
- chargerObservation() (v_del_image)
- chargerVotesImage() (del_image_vote, del_image_protocole)
- chargerCommentaires() (del_commentaire_vote, del_commentaire).
Si la valeur vaut 1, aucun alias ne sera défini (nom du champ d'origine), cf consulter() */
static $mappings = array(
'observations' => array( // v_del_image
"id_observation" => 1,
"date_observation" => 1,
"date_transmission" => 1,
"famille" => "determination.famille",
"nom_sel" => "determination.ns",
"nom_sel_nn" => "determination.nn",
"nom_referentiel" => "determination.referentiel",
"nt" => "determination.nt",
"ce_zone_geo" => "id_zone_geo",
"zone_geo" => 1,
"lieudit" => 1,
"station" => 1,
"milieu" => 1,
"ce_utilisateur" => "auteur.id",
"mots_cles_texte" => "mots_cles_texte",
"commentaire" => 1),
/* exclus car issus de la jointure annuaire:
"nom" => "auteur.nom", // XXX: jointure annuaire
"prenom" => "auteur.prenom", // XXX: jointure annuaire
"courriel" => "observateur", // XXX: jointure annuaire */
/* présents dans cel_obs mais exclus:
ordre, nom_ret, nom_ret_nn, latitude, longitude, altitude, geodatum
transmission, date_creation, date_modificationabondance, certitude, phenologie, code_insee_calcule */
 
'images' => array( // v_del_image
"id_image" => 1,
"hauteur" => 1,
// "largeur" => 1, inutile semble-t-il
"date_prise_de_vue" => "date"),
/* présents dans cel_images mais exclus:
i_commentaire, nom_original, publiable_eflore, i_mots_cles_texte, i_ordre,
i_ce_utilisateur, i_prenom_utilisateur, i_nom_utilisateur, i_courriel_utilisateur */
 
'protocoles' => array( // del_image_protocole
"ce_protocole" => "protocole.id",
"id_protocole" => "protocole.id",
"intitule" => "protocole.intitule",
"descriptif" => "protocole.descriptif",
"tag" => "protocole.tag"),
 
/* See desc del_commentaire_vote & desc del_image_vote;
Les deux schémas sont similaires, à l'exception de ce_protocole
spécifique à del_image_vote et ce_proposition => ce_image */
'votes' => array( // del_image_vote et del_commentaire_vote
"id_vote" => "vote.id",
"ce_proposition" => "proposition.id",
"ce_image" => "image.id",
"ce_utilisateur" => "auteur.id", // attention, conflit avec commentaire, cf ci-dessous
"valeur" => "vote",
"date" => 1, // attention, conflit avec commentaire, cf ci-dessous
// absents du JSON, et pourtant présents dans services/configurations/config_mapping_votes.ini
// (nécessiterait une propre jointure sur del_utilisateur)
/* "nom" => "auteur.nom",
"prenom" => "auteur.prenom",
"courriel" => "auteur.courriel" */),
 
'commentaires' => array( // del_commentaire
"id_commentaire" => 1,
"ce_observation" => "observation",
"ce_proposition" => "proposition",
"ce_commentaire_parent" => "id_parent",
 
// les deux alias suivants sont particuliers afin d'éviter un conflit d'alias
// lors des jointures avec del_commentaire_vote ci-dessus
// (cf cas particulier dans la boucle de chargerCommentaires())
"ce_utilisateur" => "__auteur_com",
"date" => "__date_com",
 
"texte" => 1,
"utilisateur_nom" => "auteur.nom",
"utilisateur_prenom" => "auteur.prenom",
"utilisateur_courriel" => "auteur.courriel",
"nom_sel" => 1,
"nom_sel_nn" => 1,
"nom_ret_nn" => 1,
"nom_referentiel" => 1,
"proposition_initiale" => 1),
);
 
private $conteneur;
private $gestionBdd;
private $bdd;
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_votes.ini');
$this->conteneur->chargerConfiguration('config_mapping_votes.ini');
$this->conteneur->chargerConfiguration('config_mapping_commentaires.ini');
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
/**
* Méthode principale de la classe.
* Lance la récupération des images dans la base et les place dans un objet ResultatService
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function consulter($ressources, $parametres) {
if (!$ressources || count($ressources) != 1 ) {
throw new Exception("Le service observation accepte un unique identifiant d'observation", RestServeur::HTTP_CODE_ERREUR);
}
 
// initialise les mappings:
// substitue les valeurs à 1 par le nom de la clef (pas d'alias de champ)
array_walk(self::$mappings['observations'], create_function('&$val, $k', 'if($val==1) $val = $k;'));
array_walk(self::$mappings['images'], create_function('&$val, $k', 'if($val==1) $val = $k;'));
array_walk(self::$mappings['protocoles'], create_function('&$val, $k', 'if($val==1) $val = $k;'));
array_walk(self::$mappings['votes'], create_function('&$val, $k', 'if($val==1) $val = $k;'));
array_walk(self::$mappings['commentaires'], create_function('&$val, $k', 'if($val==1) $val = $k;'));
 
 
// Gestion des configuration du script
$idobs = $ressources[0];
$protocole = isset($parametres['protocole']) && is_numeric($parametres['protocole']) ?intval($parametres['protocole']) : NULL;
 
// 1) récupération de l'observation (et de ses images (v_del_image est une vue utilisant des INNER JOIN))
$liaisons = self::chargerObservation($this->bdd, $idobs);
if(!$liaisons) {
header('HTTP/1.0 404 Not Found');
// don't die (phpunit)
throw(new Exception());
}
 
// 2) réassocie les images "à plat" à leur observation (merge)
// TODO: appliquer le formattage dépendant de la configuration en fin de processus
$observations = self::reformateObservationSimpleIndex($liaisons, $this->conteneur->getParametre('url_images'));
// bien que dans notre cas il n'y ait qu'une seule observation, issue de plusieurs images
// dans $liaisons, $observation est un tableau (cf reformateObservation).
// Considérons la chose comme telle au cas où le webservice doivent demain demander une paire
// d'observations (... convergence avec ListeObservations & DelTk)
 
$observation = array_pop($observations);
 
// 3) charge les données de votes et protocoles associés aux images
if($observation['images']) {
$votes = self::chargerVotesImage($this->bdd, $observation['images'], $protocole);
// 3") merge/reformate les données retournées
self::mapVotesToImages($votes,
$observation['images']);
}
 
// 4) charge les commentaires et les votes associés
// modifie/créé $observation['commentaires']
self::chargerCommentaires($this->bdd, $observation);
 
 
// désindexe le tableau (tel qu'apparement attendu par les applis), c'est une exception
// corriger l'appli cliente pour utiliser les index puis supprimer cette ligne
$observation['images'] = array_values($observation['images']);
// autre élément de post-processing: le ce_utilisateur de l'observation non-numeric...
if(!is_numeric($observation['auteur.id'])) $observation['auteur.id'] = "0";
if(!isset($observation['auteur.nom'])) $observation['auteur.nom'] = '[inconnu]';
 
if(isset($parametres['justthrow'])) return $observation;
 
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
$resultat->corps = $observation;
return $resultat;
}
 
static function chargerObservation($db, $idobs) {
// prenom_utilisateur, nom_utilisateur, courriel_utilisateur sont exclus du mapping
// car nous utilisons une construction SQL élaborée pour eux (cf IFNULL ci-dessous)
$obs_fields = DelTk::sqlFieldsToAlias(self::$mappings['observations'], NULL, 'dob');
 
$image_fields = DelTk::sqlFieldsToAlias(self::$mappings['images'], NULL, 'dob');
 
// champs de l'annuaire (del_utilisateur): id_utilisateur prenom, nom, courriel
$annuaire_fields = implode(', ', array("IFNULL(du.prenom, prenom_utilisateur) AS `auteur.prenom`",
"IFNULL(du.nom, nom_utilisateur) AS `auteur.nom`",
"IFNULL(du.courriel, courriel_utilisateur) AS observateur"));
return $db->recupererTous(sprintf(
'SELECT %s, %s, %s FROM v_del_image as dob'.
' LEFT JOIN del_utilisateur du ON CAST(du.id_utilisateur AS CHAR) = CAST(dob.ce_utilisateur AS CHAR)'.
' WHERE dob.id_observation = %d -- %s',
$obs_fields, $image_fields, $annuaire_fields, $idobs, __FILE__ . ':' . __LINE__));
}
 
// Charger les images et leurs votes associés
static function chargerVotesImage($db, $images, $protocole = NULL) {
if(!$images) return NULL;
 
$select = array('votes' =>
array('id_vote', 'ce_image', 'ce_protocole', 'ce_utilisateur', 'valeur', 'date', /* del_image_vote */),
'protocole' =>
array('id_protocole', 'intitule', 'descriptif', 'tag' /* del_image_protocole */ ));
$vote_fields = DelTk::sqlFieldsToAlias(self::$mappings['votes'], $select['votes'], 'v'); // "v": cf alias dans la requête
$proto_fields = DelTk::sqlFieldsToAlias(self::$mappings['protocoles'], $select['protocole'], 'p');
$where = array();
$where[] = sprintf('v.ce_image IN (%s)',
implode(',', array_values(array_map(create_function('$a', 'return $a["id_image"];'), $images))));
 
if ($protocole) {
$where[] = "v.ce_protocole = $protocole";
}
 
return $db->recupererTous(sprintf(
'SELECT %s, %s FROM del_image_vote AS v'.
' INNER JOIN del_image_protocole p ON v.ce_protocole = p.id_protocole'.
' WHERE %s -- %s',
$vote_fields, $proto_fields,
$where ? implode(' AND ', $where) : 1,
__FILE__ . ':' . __LINE__));
}
/**
* Formater une observation depuis une ligne liaison
* @param $liaison liaison issue de la recherche
* @return $observation l'observation mise en forme
* Exemple: vote, au sortir de MySQL contient:
* 'xxx' => 'blah', 'descriptif' => 'foo', 'valeur' => 3
* et le tableau de mapping contient:
* descriptif = protocole.descriptif, valeur = vote
* Alors $retour[ contient:
*
* */
static function mapVotesToImages($votes, &$images) {
if(!$votes) return;
 
// pour chaque vote
foreach ($votes as $vote) {
$imgid = $vote['image.id'];
$protoid = $vote['protocole.id'];
// un vote sans image associée ? est-ce possible ?
// if(!isset($images[$imgid])) continue;
if(!array_key_exists('protocoles_votes', $images[$imgid]) ||
!array_key_exists($protoid, $images[$imgid]['protocoles_votes'])) {
// extrait les champs spécifique au protocole (le LEFT JOIN de chargerVotesImage les ramène en doublons
$protocole = array_intersect_key($vote, array_flip(self::$mappings['protocoles']));
$images[$imgid]['protocoles_votes'][$protoid] = $protocole;
}
 
$vote = array_intersect_key($vote, array_flip(self::$mappings['votes']));
$images[$imgid]['protocoles_votes'][$protoid]['votes'][$vote['vote.id']] = $vote;
}
}
 
// Charger les commentaires et leurs votes associés
static function chargerCommentaires($db, &$observation) {
$select = array('votes' =>
array('id_vote', 'ce_proposition', 'ce_utilisateur', 'valeur', 'date' /* del_commentaire_vote */),
'commentaires' =>
array('id_commentaire', 'ce_observation', 'ce_proposition', 'ce_commentaire_parent', 'texte',
'ce_utilisateur', 'utilisateur_prenom', 'utilisateur_nom', 'utilisateur_courriel',
'nom_sel', 'nom_sel_nn', 'nom_ret', 'nom_ret_nn', 'nt', 'famille', 'nom_referentiel', 'date',
'proposition_initiale'));
$vote_fields = DelTk::sqlFieldsToAlias(self::$mappings['votes'], $select['votes'], 'cv'); // "v": cf alias dans la requête
$comment_fields = DelTk::sqlFieldsToAlias(self::$mappings['commentaires'], $select['commentaires'], 'dc');
 
$commentaires = $db->recupererTous(sprintf(
"SELECT %s, %s FROM del_commentaire as dc".
// LEFT JOIN optionnel, mais explicatif:
// on ne récupère des infos de vote que pour les commentaires comportant un
// nom_sel "valide"
" LEFT JOIN del_commentaire_vote cv".
" ON cv.ce_proposition = dc.id_commentaire AND dc.nom_sel != '' AND dc.nom_sel IS NOT NULL".
" WHERE ce_observation = %d -- %s",
$comment_fields, $vote_fields,
$observation['id_observation'],
__FILE__ . ':' . __LINE__));
 
if(!$commentaires) return;
 
// les commentaires réunifiées et dont les votes sont mergés
$ret = array();
foreach ($commentaires as $comment) {
$commentid = $comment['id_commentaire'];
$voteid = $comment['vote.id'];
 
if(!array_key_exists($commentid, $ret)) {
$comment_extract = array_intersect_key($comment, array_flip(self::$mappings['commentaires']));
// cas particulier: conflit d'aliases avec del_commentaire_vote
$comment_extract['auteur.id'] = $comment_extract['__auteur_com'];
$comment_extract['date'] = $comment_extract['__date_com'];
unset($comment_extract['__auteur_com'], $comment_extract['__date_com']);
 
// toujours un éléments "votes", quand bien même il n'y en aurait pas
$comment_extract['votes'] = array();
$ret[$commentid] = $comment_extract;
}
 
if(!$comment['nom_sel'] || ! $voteid) continue;
$vote = array_intersect_key($comment, array_flip(self::$mappings['votes']));
$ret[$commentid]['votes'][$voteid] = $vote;
}
$observation['commentaires'] = $ret;
}
 
// cf ListeObservation::reformateObservation() et ListeImages2::reformateImagesDoubleIndex()
// (trop de variétés de formatage, à unifier côté client pour unifier côté backend ...)
static function reformateObservationSimpleIndex($obs, $url_pattern = '') {
// XXX: cf Observation.php::consulter(), nous pourriouns ici
// conserver les valeurs vides (pour les phptests notamment, ou non)
$obs = array_map('array_filter', $obs);
$obs_merged = array();
foreach($obs as $o) {
$id = $o['id_observation'];
$image = array_intersect_key($o, array_flip(array('id_image', 'date', 'hauteur' , 'largeur', 'nom_original')));
$image['binaire.href'] = sprintf($url_pattern, $image['id_image']);
unset($o['id_image'], $o['date'], $o['hauteur'], $o['largeur'], $o['nom_original']);
if(!isset($obs_merged[$id])) $obs_merged[$id] = $o;
$obs_merged[$id]['images'][$image['id_image']] = $image;
}
return $obs_merged;
}
 
}
/tags/v1.1-helium/services/modules/0.1/observations/ListeObservations.php
New file
0,0 → 1,435
<?php
/**
* Le web service observations récupère toutes les observations et, pour chacune d'elle, les
* images qui lui sont associées.
* Basée sur la classe antérieure dans ListeObservations.php de
* Grégoire Duché et Aurélien Peronnet
* (formaterVote, formaterDeterminations, chargerNombreCommentaire, chargerVotes, chargerDeterminations)
*
* @category php 5.2
* @package del
* @author Raphaël Droz <raphael@tela-botanica.org>
* @copyright Copyright (c) 2013 Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Observations
*
* TODO:
* PDO::prepare()
* Sphinx pour auteur, genre, ns, commune, tag et masque-général
*/
 
require_once(dirname(__FILE__) . '/../DelTk.php');
/*
restore_error_handler();
restore_exception_handler();
error_reporting(E_ALL);
*/
 
class ListeObservations {
 
private $conteneur;
private $gestionBdd;
private $bdd;
private $parametres = array();
private $ressources = array();
 
static $tris_possibles = array('date_observation');
// paramètres autorisés
 
static $sql_fields_liaisons = array(
'dob' => array('id_observation', 'nom_sel AS `determination.ns`', 'nt AS `determination.nt`',
'nom_sel_nn AS `determination.nn`', 'famille AS `determination.famille`',
'nom_referentiel AS `determination.referentiel`',
'ce_zone_geo AS id_zone_geo', 'zone_geo', 'lieudit',
'station', 'milieu', 'date_observation', 'mots_cles_texte', 'date_transmission',
'ce_utilisateur AS `auteur.id`', 'prenom_utilisateur AS `auteur.prenom`',
'nom_utilisateur AS `auteur.nom`', 'courriel_utilisateur AS observateur',
'commentaire'),
'di' => array('id_image', 'date_prise_de_vue AS `date`', 'hauteur',/* 'largeur','nom_original' // apparemment inutilisés */),
'du' => array('prenom', 'nom', 'courriel'),
'dc' => array('commentaire')
);
 
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_departements_bruts.ini');
$this->conteneur->chargerConfiguration('config_observations.ini');
$this->conteneur->chargerConfiguration('config_mapping_votes.ini');
$this->conteneur->chargerConfiguration('config_mapping_commentaires.ini');
$this->navigation = $conteneur->getNavigation();
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
 
static function reformateObservation($obs, $url_pattern = '') {
$obs = array_map('array_filter', $obs);
$obs_merged = array();
foreach($obs as $o) {
$id = $o['id_observation'];
 
// car auteur.id peut être un email, un hash, ou un annuaire_tela.U_ID
// mais dans les deux premiers cas SELECT courriel AS observateur fait déjà l'affaire
if(!isset($o['auteur.id']) || !is_numeric($o['auteur.id'])) $o['auteur.id'] = "0";
if(!isset($o['auteur.nom'])) $o['auteur.nom'] = '[inconnu]';
 
$image = array_intersect_key($o, array_flip(array('id_image', 'date', 'hauteur' , 'largeur', 'nom_original')));
$image['binaire.href'] = sprintf($url_pattern, $image['id_image']);
unset($o['id_image'], $o['date'], $o['hauteur'], $o['largeur'], $o['nom_original']);
if(!isset($obs_merged['"' . $id . '"'])) $obs_merged['"' . $id . '"'] = $o;
$obs_merged['"' . $id . '"']['images'][] = $image;
}
return $obs_merged;
}
 
/**
* Méthode principale de la classe.
* Lance la récupération des images dans la base et les place dans un objet ResultatService
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
**/
public function consulter($ressources, $parametres) {
// SELECT, à terme, pourrait affecter getInfos(), mais en aucune manière getIdObs()
$req = array('select' => array(), 'join' => array(), 'where' => array(), 'groupby' => array(), 'having' => array());
 
// toujours nécessaire puisque nous tapons sur v_del_image qui INNER JOIN cel_images, or nous voulons certes
// toutes les images, mais nous voulons $limite observations uniques.
$req['groupby'][] = 'vdi.id_observation';
 
$db = $this->bdd;
 
// filtrage de l'INPUT
$params = DelTk::requestFilterParams($parametres, DelTk::$parametres_autorises, $this->conteneur);
 
$params['masque.tag'] = DelTk::buildTagsAST(@$parametres['masque.tag'], 'OR', ',');
 
// ... et paramètres par défaut
$params = array_merge(DelTk::$default_params, $params);
 
// création des contraintes (masques)
DelTk::sqlAddConstraint($params, $db, $req);
self::sqlAddConstraint($params, $db, $req, $this->conteneur);
self::sqlAddMasqueConstraint($params, $db, $req, $this->conteneur);
 
// 1) grunt-work: *la* requête de récupération des id valides (+ SQL_CALC_FOUND_ROWS)
$idobs_tab = self::getIdObs($params, $req, $db);
// idobs est une liste (toujours ordonnée) des id d'observations recherchées
$idobs = array_values(array_map(create_function('$a', 'return $a["id_observation"];'), $idobs_tab));
 
if($idobs) {
$total = $db->recuperer('SELECT FOUND_ROWS() AS c'); $total = intval($total['c']);
 
// 2) récupération des données nécessaires pour ces observations (obs + images)
// ici les champs récupérés sont issus de self::$sql_fields_liaisons mais sans préfixes
// car tout provient de v_del_image
$obs_unfmt = self::getInfos($idobs, $db);
 
// 3) suppression, merge des données en tableau assez représentatif du futur JSON en output
$observations = self::reformateObservation($obs_unfmt, $this->conteneur->getParametre('url_images'));
 
// 4) récupération des données nécessaires pour ces observations (commentaires + votes)
// modifie $observations
$this->configurer();
$this->chargerDeterminations($observations);
 
// 5) restauration de l'ordre souhaité initialement
$observations = self::sortArrayByArray($observations, $idobs);
} else {
$observations = array();
$total = 0;
}
 
// 6) JSON output
$resultat = new ResultatService();
$resultat->corps = array('entete' => DelTk::makeJSONHeader($total, $params, Config::get('url_service')),
'resultats' => $observations);
return $resultat;
}
 
static function sortArrayByArray($array, $orderArray) {
$ordered = array();
foreach($orderArray as $key) {
if(array_key_exists('"' . $key . '"', $array)) {
$ordered['"' . $key . '"'] = $array['"' . $key . '"'];
unset($array['"' . $key . '"']);
}
}
return $ordered + $array;
}
 
// SQL helpers
/*
* Retourne une liste ordonnée d'id d'observation correspondant aux critères
* passés dans p et aux clauses where/join présentes dans le tableau $req
*
* @param p: $params (filtrés sauf escape-string)
* @param req: le tableau représentant les composants de la requete SQL
* @param db: l'instance de db
*/
static function getIdObs($p, $req, $db) {
$req_s = sprintf('SELECT SQL_CALC_FOUND_ROWS id_observation' .
' FROM v_del_image vdi'.
' %s' . // LEFT JOIN if any
' WHERE %s'. // where-clause ou TRUE
' %s'. // group-by
' %s'. // having (si commentaires)
' ORDER BY %s %s %s'.
' LIMIT %d, %d -- %s',
$req['join'] ? implode(' ', $req['join']) : '',
$req['where'] ? implode(' AND ', $req['where']) : 'TRUE',
 
$req['groupby'] ? ('GROUP BY ' . implode(', ', array_unique($req['groupby']))) : '',
$req['having'] ? ('HAVING ' . implode(' AND ', $req['having'])) : '',
 
$p['tri'], strtoupper($p['ordre']),
// date_transmission peut-être NULL et nous voulons de la consistence
// (sauf après r1860 de Cel)
$p['tri'] == 'date_transmission' ? ', id_observation' : '',
 
$p['navigation.depart'], $p['navigation.limite'], __FILE__ . ':' . __LINE__);
 
$res = $db->recupererTous($req_s);
$err = mysql_error();
if(!$res && $err) {
// http_response_code(400);
// if(defined('DEBUG') && DEBUG) header("X-Debug: $req_s");
throw new Exception('not found', 400);
}
// ordre préservé, à partir d'ici c'est important.
return $res;
}
 
/*
Champs récupérés:
Pour del_images, la vue retourne déjà ce que nous recherchons de cel_obs et cel_images
(cel_obs.* et cel_[obs_]images.{id_observation, id_image, date_prise_de_vue AS date, hauteur, largeur})
Pour del_commentaires: nous voulons *
Reste ensuite à formatter.
Note: le préfixe de table utilisé ici (vdi) n'impacte *aucune* autre partie du code car rien
n'en dépend pour l'heure. (inutilisation de $req['select'])
*/
static function getInfos($idobs, $db) {
/*$select_fields = implode(',', array_merge(
array_map(create_function('$a', 'return "vdi.".$a;'), self::$sql_fields_liaisons['dob']),
array_map(create_function('$a', 'return "vdi.".$a;'), self::$sql_fields_liaisons['di']),
array_map(create_function('$a', 'return "du.".$a;'), self::$sql_fields_liaisons['du'])));*/
$select_fields = array_merge(self::$sql_fields_liaisons['dob'],
self::$sql_fields_liaisons['di']);
$req_s = sprintf('SELECT %s FROM v_del_image vdi'.
// ' LEFT JOIN del_commentaire AS dc ON di.id_observation = dc.ce_observation AND dc.nom_sel IS NOT NULL'.
' WHERE id_observation IN (%s)',
implode(',', $select_fields),
implode(',', $idobs));
return $db->recupererTous($req_s);
}
 
 
/**
* Complément à DelTk::sqlAddConstraint()
*
* @param $p les paramètres (notamment de masque) passés par l'URL et déjà traités/filtrés (sauf quotes)
* @param $req le tableau, passé par référence représentant les composants de la requête à bâtir
* @param $c conteneur, utilisé soit pour l'appel récursif à requestFilterParams() en cas de param "masque"
* soit pour la définition du type (qui utilise la variable nb_commentaires_discussion)
*/
static function sqlAddConstraint($p, $db, &$req, Conteneur $c = NULL) {
if(!empty($p['masque.tag'])) {
// TODO: remove LOWER() lorsqu'on est sur que les tags sont uniformés en minuscule
// i_mots_cles_texte provient de la VIEW v_del_image
if(isset($p['masque.tag']['AND'])) {
/* Lorsque nous interprêtons la chaîne provenant du masque général (cf: buildTagsAST($p['masque'], 'OR', ' ') dans sqlAddMasqueConstraint()),
nous sommes splittés par espace. Cependant, assurons que si une virgule à été saisie, nous n'aurons pas le motif
" AND CONCAT(mots_cles_texte, i_mots_cles_texte) REGEXP ',' " dans notre requête.
XXX: Au 12/11/2013, une recherche sur tag depuis le masque général implique un OU, donc le problème ne se pose pas ici */
$subwhere = array();
foreach($p['masque.tag']['AND'] as $tag) {
if(trim($tag) == ',') continue;
 
$subwhere[] = sprintf('LOWER(CONCAT(%s)) REGEXP %s',
DelTk::sqlAddIfNullPourConcat(array('vdi.mots_cles_texte', 'vdi.i_mots_cles_texte')),
$db->proteger(strtolower($tag)));
}
$req['where'][] = '(' . implode(' AND ', $subwhere) . ')';
}
else {
$req['where'][] = sprintf('LOWER(CONCAT(%s)) REGEXP %s',
DelTk::sqlAddIfNullPourConcat(array('vdi.mots_cles_texte', 'vdi.i_mots_cles_texte')),
$db->proteger(strtolower(implode('|', $p['masque.tag']['OR']))));
}
}
 
if(!empty($p['masque.type'])) {
self::addTypeConstraints($p['masque.type'], $db, $req, $c);
}
}
 
/* Le masque fait une recherche générique parmi de nombreux champs ci-dessus.
Nous initialisons donc ces paramètres (excepté masque biensur), et nous rappelons
récursivement. À la seule différence que nous n'utiliserons que $or_req['where']
imploded par des " OR ". */
static function sqlAddMasqueConstraint($p, $db, &$req, Conteneur $c = NULL) {
if(!empty($p['masque'])) {
$or_params = array('masque.auteur' => $p['masque'],
'masque.departement' => $p['masque'],
'masque.id_zone_geo' => $p['masque'],
'masque.tag' => $p['masque'],
'masque.ns' => $p['masque'],
'masque.famille' => $p['masque'],
'masque.date' => $p['masque'],
'masque.genre' => $p['masque'],
/* milieu: TODO ? */ );
/* Cependant les champs spécifiques ont priorité sur le masque général.
Pour cette raison nous supprimons la génération de SQL du masque général sur les
champ spécifiques qui feront l'objet d'un traitement avec une valeur propre. */
if(isset($p['masque.auteur'])) unset($or_params['masque.auteur']);
if(isset($p['masque.departement'])) unset($or_params['masque.departement']);
if(isset($p['masque.id_zone_geo'])) unset($or_params['masque.id_zone_geo']);
if(isset($p['masque.tag'])) unset($or_params['masque.tag']);
if(isset($p['masque.famille'])) unset($or_params['masque.famille']);
if(isset($p['masque.date'])) unset($or_params['masque.date']);
if(isset($p['masque.genre'])) unset($or_params['masque.genre']);
 
 
$or_masque = DelTk::requestFilterParams($or_params, array_keys($or_params), $c);
if(isset($or_params['masque.tag'])) {
$or_masque['masque.tag'] = DelTk::buildTagsAST($p['masque'], 'OR', ' ');
}
 
// $or_req = array('select' => array(), 'join' => array(), 'where' => array(), 'groupby' => array(), 'having' => array());
$or_req = array('join' => array(), 'where' => array());
DelTk::sqlAddConstraint($or_masque, $db, $or_req);
self::sqlAddConstraint($or_masque, $db, $or_req);
 
if($or_req['where']) {
$req['where'][] = '(' . implode(' OR ', $or_req['where']) . ')';
// utile au cas ou des jointures seraient rajoutées
$req['join'] = array_unique(array_merge($req['join'], $or_req['join']));
}
}
}
 
 
private function configurer() {
$this->mappingVotes = $this->conteneur->getParametre('mapping_votes');
$this->mappingCommentaire = $this->conteneur->getParametre('mapping_commentaire');
}
 
 
/*
* @param $req: la représentation de la requête MySQL complète, à amender.
*/
static function addTypeConstraints($val, $db, &$req, Conteneur $c) {
if(array_key_exists('adeterminer', $val)) {
// On récupère toutes les observations qui on le tag "aDeterminer" *ou* qui n'ont pas de nom d'espèce
// *ou* qui ont la "certitude" à ("aDeterminer" *ou* "douteux")
$req['where'][] = '(' . implode(' OR ', array(
'vdi.certitude = "aDeterminer"',
'vdi.certitude = "douteux"',
'vdi.mots_cles_texte LIKE "%aDeterminer%"',
'vdi.nom_sel_nn IS NULL', // TODO: ensure pas d'entrée à 0
)) . ')';
}
if(array_key_exists('validees', $val)) {
//On récupère toutes les observations ayant un commentaire doté de proposition_retenue = 1
$req['join'][] = 'INNER JOIN del_commentaire AS dc ON vdi.id_observation = dc.ce_observation AND dc.proposition_retenue = 1';
}
 
// solution n°1: impraticable
if(false && array_key_exists('endiscussion', $val)) {
//Si on veut les observations en discussion,
// on va récupérer les ids des observations dont le nombre de commentaire est supérieur à N
$req['select'][] = 'COUNT(dc.id_commentaire) AS comm_count';
$req['join'][] = 'INNER JOIN del_commentaire AS dc ON vdi.id_observation = dc.ce_observation';
$req['groupby'][] = 'vdi.id_observation';
$req['having'][] = "COUNT(id_commentaire) > " . $c->getParametre('nb_commentaires_discussion');
}
 
if(array_key_exists('endiscussion', $val)) {
$req['where'][] = '(SELECT COUNT(id_commentaire) FROM del_commentaire AS dc'.
' WHERE ce_observation = id_observation) > ' . intval($c->getParametre('nb_commentaires_discussion'));
}
}
 
 
/**
* Récupérer toutes les déterminations et le nombre de commentaire au total
* @param array $observations la liste des observations à mettre à jour
* */
private function chargerDeterminations(&$observations) {
$idObs = array_values(array_map(create_function('$a', 'return $a["id_observation"];'),
$observations));
$r = sprintf('SELECT * FROM del_commentaire AS dc WHERE dc.nom_sel IS NOT NULL AND ce_observation IN (%s) -- %s',
implode(',',$idObs),
__FILE__ . ':' . __LINE__);
$propositions = $this->bdd->recupererTous($r);
if(!$propositions) return;
foreach ($propositions as $proposition) {
$idObs = $proposition['ce_observation'];
$idComment = $proposition['id_commentaire'];
$comment = $this->formaterDetermination($idComment, $proposition);
if($comment) $observations['"' . $idObs . '"']['commentaires'][$idComment] = $comment;
}
}
 
private function formaterDetermination($commentId, $proposition) {
if(!$proposition) return NULL;
 
$proposition_formatee = array('nb_commentaires' => '0');
foreach ($this->mappingCommentaire as $nomOriginal => $nomFinal) {
if (isset($proposition[$nomOriginal])) {
$proposition_formatee[$nomFinal] = $proposition[$nomOriginal];
}
}
 
// Charger les votes sur les déterminations
$resultatsVotes = $this->bdd->recupererTous(
sprintf('SELECT * FROM del_commentaire_vote WHERE ce_proposition = %d', $commentId));
foreach ($resultatsVotes as $vote) {
$proposition_formatee['votes'][$vote['id_vote']] = $this->formaterVote($vote);
}
 
 
// chargerNombreCommentaire()
// Charger le nombre de commentaires (sans détermination) associé à l'observation
$listeCommentaires = $this->bdd->recupererTous(sprintf(
'SELECT ce_commentaire_parent, ce_proposition, COUNT( id_commentaire ) AS nb '.
'FROM del_commentaire WHERE ce_proposition = %d GROUP BY ce_proposition -- %s',
$commentId, __FILE__ . ':' . __LINE__));
foreach ($listeCommentaires as $ligneProposition) {
// ce test sert à exclure les proposition de 1er niveau qui sont elles aussi des commentaires
if($ligneProposition['ce_commentaire_parent']) {
// TODO/debug: id_commentaire_parent != $commentId ??
// reprendre la "logique" du code... moins de boucles, moins de requêtes, ...
if($ligneProposition['ce_commentaire_parent'] != $commentId) {
// restore_error_handler();
error_log(sprintf("possible error: nb_commentaires = %s: comment = %d, parent = %d, %s",
$ligneProposition['nb'], $commentId, $ligneProposition['ce_commentaire_parent'], __FILE__));
}
$proposition_formatee['nb_commentaires'] = $ligneProposition['nb'];
} else {
$proposition_formatee['observation']['nb_commentaires'] = $ligneProposition['nb'];
}
}
 
return $proposition_formatee;
}
 
/**
* Formater un vote en fonction du fichier de configuration config_votes.ini
* @param $votes array()
* */
private function formaterVote($vote) {
$retour = array();
foreach ($vote as $param=>$valeur) {
$retour[$this->mappingVotes[$param]] = $valeur;
}
return $retour;
}
}
/tags/v1.1-helium/services/modules/0.1/observations/ListeObservationsWidget.php
New file
0,0 → 1,394
<?php
// declare(encoding='UTF-8');
/**
* Le web service observations récupère toutes les observations et, pour chacune d'elle, les
* images qui lui sont associées.
*
* @category php 5.2
* @package del
* @subpackage images
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Observations
*/
 
class ListeObservationsWidget {
private $conteneur;
private $navigation;
private $masque;
private $gestionBdd;
private $bdd;
private $parametres = array();
private $ressources = array();
private $tri = 'date_transmission';
private $directionTri = 'desc';
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_observations.ini');
$this->conteneur->chargerConfiguration('config_departements_bruts.ini');
$this->navigation = $conteneur->getNavigation();
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
/**
* Méthode principale de la classe.
* Lance la récupération des images dans la base et les place dans un objet ResultatService
* pour l'afficher.
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
* @param array $parametres les paramètres situés après le ? dans l'url
* */
public function consulter($ressources, $parametres) {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
// Gestion des configuration du script
$this->configurer();
$this->verifierConfiguration();
$this->verifierParametresTri();
$this->initialiserTri();
// Lancement du service
$observations = $this->chargerObservations();
$total = $this->compterObservations();
$this->navigation->setTotal($total);
$observations = $this->formaterObservations($observations);
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
$resultat->corps = array('entete' => $this->conteneur->getEntete(), 'resultats' => $observations);
return $resultat;
}
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
private function verifierParametresTri() {
$erreurs = array();
$tris_possibles = $this->conteneur->getParametre('tris_possibles');
$tris_possibles_tableau = explode(',', $tris_possibles);
if(isset($this->parametres['tri']) && !in_array($this->parametres['tri'], $tris_possibles_tableau)) {
$erreurs[] = '- le type de tri demandé est incorrect, les valeurs possibles sont '.$tris_possibles.' ;';
}
$directions_tri = array('asc', 'desc');
if(isset($this->parametres['ordre']) && !in_array($this->parametres['ordre'], $directions_tri)) {
$erreurs[] = '- la direction du tri demandé est incorrecte, les valeurs supportées sont asc ou desc ;';
}
if (!empty($erreurs)) {
$e = 'Erreur lors de l\'analyse des parametres du tri : '."\n";
$e .= implode("\n", $erreurs);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
private function initialiserTri() {
$this->tri = isset($this->parametres['tri']) ? $this->parametres['tri'] : $this->tri;
$this->directionTri = isset($this->parametres['ordre']) ? $this->parametres['ordre'] : $this->directionTri;
}
/*-------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
--------------------------------------------------------------------------------*/
/**
* Configuration du service en fonction du fichier de config config_del.ini
* */
private function configurer() {
$this->mappingFiltre = $this->conteneur->getParametre('mapping_masque');
$this->mappingObservation = $this->conteneur->getParametre('mapping_observation');
$this->mappingVotes = $this->conteneur->getParametre('mapping_votes');
$this->mappingCommentaire = $this->conteneur->getParametre('mapping_commentaire');
}
/**
* Vérifier que le service est bien configuré
* */
private function verifierConfiguration() {
$erreurs = array();
$tableauObservations = $this->conteneur->getParametre('observations');
if (empty($tableauObservations)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [images] ou celui-ci est vide ;';
} else {
if ($this->conteneur->getParametre('url_service') == null) {
$erreurs[] = '- paramètre "url_service" manquant ;';
}
if ($this->conteneur->getParametre('url_images') == null) {
$erreurs[] = '- paramètre "url_images" manquant ;';
}
}
 
if (empty($this->mappingObservation)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [mapping_observation] ou celui-ci est vide ;';
} else {
$champsMappingObs = array('id_observation', 'date_observation', 'date_transmission', 'famille', 'nom_sel', 'nom_sel_nn', 'nt',
'ce_zone_geo', 'zone_geo', 'lieudit', 'station', 'courriel', 'ce_utilisateur', 'nom', 'prenom');
foreach ($champsMappingObs as $champ) {
if (!isset($this->mappingObservation[$champ])) {
$erreurs[] = '- le mapping du champ "'.$champ.'" pour l\'observation est manquant ;';
}
}
}
if (!empty($erreurs)) {
$e = 'Erreur lors de la configuration : '."\n";
$e .= implode("\n", $erreurs);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
/**
* Charger la clause WHERE en fonction des paramètres de masque
* */
private function chargerClauseWhere() {
$where = array();
$tableauMasque = $this->masque->getMasque();
if (!empty($tableauMasque)) {
foreach($tableauMasque as $idMasque => $valeurMasque) {
$idMasque = str_replace('masque.', '', $idMasque);
switch ($idMasque) {
// nom du masque => nom BDD
case 'auteur' :
$whereAuteur = ' '.$this->creerFiltreAuteur($this->masque->getMasque('auteur'));
if($whereAuteur != '') {
$where[] = $whereAuteur;
}
break;
case 'date' :
$whereDate = ' '.$this->creerFiltreDate($valeurMasque);
if($whereDate != '') {
$where[] = $whereDate;
}
break;
case 'departement' :
$where[] = ' '.$this->creerFiltreIdZoneGeo($valeurMasque);
break;
case 'genre' :
$where[] = ' '.$this->mappingFiltre['ns'].' LIKE '.$this->proteger('%'.$valeurMasque.'% %');
break;
case 'tag' :
$where[] = ' '.$this->creerFiltreMotsCles($valeurMasque);
break;
case 'ns' :
$where[] = ' nom_sel LIKE '.$this->proteger($valeurMasque.'%');
break;
case 'commune' :
$where[] = ' '.$this->mappingFiltre[$idMasque].' LIKE '.$this->proteger(str_replace(array('-',' '), '_', $valeurMasque).'%');
break;
case 'masque' :
$where[] = ' '.$this->creerFiltreMasqueGeneral($valeurMasque);
break;
default:
$where[] = ' '.$this->mappingFiltre[$idMasque].' = '.$this->proteger($valeurMasque);
break;
}
}
}
if (!empty($where)) {
return ' WHERE '.implode('AND', $where);
} else {
return;
}
}
private function creerFiltreMasqueGeneral($valeurMasque) {
//TODO: affecter d'aborder les variables, puis les tester pour les
// ajouter à la chaine
$whereAuteur = $this->creerFiltreAuteur($valeurMasque);
$whereIdZoneGeo = $this->creerFiltreIdZoneGeo($valeurMasque);
$masqueGeneral = '( '.
(($whereAuteur != '') ? $whereAuteur.' OR ' : '' ).
(($whereIdZoneGeo != '') ? $whereIdZoneGeo.' OR ' : '' ).
'zone_geo LIKE '.$this->proteger($this->remplacerParJokerCaractere($valeurMasque).'%').' OR '.
$this->creerFiltreMotsCles($valeurMasque).' OR '.
'nom_sel LIKE '.$this->proteger($valeurMasque.'%').' OR '.
'famille LIKE '.$this->proteger($valeurMasque.'%').' OR '.
'milieu LIKE '.$this->proteger($valeurMasque).' OR '.
$this->mappingFiltre['ns'].' LIKE '.$this->proteger('%'.$valeurMasque.'% %').' OR '.
$this->creerFiltreDate($valeurMasque).
') ';
return $masqueGeneral;
}
private function creerFiltreAuteur($valeurMasque) {
$masque = '';
$auteurId = $valeurMasque;
if (is_numeric($auteurId)) {
$masque = ' ce_utilisateur = '.$auteurId;
} else {
if (strpos($auteurId, '@') === false) {
$tableauNomPrenom = explode(' ',$auteurId, 2);
if(count($tableauNomPrenom) == 2) {
// on teste potentiellement un nom prenom ou bien un prénom nom
$masque = '('.
'(nom LIKE '.$this->proteger($tableauNomPrenom[0].'%').' AND '.
'prenom LIKE '.$this->proteger($tableauNomPrenom[1].'%').') OR '.
'(nom LIKE '.$this->proteger($tableauNomPrenom[1].'%').' AND '.
'prenom LIKE '.$this->proteger($tableauNomPrenom[0].'%').') OR '.
'(dob.nom_utilisateur LIKE '.$this->proteger($tableauNomPrenom[0].'%').' AND '.
'dob.prenom_utilisateur LIKE '.$this->proteger($tableauNomPrenom[1].'%').') OR '.
'(dob.nom_utilisateur LIKE '.$this->proteger($tableauNomPrenom[1].'%').' AND '.
'dob.prenom_utilisateur LIKE '.$this->proteger($tableauNomPrenom[0].'%').') '.
')';
} else {
$masque = '(
(nom LIKE '.$this->proteger($auteurId.'%').' OR '.
'prenom LIKE '.$this->proteger($auteurId.'%').' OR '.
'dob.nom_utilisateur LIKE '.$this->proteger($auteurId.'%').' OR '.
'dob.prenom_utilisateur LIKE '.$this->proteger($auteurId.'%').')'.
')';
}
} else {
$masque = " courriel LIKE ".$this->proteger($valeurMasque.'%').
" OR dob.courriel_utilisateur LIKE ".$this->proteger($valeurMasque.'%')." ";
}
}
return $masque;
}
private function remplacerParJokerCaractere($valeurMasque) {
return str_replace(array('-',' '), '_', $valeurMasque);
}
//TODO: déplacer les fonctions ci dessus et dessous dans une classe
// utilitaire
function supprimerAccents($str, $charset='utf-8')
{
$str = htmlentities($str, ENT_NOQUOTES, $charset);
$str = preg_replace('#&([A-za-z])(?:acute|cedil|circ|grave|orn|ring|slash|th|tilde|uml);#', '\1', $str);
$str = preg_replace('#&([A-za-z]{2})(?:lig);#', '\1', $str); // pour les ligatures e.g. '&oelig;'
$str = preg_replace('#&[^;]+;#', '', $str); // supprime les autres caractères
return $str;
}
private function obtenirIdDepartement($nomDpt) {
$nomDpt = $this->supprimerAccents($nomDpt);
$nomDpt = strtolower(str_replace(' ','-',$nomDpt));
$idDpt = $this->conteneur->getParametre($nomDpt);
if($idDpt == null || $idDpt == ' ') {
$idDpt = ' ';
}
return $idDpt;
}
private function creerFiltreIdZoneGeo($valeurMasque) {
$masque = '';
$dept = $valeurMasque;
if (is_numeric($dept)) {
$dept = sprintf('%02s', $dept);
$dept = sprintf("%-'_5s", $dept);
$masque = " ce_zone_geo LIKE ".$this->proteger('INSEE-C:'.$dept);
} else {
$deptId = $this->conteneur->getParametre($dept);
if ($deptId != null) {
$masque = " ce_zone_geo LIKE ".$this->proteger('INSEE-C:'.$deptId.'%');
} else {
$id = $this->obtenirIdDepartement($valeurMasque);
$masque = " ce_zone_geo LIKE ".$this->proteger('INSEE-C:'.$id.'%');
}
}
return $masque;
}
private function creerFiltreDate($valeurMasque) {
//TODO: définir dans le fichier de config un tableau contenant plusieurs format de date
// autorisés pour la recherche, qui seraient ajoutés au OR
$masque = '(';
$masque .= (is_numeric($valeurMasque)) ? ' YEAR(date_observation) = '.$this->proteger($valeurMasque).' OR ' : '';
$masque .= " DATE_FORMAT(date_observation, '%d/%m/%Y') = ".$this->proteger($valeurMasque).' '.
')';
return $masque;
}
private function creerFiltreMotsCles($valeurMasque) {
$mots_cles = explode(' ', $valeurMasque);
$requeteMotsClesImg = '';
$requeteMotsClesObs = '';
//TODO voir s'il existe un moyen plus simple que le foreach + rtrim
// comme avec implode (attention au fait que l'on concatène des % au début et à la fin)
foreach($mots_cles as $mot_cle) {
$requeteMotsCles = $this->proteger('%'.$mot_cle.'%');
$requeteMotsClesObs .= 'dob.mots_cles_texte LIKE '.$requeteMotsCles.' AND ';
}
$requeteMotsClesImg = rtrim($requeteMotsClesImg, ' AND ');
$requeteMotsClesObs = rtrim($requeteMotsClesObs, ' AND ');
$masque = '('.
'('.$requeteMotsClesImg.') OR '.
'('.$requeteMotsClesObs.') '.
') ';
return $masque;
}
/*-------------------------------------------------------------------------------
CHARGEMENT DES OBSERVATIONS
--------------------------------------------------------------------------------*/
/**
* Chargement depuis la bdd de toutes les liaisons entre images et observations
* */
private function chargerObservations() {
$requete = 'SELECT DISTINCT dob.id_observation '.
'FROM '.$this->gestionBdd->formaterTable('del_observation', 'dob').
'INNER JOIN '.$this->gestionBdd->formaterTable('del_obs_image', 'doi').
'ON doi.id_observation = dob.id_observation '.
$this->chargerClauseWhere().
' ORDER BY '.$this->tri.' '.$this->directionTri.' '.
$this->gestionBdd->getLimitSql();
return $this->bdd->recupererTous($requete);
}
/**
* Compter le nombre total d'images dans la base pour affichage dans entete.
* */
private function compterObservations() {
$requete = 'SELECT FOUND_ROWS() AS nbre ';
$resultats = $this->bdd->recuperer($requete);
return (int) $resultats['nbre'];
}
/**
* Retourner un tableau d'images formaté en fonction des liaisons trouvées
* @param $liaisons les liaisons de la table del_obs_images
* */
private function formaterObservations($liaisons) {
$observations = array();
foreach ($liaisons as $liaison) {
$observations[] = $liaison['id_observation'];
}
return $observations;
}
/*-------------------------------------------------------------------------------
FORMATER ET METTRE EN FORME
--------------------------------------------------------------------------------*/
private function proteger($valeur) {
if (is_array($valeur)) {
return $this->bdd->protegerTableau($valeur);
} else {
return $this->bdd->proteger($valeur);
}
}
}
?>
/tags/v1.1-helium/services/modules/0.1/Protocoles.php
New file
0,0 → 1,196
<?php
/**
* Description :
* Classe principale de chargement des services d'eFlore.
*
* Encodage en entrée : utf8
* Encodage en sortie : utf8
* @package eflore-projets
* @author Jennifer DHÉ <jennifer.dhe@tela-botanica.org>
* @author Delphine CAUQUIL <delphine@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version 0.1
* @copyright 1999-2011 Tela Botanica (accueil@tela-botanica.org)
*/
class Protocoles extends RestService {
 
/*
* url possibles :
* http://localhost/del/services/0.1/observations/ => toutes les observations (infos obs, infos images, infos propositions, infos nb commentaires)
* http://localhost/del/services/0.1/observations/#id => une observation donnée et ses images, SANS LES propositions & nombre de commentaire
* */
private $parametres = array();
private $ressources = array();
private $methode = null;
private $projetNom = array();
private $serviceNom = array();
private $cheminCourant = null;
 
private $conteneur;
/** Indique si oui (true) ou non (false), on veut utiliser les paramètres bruts. */
protected $utilisationParametresBruts = true;
 
public function __construct() {
$this->cheminCourant = dirname(__FILE__).DS;
}
 
public function consulter($ressources, $parametres) {
$this->methode = 'consulter';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
$reponseHttp->setResultatService($resultat);
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
}
$reponseHttp->emettreLesEntetes();
$corps = $reponseHttp->getCorps();
return $corps;
}
public function ajouter($ressources, $requeteDonnees) {
$this->methode = 'ajouter';
$resultat = '';
try {
$this->initialiserRessourcesEtParametres($ressources, $requeteDonnees);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
}
}
 
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function traiterRessources() {
$retour = '';
$this->initialiserProjet();
if ($this->avoirRessourceService()) {
$retour = $this->initialiserService();
}
return $retour;
}
private function avoirRessourceIdentifiant($num) {
$presenceId = false;
if (is_numeric($this->ressources[$num])) {
$presenceId = true;
} else {
$message = "Le service demandé '$service' nécessite d'avoir un identifiant d'image valide";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
return $presenceId;
}
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU PROJET
------------------------------------------------------------------------------------------------------------------*/
private function initialiserProjet() {
$this->chargerNomDuProjet();
$this->chargerConfigProjet();
 
}
 
private function chargerNomDuProjet() {
$this->projetNom = 'protocoles';
}
 
private function chargerConfigProjet() {
$projet = $this->projetNom;
$chemin = Config::get('chemin_configurations')."config_$projet.ini";
Config::charger($chemin);
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
------------------------------------------------------------------------------------------------------------------*/
private function avoirRessourceService() {
/*
* url possibles :
* http://localhost/del/services/0.1/observations/ => toutes les observations (infos obs, infos images, infos propositions, infos nb commentaires)
* http://localhost/del/services/0.1/observations/#id => une observation donnée et ses images, SANS LES propositions & nombre de commentaire
* */
$presenceRessourceService = false;
if (isset($this->ressources[0])) {
if ($this->avoirRessourceIdentifiant(0)) {
if (sizeof($this->ressources) == 1) {
$presenceRessourceService = true;
$this->serviceNom = 'observation';
} else {
if (isset($this->ressources[1])) {
$presenceRessourceService = $this->avoirRessourceSousService();
}
}
}
} else {
$presenceRessourceService = true;
$this->serviceNom = 'liste-protocoles';
}
return $presenceRessourceService;
}
private function avoirRessourceSousService() {
$presenceRessourceService = false;
$servicesDispo = Outils::recupererTableauConfig('servicesDispo');
if ($this->avoirRessourceIdentifiant(1)) {
$service = $this->ressources[2];
if (in_array($service, $servicesDispo)) {
$presenceRessourceService = true;
$this->serviceNom = 'vote-observation';
} else {
$message = "Le service demandé '$service' n'est pas disponible pour le projet {$this->projetNom} !\n".
"Les services disponibles sont : ".implode(', ', $servicesDispo);
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
}
return $presenceRessourceService;
}
 
private function initialiserService() {
//$this->chargerNomDuService();
$classe = $this->obtenirNomClasseService($this->serviceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->projetNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
$this->conteneur->chargerConfiguration('config_'.$this->projetNom.'.ini');
require_once $chemin;
$service = new $classe($this->conteneur);
if ($this->methode == 'consulter') {
$retour = $service->consulter($this->ressources, $this->parametres);
} elseif ($this->methode == 'ajouter') {
$retour = $service->ajouter($this->ressources, $this->parametres);
}
}
}
if (is_null($service)) {
$message = "Le service demandé '{$this->serviceNom}' n'existe pas dans le projet {$this->projetNom} !";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
return $retour;
}
 
private function obtenirNomClasseService($mot) {
$classeNom = str_replace(' ', '', ucwords(strtolower(str_replace('-', ' ', $mot))));
return $classeNom;
}
}
?>
/tags/v1.1-helium/services/modules/0.1/MotsCles.php
New file
0,0 → 1,211
<?php
/**
* Description :
* Classe principale de chargement des services d'eFlore.
*
* Encodage en entrée : utf8
* Encodage en sortie : utf8
* @package del
* @author Aurélien Peronnet <aurelien@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version 0.1
* @copyright 1999-2011 Tela Botanica (accueil@tela-botanica.org)
*/
class MotsCles extends RestService {
 
/*
* url possibles :
* http://localhost/del/services/0.1/motscles/#id => les mots clés associés à une image donnée
* */
private $parametres = array();
private $ressources = array();
private $methode = null;
private $projetNom = array();
private $serviceNom = array();
private $cheminCourant = null;
 
private $conteneur;
/** Indique si oui (true) ou non (false), on veut utiliser les paramètres bruts. */
protected $utilisationParametresBruts = true;
 
public function __construct() {
$this->cheminCourant = dirname(__FILE__).DS;
}
 
public function consulter($ressources, $parametres) {
$this->methode = 'consulter';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
$reponseHttp->setResultatService($resultat);
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
}
$reponseHttp->emettreLesEntetes();
$corps = $reponseHttp->getCorps();
return $corps;
}
public function ajouter($ressources, $parametres) {
$this->methode = 'ajouter';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
$reponseHttp->setResultatService($resultat);
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
}
$corps = $reponseHttp->getCorps();
return $corps;
}
public function supprimer($ressources) {
$this->methode = 'supprimer';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->ressources = $ressources;
$this->conteneur = new Conteneur();
$resultat = $this->traiterRessources();
$reponseHttp->setResultatService($resultat);
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
$reponseHttp->emettreLesEntetes();
echo $reponseHttp->getCorps();
}
}
public function modifier($ressources, $requeteDonnees) {
}
 
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function traiterRessources() {
$retour = '';
$this->initialiserProjet();
$retour = $this->initialiserService();
return $retour;
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU PROJET
------------------------------------------------------------------------------------------------------------------*/
private function initialiserProjet() {
$this->chargerNomDuProjet();
$this->chargerConfigProjet();
 
}
 
private function chargerNomDuProjet() {
$this->projetNom = 'motscles';
}
 
private function chargerConfigProjet() {
$projet = $this->projetNom;
$chemin = Config::get('chemin_configurations')."config_mots_cles.ini";
Config::charger($chemin);
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
------------------------------------------------------------------------------------------------------------------*/
private function chargerNomService() {
// si la méthode est POST, on ajouter un commentaire
if ($this->methode == 'ajouter') {
$this->serviceNom = 'ajouter-mot-cle';
} else if ($this->methode == 'supprimer') {
$this->serviceNom = 'supprimer-mot-cle';
}
else {
//S'il n'y a pas de ressources => tous les commentaires
if (!isset($this->ressources) || empty($this->ressources)) {
$this->serviceNom = 'liste-mots-cles';
} else {
if (!is_numeric($this->ressources[0])) {
$message = "La première ressource doit être un identifiant";
$code = RestServeur::HTTP_CODE_ERREUR;
throw new Exception($message, $code);
} else {
$this->serviceNom = 'consulter-mots-cles';
}
}
}
}
private function editerMessageErreurRessource() {
$message = "Le service demandé '".$this->projetNom.'/'.implode('/', $this->ressources).
"' n'est pas disponible pour le projet ".$this->projetNom." !\n".
"Les services disponibles sont : images, images/#id/votes, images/#id/vote/#id_vote";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
private function etreRessourceIdentifiant($num) {
$presenceId = false;
if (is_numeric($this->ressources[$num])) {
$presenceId = true;
} else {
$message = "Le service demandé '$service' nécessite d'avoir un identifiant d'image valide";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
return $presenceId;
}
 
private function initialiserService() {
$this->chargerNomService();
$classe = $this->obtenirNomClasseService($this->serviceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->projetNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
$this->conteneur->chargerConfiguration('config_mots_cles.ini');
require_once $chemin;
$service = new $classe($this->conteneur);
if ($this->methode == 'consulter') {
$retour = $service->consulter($this->ressources, $this->parametres);
} elseif ($this->methode == 'ajouter') {
$retour = $service->ajouter($this->ressources, $this->parametres);
} elseif ($this->methode == 'modifier') {
$retour = $service->modifier($this->ressources, $this->parametres);
} elseif ($this->methode == 'supprimer') {
$retour = $service->supprimer($this->ressources, $this->parametres);
}
}
}
if (is_null($service)) {
$message = "Le service demandé '{$this->serviceNom}' n'existe pas dans le projet {$this->projetNom} !";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
return $retour;
}
 
private function obtenirNomClasseService($mot) {
$classeNom = str_replace(' ', '', ucwords(strtolower(str_replace('-', ' ', $mot))));
return $classeNom;
}
}
?>
/tags/v1.1-helium/services/modules/0.1/Utilisateurs.php
New file
0,0 → 1,159
<?php
/**
* Description :
* Classe principale de chargement des services d'eFlore.
*
* Encodage en entrée : utf8
* Encodage en sortie : utf8
* @package eflore-projets
* @author Jennifer DHÉ <jennifer.dhe@tela-botanica.org>
* @author Delphine CAUQUIL <delphine@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version 0.1
* @copyright 1999-2011 Tela Botanica (accueil@tela-botanica.org)
*/
class Utilisateurs extends RestService {
 
private $parametres = array();
private $ressources = array();
private $methode = null;
private $projetNom = array();
private $serviceNom = array();
private $cheminCourant = null;
 
private $conteneur;
/** Indique si oui (true) ou non (false), on veut utiliser les paramètres bruts. */
protected $utilisationParametresBruts = true;
 
public function __construct() {
$this->cheminCourant = dirname(__FILE__).DS;
}
 
public function consulter($ressources, $parametres) {
$this->methode = 'consulter';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
$reponseHttp->setResultatService($resultat);
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
}
$reponseHttp->emettreLesEntetes();
$corps = $reponseHttp->getCorps();
return $corps;
}
public function modifier($ressources, $parametres) {
$this->methode = 'modifier';
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$this->initialiserRessourcesEtParametres($ressources, $parametres);
$this->conteneur = new Conteneur($this->parametres);
$resultat = $this->traiterRessources();
$reponseHttp->setResultatService($resultat);
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
}
$reponseHttp->emettreLesEntetes();
$corps = $reponseHttp->getCorps();
return $corps;
}
private function initialiserRessourcesEtParametres($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function traiterRessources() {
$retour = '';
$this->initialiserProjet();
$retour = $this->initialiserService();
return $retour;
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU PROJET
------------------------------------------------------------------------------------------------------------------*/
private function initialiserProjet() {
$this->projetNom = 'utilisateurs';
$this->chargerConfigProjet();
}
 
private function chargerConfigProjet() {
$projet = $this->projetNom;
$chemin = Config::get('chemin_configurations')."config_$projet.ini";
Config::charger($chemin);
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
------------------------------------------------------------------------------------------------------------------*/
private function initialiserService() {
$this->chargerNomService();
$classe = $this->obtenirNomClasseService($this->serviceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->projetNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
$this->conteneur->chargerConfiguration('config_'.$this->projetNom.'.ini');
require_once $chemin;
$service = new $classe($this->conteneur);
if ($this->methode == 'consulter') {
$retour = $service->consulter($this->ressources, $this->parametres);
} elseif ($this->methode == 'ajouter') {
$retour = $service->ajouter($this->ressources, $this->parametres);
} elseif ($this->methode == 'modifier') {
$retour = $service->modifier($this->ressources, $this->parametres);
}
}
}
if (is_null($service)) {
$message = "Le service demandé '{$this->serviceNom}' n'existe pas dans le projet {$this->projetNom} !";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
return $retour;
}
private function chargerNomService() {
//S'il n'y a pas de ressources => envoyer sur identification anonyme
if (!isset($this->ressources) || empty($this->ressources)) {
$this->serviceNom = 'identification-anonyme';
} else {
//S'il y a 1 ressource et que celle ci est 'deconnecter', envoyer vers deconnecter
if (sizeof($this->ressources) == 1 && ($this->ressources[0] == 'deconnecter')) {
$this->serviceNom = 'deconnecter';
} else if(sizeof($this->ressources) == 2 && $this->ressources[1] == 'preferences') {
$this->serviceNom = 'preferences';
} else if (sizeof($this->ressources) == 2) {
$this->serviceNom = 'connecter';
} else {
$this->serviceNom = 'identification-anonyme';
}
}
}
 
private function obtenirNomClasseService($mot) {
$classeNom = str_replace(' ', '', ucwords(strtolower(str_replace('-', ' ', $mot))));
return $classeNom;
}
 
 
}
?>
/tags/v1.1-helium/services/modules/0.1/syndication/SyndicationCommentaires.php
New file
0,0 → 1,315
<?php
/**
* Service fournissant des informations concernant les commentaire de DEL au format RSS1, RSS2 ou ATOM.
* Encodage en entrée : utf8
* Encodage en sortie : utf8
*
* @author Aurélien PERONNET <aurelien@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright 2010
*/
class SyndicationCommentaires {
 
private $ressources = null;
private $parametres = null;
private $format = null;
private $service = null;
private $squelette = null;
private $squelette_dossier = null;
private $masque = array();
private $mappingFiltre = array();
private $conteneur = null;
private $gestionBdd = null;
private $navigation = null;
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_syndication_commentaires.ini');
$this->mappingFiltre = $this->conteneur->getParametre('mapping_masque');
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->navigation = $conteneur->getNavigation();
}
 
public function consulter($params = array()) {
$this->verifierConfiguration();
 
if ($this->fluxAdminDemande()) {
$this->demanderAutorisationAdmin();
}
 
$donnees_brutes = $this->getDerniersCommentaires();
$commentaires_formates = $this->formaterPourRss($donnees_brutes) ;
return $commentaires_formates;
}
 
/**
* Vérifier que le service est bien configuré
* */
public function verifierConfiguration() {
$erreurs = array();
 
if (empty($this->mappingFiltre)) {
$erreurs[] = 'Le fichier de configuration ne contient pas le tableau [mapping_masque] ou celui-ci est vide.';
}
 
if (!empty($erreurs)) {
$e = 'Erreur lors de la configuration : '."\n";
$e .= implode("\n", $erreurs);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
 
/**
* Verifier si le flux admin est demande
*/
private function fluxAdminDemande() {
return $this->conteneur->getParametre('admin') != null && $this->conteneur->getParametre('admin') == 1;
}
 
private function demanderAutorisationAdmin() {
$verification = new ControleAcces($this->conteneur);
$verification->demanderAuthentificationAdmin();
}
 
private function formaterPourRss($elements) {
$donnees = $this->construireDonneesCommunesAuFlux($elements);
foreach ($elements as $element) {
$identifiants[$element['id_commentaire']] = $element['id_commentaire'];
}
foreach ($elements as $element) {
$donnees['items'][] = $this->construireDonneesCommunesAuxItems($element);
}
return $donnees;
}
 
private function construireDonneesCommunesAuFlux($infos) {
$donnees = array();
$donnees['guid'] = htmlspecialchars($this->creerUrlService());
$donnees['titre'] = 'identiPlante : commentaires et propositions';
$donnees['description'] = 'Ce flux regroupe les dernières déterminations et commentaires rédigés dans l\'application identiPlante';
$donnees['lien_service'] = htmlspecialchars($this->creerUrlService());
$donnees['lien_del'] = $this->conteneur->getParametre('delAppliLien');
$donnees['editeur'] = $this->conteneur->getParametre('editeur');
$derniere_info_en_date = reset($infos);
$date_modification_timestamp = $this->convertirDateHeureMysqlEnTimestamp($derniere_info_en_date['date']);
$donnees['date_maj_RSS'] = date(DATE_RSS, $date_modification_timestamp);
$donnees['date_maj_ATOM'] = date(DATE_ATOM, $date_modification_timestamp);
$donnees['date_maj_W3C'] = date(DATE_W3C, $date_modification_timestamp);
$donnees['annee_courante'] = date('Y');
$donnees['generateur'] = 'DEL - SyndicationCommentaire';
$donnees['generateur_version'] = (preg_match('/([0-9]+)/', '$Revision$', $match)) ? $match[1] : '0';
return $donnees;
}
 
private function creerUrlService() {
$url_service = 'http://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
return $url_service;
}
 
private function construireDonneesCommunesAuxItems($info) {
$item = array();
$date_modification_timestamp = $this->convertirDateHeureMysqlEnTimestamp($info['date']);
$item['date_maj_simple'] = strftime('%A %d %B %Y à %H:%M', $date_modification_timestamp);
$item['date_maj_RSS'] = date(DATE_RSS, $date_modification_timestamp);
$item['date_maj_ATOM'] = date(DATE_ATOM, $date_modification_timestamp);
$item['date_maj_W3C'] = date(DATE_W3C, $date_modification_timestamp);
$item['titre'] = $this->creerTitre($info);
$item['guid'] = $this->creerGuidItem($info);
$item['lien'] = $this->creerLienItem($info);
$item['categorie'] = $this->creerCategorie($item);
$item['description'] = $this->creerDescription($info, $item);
$item['description_encodee'] = htmlspecialchars($this->creerDescription($info, $item));
$item['modifier_par'] = $this->creerAuteur($info);
return $item;
}
 
protected function convertirDateHeureMysqlEnTimestamp($date_heure_mysql){
$timestamp = 0;
// Le date de 1970-01-01 pose problème dans certains lecteur de Flux, on met donc la date de création de Tela
$date_heure_mysql = ($date_heure_mysql == '0000-00-00 00:00:00') ? '1999-12-14 00:00:00' : $date_heure_mysql;
if ($date_heure_mysql != '0000-00-00 00:00:00') {
$val = explode(' ', $date_heure_mysql);
$date = explode('-', $val[0]);
$heure = explode(':', $val[1]);
$timestamp = mktime((int) $heure[0], (int) $heure[1], (int) $heure[2], (int) $date[1], (int) $date[2], (int) $date[0]);
}
return $timestamp;
}
 
private function creerTitre($element) {
$nomPropose = htmlspecialchars($element['nom_sel']);
$intitule = ($element['nom_sel'] != '') ? "Proposition $nomPropose" : 'Commentaire';
$auteur = htmlspecialchars($this->creerAuteur($element));
$nomSelActuel = htmlspecialchars($element['dob_nom_sel']);
$zoneGeo = htmlspecialchars((($element['dob_zone_geo'] != '') ? $element['dob_zone_geo'] : '?'));
$dateObs = htmlspecialchars(strftime('%d %B %Y', strtotime($element['dob_date_observation'])));
 
$titre = "$intitule par $auteur pour $nomSelActuel à $zoneGeo le $dateObs";
return $titre;
}
 
private function creerAuteur($info) {
$auteur = 'Anonyme';
if ($info['utilisateur_prenom'] != '' && $info['utilisateur_nom'] != '') {
$auteur = $info['utilisateur_prenom'].' '.$info['utilisateur_nom'];
}
return $auteur;
}
 
private function creerGuidItem($element) {
$guid = sprintf($this->conteneur->getParametre('guidObsTpl'), $element['id_commentaire']);
return $guid;
}
 
private function creerLienItem($element) {
$lien = sprintf($this->conteneur->getParametre('delFicheObsTpl'), $element['dob_id_observation']);
return $lien;
}
 
private function creerCategorie($element) {
$categorie = 'Commentaires';
$categorie = htmlentities($categorie);
return $categorie;
}
 
private function creerDescription($donnees, $item) {
$idCommentaire = $donnees['id_commentaire'];
$idObs = $donnees['dob_id_observation'];
$nomPropose = ($donnees['nom_sel'] != '') ? htmlspecialchars($donnees['nom_sel']) : '';
$dateCommentaire = htmlspecialchars(strftime('%A %d %B %Y à %H:%M', $this->convertirDateHeureMysqlEnTimestamp($donnees['date'])));
$nomSelActuel = htmlspecialchars($donnees['dob_nom_sel']);
$etreProposition = ($nomPropose != '') ? true : false;
$intitule = ($etreProposition) ? 'Proposition' : 'Commentaire';
$txt = ($donnees['texte'] != '') ? htmlspecialchars($donnees['texte']) : '';
$auteur = htmlspecialchars($this->creerAuteur($donnees)).
($this->fluxAdminDemande() ? ' ('.$donnees['utilisateur_courriel'].')' : '');
$lieuObs = htmlspecialchars((($donnees['dob_zone_geo'] != '') ? $donnees['dob_zone_geo'] : '?'));
$dateObs = htmlspecialchars(str_replace(' 00:00:00', '', $donnees['dob_date_observation']));
$observateur = htmlspecialchars($this->creerObservateur($donnees));
 
$contenuCommentaire = '';
if ($etreProposition) {
$contenuCommentaire =
'<li><span class="champ">'."Nom proposé :</span> <em>$nomPropose</em></li>".
((!empty($txt)) ? '<li><span class="champ">'."Argumentaire :</span> $txt</li>" : '').
'<li><span class="champ">'."Auteur de la proposition :</span> $auteur</li>".
'<li><span class="champ">'."Proposé le :</span> $dateCommentaire</li>";
} else {
$contenuCommentaire =
'<li><span class="champ">'."Commentaire #$idCommentaire :</span> <pre>$txt</pre></li>".
'<li><span class="champ">'."Auteur du commentaire :</span> $auteur</li>".
'<li><span class="champ">'."Commenté le :</span> $dateCommentaire</li>";
}
 
$description = '<style>.champ{color:grey} .gauche{float:left;padding:0 20px 0 0;} ul{list-style-type:none;padding:0;}</style>'.
'<h2>'."$intitule identiPlante #$idCommentaire pour l'observation #$idObs".'</h2>'.
'<div class="gauche">'.
" <h3>Observation #$idObs</h3>".
' <ul>'.
' <li><span class="champ">'."Nom saisi actuel :</span> <em>$nomSelActuel</em></li>".
' <li><span class="champ">'."Lieu :</span> $lieuObs</li>".
' <li><span class="champ">'."Date :</span> $dateObs</li>".
' <li><span class="champ">'."Auteur :</span> $observateur</li>".
' </ul>'.
'</div>'.
'<div class="gauche">'.
" <h3>$intitule #$idCommentaire</h3>".
" <ul>$contenuCommentaire</ul>".
'</div>';
return $description;
}
 
private function creerObservateur($info) {
$observateur = 'Anonyme';
if ($info['observateur_prenom'] != '' && $info['observateur_nom'] != '') {
$observateur = $info['observateur_prenom'].' '.$info['observateur_nom'];
}
return $observateur;
}
 
private function getDerniersCommentaires() {
$requete = 'SELECT DISTINCT dc.*, '.
' dob.id_observation AS dob_id_observation, dob.ce_zone_geo AS dob_ce_zone_geo, '.
' dob.zone_geo AS dob_zone_geo, dob.date_observation AS dob_date_observation, dob.nom_sel AS dob_nom_sel, '.
' duo.prenom AS observateur_prenom, duo.nom AS observateur_nom, duo.courriel AS observateur_courriel '.
'FROM del_commentaire AS dc '.
' INNER JOIN del_observation AS dob '.
' ON dob.id_observation = dc.ce_observation '.
' LEFT JOIN del_utilisateur AS duo '.
' ON dob.ce_utilisateur = duo.id_utilisateur '.
'WHERE proposition_initiale != 1 '.
$this->chargerClauseWhere().' '.
'ORDER BY dc.date DESC '.
'LIMIT '.$this->navigation->getDepart().','.$this->navigation->getLimite().' ';
 
$elements = $this->gestionBdd->getBdd()->recupererTous($requete);
return $elements;
}
 
/**
* Charger la clause WHERE en fonction des paramètres de masque
* */
private function chargerClauseWhere() {
$where = array();
 
$tableauMasque = $this->masque->getMasque();
if (!empty($tableauMasque)) {
foreach ($tableauMasque as $idMasque => $valeurMasque) {
$idMasque = str_replace('masque.', '', $idMasque);
$champ = $this->mappingFiltre[$idMasque];
$valeurMasquePattern = $this->gestionBdd->getBdd()->proteger($valeurMasque.'%');
$valeurMasqueProtegee = $this->gestionBdd->getBdd()->proteger($valeurMasque);
 
switch ($idMasque) {
case 'espece':
$where[] = " dob.$champ LIKE $valeurMasquePattern OR dc.$champ LIKE $valeurMasquePattern ";
break;
case 'auteur':
$where[] = $this->creerFiltreAuteur($valeurMasque);
break;
default:
$where[] = " $champ = $valeurMasqueProtegee ";
}
}
}
 
$whereSql = '';
if (!empty($where)) {
$whereSql = ' AND '.implode('AND', $where);
}
return $whereSql;
}
 
private function creerFiltreAuteur($auteurId) {
$whereAuteur = '';
if (is_numeric($auteurId)) {
$whereAuteur = " dc.ce_utilisateur = $auteurId ";
} else {
$auteurIdMotif = $this->gestionBdd->getBdd()->proteger($auteurId.'%');
 
if (strpos($auteurId, '@') === false) {
$tableauNomPrenom = explode(' ', $auteurId, 2);
if (count($tableauNomPrenom) == 2) {
// on teste potentiellement un nom prenom ou bien un prénom nom
$nomMotif = $this->gestionBdd->getBdd()->proteger($tableauNomPrenom[0].'%');
$prenomMotif = $this->gestionBdd->getBdd()->proteger($tableauNomPrenom[1].'%');
 
$whereAuteur = ' ('.
"(dc.utilisateur_nom LIKE $nomMotif AND dc.utilisateur_prenom LIKE $prenomMotif) ".
'OR '.
"(dc.utilisateur_nom LIKE $nomMotif AND dc.utilisateur_prenom LIKE $prenomMotif) ".
') ';
} else {
$whereAuteur = "(dc.utilisateur_nom LIKE $auteurIdMotif OR dc.utilisateur_prenom LIKE $auteurIdMotif) ";
}
} else {
$whereAuteur = " dob.utilisateur_courriel LIKE $auteurIdMotif ";
}
}
return $whereAuteur;
}
}
?>
/tags/v1.1-helium/services/modules/0.1/syndication/SyndicationTagsParProtocole.php
New file
0,0 → 1,318
<?php
/**
* Service fournissant des informations concernant les tags sur les images de DEL en fonction d'un protocole
* au format RSS1, RSS2 ou ATOM.
* Encodage en entrée : utf8
* Encodage en sortie : utf8
*
* @author Grégoire DUCHE <gregoire@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright 2010
*/
class SyndicationTagsParProtocole {
 
/**
* Paramètres du service
* */
private $ressources = null;
private $parametres = null;
private $format = null;
private $service = null;
private $squelette = null;
private $squelette_dossier = null;
private $masque = array();
private $mappingFiltre = array();
private $conteneur = null;
private $gestionBdd = null;
private $navigation = null;
private $type_rss = null;
 
/**
* Constructeur
* Initialiser les configurations
* */
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_syndication_tagsparprotocole.ini');
$this->mappingFiltre = $this->conteneur->getParametre('mapping_masque');
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->navigation = $conteneur->getNavigation();
}
 
/**
* Consulter
* Méthode par défaut pour récupérer l'ensemble des tags.
* Vérifie la configuration et retourne les derniers tags formatés
* */
public function consulter($params = array()) {
$this->verifierConfiguration();
$this->type_rss = $params[1];
if ($this->fluxAdminDemande()) {
$this->demanderAutorisationAdmin();
}
 
$donnees_brutes = $this->getDerniersVotesImage();
$commentaires_formates = $this->formaterPourRss($donnees_brutes) ;
return $commentaires_formates;
}
 
/**
* Vérifier que le service est bien configuré
* */
public function verifierConfiguration() {
$erreurs = array();
 
if (empty($this->mappingFiltre)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [mapping_masque] ou celui-ci est vide ;';
} else {
$champsMappingFiltre = array('image', 'protocole');
foreach ($champsMappingFiltre as $champ) {
if (!isset($this->mappingFiltre[$champ])) {
$erreurs[] = '- le mapping du champ "'.$champ.'" pour le commentaire est manquant ;';
}
}
}
 
if (!empty($erreurs)) {
$e = 'Erreur lors de la configuration : '."\n";
$e .= implode("\n", $erreurs);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
 
/**
* Verifier si le flux admin est demandé
*/
private function fluxAdminDemande() {
return $this->conteneur->getParametre('admin') != null && $this->conteneur->getParametre('admin') == 1;
}
 
/**
* Si le flux est un flux admin, demander un mot de passe
* */
private function demanderAutorisationAdmin() {
$verification = new ControleAcces($this->conteneur);
$verification->demanderAuthentificationAdmin();
}
 
/**
* Formater les données pour mettre en page le RSS
* */
private function formaterPourRss($elements) {
$donnees = $this->construireDonneesCommunesAuFlux($elements);
foreach ($elements as $element) {
$identifiants[$element['id_tag']] = $element['id_tag'];
}
foreach ($elements as $element) {
$donnees['items'][] = $this->construireDonneesCommunesAuxItems($element);
}
return $donnees;
}
 
/**
* Générer les métadonnées du flux (titre, dates, editeur etc.)
* */
private function construireDonneesCommunesAuFlux($infos) {
$donnees = array();
$donnees['guid'] = htmlspecialchars($this->creerUrlService());
$donnees['titre'] = 'pictoFlora : tags';
$donnees['description'] = 'Ce flux regroupe les derniers tags des images de pictoFlora';
$donnees['lien_service'] = htmlspecialchars($this->creerUrlService());
$donnees['lien_del'] = $this->conteneur->getParametre('pictoAppliLien');
$donnees['editeur'] = $this->conteneur->getParametre('editeur');
$derniere_info_en_date = reset($infos);
$date_modification_timestamp = strtotime($derniere_info_en_date['date']);
$donnees['date_maj_RSS'] = date(DATE_RSS, $date_modification_timestamp);
$donnees['date_maj_ATOM'] = date(DATE_ATOM, $date_modification_timestamp);
$donnees['date_maj_W3C'] = date(DATE_W3C, $date_modification_timestamp);
$donnees['annee_courante'] = date('Y');
$donnees['generateur'] = 'DEL - SyndicationCommentaire';
$donnees['generateur_version'] = (preg_match('/([0-9]+)/', '$Revision$', $match)) ? $match[1] : '0';
return $donnees;
}
 
/**
* Générer le lien du flux RSS
* */
private function creerUrlService() {
$url_service = 'http://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
return $url_service;
}
 
/**
* Générer les données communes & spécifiques à chaque item
* */
private function construireDonneesCommunesAuxItems($info) {
$item = array();
$date_modification_timestamp = strtotime($info['date']);
$item['date_maj_simple'] = strftime('%A %d %B %Y à %H:%M', $date_modification_timestamp);
$item['date_maj_RSS'] = date(DATE_RSS, $date_modification_timestamp);
$item['date_maj_ATOM'] = date(DATE_ATOM, $date_modification_timestamp);
$item['date_maj_W3C'] = date(DATE_W3C, $date_modification_timestamp);
$item['titre'] = $this->creerTitre($info);
$item['guid'] = $this->creerGuidItem($info);
$item['lien'] = $this->creerLienItem($info);
$item['categorie'] = $this->creerCategorie($item);
$item['description'] = $this->creerDescription($info, $item);
$item['description_encodee'] = htmlspecialchars($this->creerDescription($info, $item));
$item['modifier_par'] = $this->formaterNomTagueur($info);
return $item;
}
 
private function creerCategorie($element) {
$categorie = 'Tag protocole';
$categorie = htmlentities($categorie);
return $categorie;
}
 
private function creerGuidItem($element) {
$guid = sprintf($this->conteneur->getParametre('tagParProtocole'), $element['id_tag']);
return $guid;
}
 
private function creerLienItem($element) {
// TODO : ajouter un lien vers la plateforme validation de picto lorsqu'elle sera dispo
$lien = $this->conteneur->getParametre('pictofloraFicheObsTpl');
return $lien;
}
 
private function creerTitre($element) {
$tag = $element['tag'];
$nomSel = htmlspecialchars($element['nom_sel']);
$tagueur = htmlspecialchars($this->formaterNomTagueur($element));
$auteurImg = $this->formaterNomAuteurImg($element);
$titre = "Tag «{$tag}» par $tagueur pour $nomSel de $auteurImg";
return $titre;
}
 
private function creerDescription($donnees, $item) {
$idTag = htmlspecialchars($donnees['id_tag']);
$idObs = htmlspecialchars($donnees['id_observation']);
$idImg = htmlspecialchars($donnees['id_image']);
$urlImg = $this->getUrlImage($donnees['id_image']);
$miniatureUrl = $this->getUrlImage($donnees['id_image'], 'CRS');
$nomSelActuel = htmlspecialchars($donnees['nom_sel']);
$dateObs = htmlspecialchars(str_replace(' 00:00:00', '', $donnees['date_observation']));
$lieuObs = htmlspecialchars($donnees['zone_geo']);
$tag = htmlspecialchars($donnees['tag']);
$dateTag = htmlspecialchars(strftime('%A %d %B %Y à %H:%M', strtotime($donnees['date'])));
$auteurImg = htmlspecialchars($this->creerAuteurImg($donnees));
$tagueur = htmlspecialchars($this->creerTagueur($donnees));
 
$description = '<style>.champ{color:grey} .gauche{float:left;padding:0 20px 0 0;} ul{list-style-type:none;padding:0;}</style>'.
'<h2>'."Tag pictoFlora #$idTag pour l'image #$idImg de l'observation #$idObs".'</h2>'.
'<div class="gauche">'.
' <a href="'.$urlImg.'">'.
' <img src="'.$miniatureUrl.'" alt="Img #'.$idImg.'"/>'.
' </a>'.
'</div>'.
'<div class="gauche">'.
" <h3>Image #$idImg de l'observation #$idObs</h3>".
' <ul>'.
' <li><span class="champ">'."Auteur de l'image :</span> $auteurImg</li>".
' <li><span class="champ">'."Nom saisi actuel :</span> <em>$nomSelActuel</em></li>".
' <li><span class="champ">'."Lieu :</span> $lieuObs</li>".
' <li><span class="champ">'."Date :</span> $dateObs</li>".
' </ul>'.
'</div>'.
'<div class="gauche">'.
" <h3>Tag #$idTag</h3>".
' <ul>'.
' <li><span class="champ">'."Tag :</span> <strong>$tag</strong></li>".
' <li><span class="champ">'."Auteur :</span> $tagueur</li>".
' <li><span class="champ">'."Taguée le :</span> $dateTag</li>".
' </ul>'.
'</div>';
return $description;
}
 
private function getUrlImage($id, $format = 'L') {
$url_tpl = $this->conteneur->getParametre('celImgUrlTpl');
$id = sprintf('%09s', $id).$format;
$url = sprintf($url_tpl, $id);
return $url;
}
 
private function creerAuteurImg($info) {
$auteur = $this->formaterNomAuteurImg($info).
($this->fluxAdminDemande() ? ' ('.$info['auteur_courriel'].')' : '');
return $auteur;
}
 
private function formaterNomAuteurImg($info) {
$auteur = 'Anonyme';
if ($info['auteur_prenom'] != '' && $info['auteur_nom'] != '') {
$auteur = $info['auteur_prenom'].' '.$info['auteur_nom'];
}
return $auteur;
}
 
private function creerTagueur($info) {
$tagueur = $this->formaterNomTagueur($info).
($this->fluxAdminDemande() ? ' ('.$info['tagueur_courriel'].')' : '');
return $tagueur;
}
 
private function formaterNomTagueur($info) {
$tagueur = 'Anonyme';
if ($info['tagueur_prenom'] != '' && $info['tagueur_nom'] != '') {
$tagueur = $info['tagueur_prenom'].' '.$info['tagueur_nom'];
}
return $tagueur;
}
 
/**
* Retrouver les derniers votes image
* */
private function getDerniersVotesImage() {
$requete = 'SELECT DISTINCT id_tag, tag, date, '.
' do.id_observation, do.nom_sel, do.zone_geo, do.date_observation, doi.id_image, '.
' duo.prenom AS auteur_prenom, duo.nom AS auteur_nom, duo.courriel AS auteur_courriel, '.
' du.prenom AS tagueur_prenom, du.nom AS tagueur_nom, du.courriel AS tagueur_courriel '.
'FROM del_image_tag AS dit '.
' INNER JOIN del_obs_image AS doi '.
' ON ce_image = id_image '.
' INNER JOIN del_observation AS do '.
' ON doi.id_observation = do.id_observation '.
' LEFT JOIN del_utilisateur AS duo '.
' ON do.ce_utilisateur = duo.id_utilisateur '.
' LEFT JOIN del_utilisateur AS du '.
' ON if((CHAR_LENGTH(dit.ce_utilisateur) <> 32),CAST(dit.ce_utilisateur AS unsigned),0) '.
' = du.id_utilisateur '.
'WHERE actif = 1 '.
$this->chargerClauseWhere().' '.
'ORDER BY date DESC '.
'LIMIT '.$this->navigation->getDepart().','.$this->navigation->getLimite();
$elements = $this->gestionBdd->getBdd()->recupererTous($requete);
return $elements;
}
 
/**
* Charger la clause WHERE en fonction des paramètres de masque
* */
private function chargerClauseWhere() {
$where = array();
$tableauMasque = $this->masque->getMasque();
if (!empty($tableauMasque)) {
foreach ($tableauMasque as $idMasque => $valeurMasque) {
$idMasque = str_replace('masque.', '', $idMasque);
$champMasque = $this->mappingFiltre[$idMasque];
$masqueMotif = $this->gestionBdd->getBdd()->proteger($valeurMasque);
 
switch ($idMasque) {
case 'image':
//TODO : ajouter le protocole ? case 'protocole':
default:
$where[] = " $champMasque = $masqueMotif ";
}
}
}
 
$conditionsTxt = (!empty($where)) ? ' AND '.implode('AND', $where) : '';
return $conditionsTxt;
}
}
?>
/tags/v1.1-helium/services/modules/0.1/syndication/SyndicationVotesParProtocole.php
New file
0,0 → 1,341
<?php
/**
* Service fournissant des informations concernant les votes sur les images de DEL en fonction d'un protocole
* au format RSS1, RSS2 ou ATOM.
* Encodage en entrée : utf8
* Encodage en sortie : utf8
*
* @author Grégoire DUCHE <gregoire@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright 2010
*/
class SyndicationVotesParProtocole {
/**
* Paramètres du service
* */
private $ressources = null;
private $parametres = null;
private $format = null;
private $service = null;
private $squelette = null;
private $squelette_dossier = null;
private $masque = array();
private $mappingFiltre = array();
private $conteneur = null;
private $gestionBdd = null;
private $navigation = null;
private $type_rss = null;
 
/**
* Constructeur
* Initialiser les configurations
* */
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_syndication_votesparprotocole.ini');
$this->mappingFiltre = $this->conteneur->getParametre('mapping_masque');
$this->masque = $conteneur->getMasque();
$this->gestionBdd = $conteneur->getGestionBdd();
$this->navigation = $conteneur->getNavigation();
}
 
/**
* Consulter
* Méthode par défaut pour récupérer l'ensemble des votes.
* Vérifie la configuration et retourne les derniers votes formatés
* */
public function consulter($params = array()) {
$this->verifierConfiguration();
$this->type_rss = $params[1];
if ($this->fluxAdminDemande()) {
$this->demanderAutorisationAdmin();
}
 
$donnees_brutes = $this->getDerniersVotesImage();
$commentaires_formates = $this->formaterPourRss($donnees_brutes) ;
return $commentaires_formates;
}
 
/**
* Vérifier que le service est bien configuré
* */
public function verifierConfiguration() {
$erreurs = array();
 
if (empty($this->mappingFiltre)) {
$erreurs[] = '- le fichier de configuration ne contient pas le tableau [mapping_masque] ou celui-ci est vide ;';
} else {
$champsMappingFiltre = array('image', 'protocole');
foreach ($champsMappingFiltre as $champ) {
if (!isset($this->mappingFiltre[$champ])) {
$erreurs[] = '- le mapping du champ "'.$champ.'" pour le commentaire est manquant ;';
}
}
}
 
if (!empty($erreurs)) {
$e = 'Erreur lors de la configuration : '."\n";
$e .= implode("\n", $erreurs);
throw new Exception($e, RestServeur::HTTP_CODE_ERREUR);
}
}
 
/**
* Verifier si le flux admin est demandé
*/
private function fluxAdminDemande() {
return $this->conteneur->getParametre('admin') != null && $this->conteneur->getParametre('admin') == 1;
}
 
/**
* Si le flux est un flux admin, demander un mot de passe
* */
private function demanderAutorisationAdmin() {
$verification = new ControleAcces($this->conteneur);
$verification->demanderAuthentificationAdmin();
}
 
/**
* Formater les données pour mettre en page le RSS
* */
private function formaterPourRss($elements) {
$donnees = $this->construireDonneesCommunesAuFlux($elements);
foreach ($elements as $element) {
$identifiants[$element['id_vote']] = $element['id_vote'];
}
foreach ($elements as $element) {
$donnees['items'][] = $this->construireDonneesCommunesAuxItems($element);
}
return $donnees;
}
 
/**
* Générer les métadonnées du flux (titre, dates, editeur etc.)
* */
private function construireDonneesCommunesAuFlux($infos) {
$donnees = array();
$donnees['guid'] = htmlspecialchars($this->creerUrlService());
$donnees['titre'] = 'pictoFlora : votes';
$donnees['description'] = 'Ce flux regroupe les derniers votes sur les images de pictoFlora';
$donnees['lien_service'] = htmlspecialchars($this->creerUrlService());
$donnees['lien_del'] = $this->conteneur->getParametre('pictoAppliLien');
$donnees['editeur'] = $this->conteneur->getParametre('editeur');
$derniere_info_en_date = reset($infos);
$date_modification_timestamp = strtotime($derniere_info_en_date['date_vote']);
$donnees['date_maj_RSS'] = date(DATE_RSS, $date_modification_timestamp);
$donnees['date_maj_ATOM'] = date(DATE_ATOM, $date_modification_timestamp);
$donnees['date_maj_W3C'] = date(DATE_W3C, $date_modification_timestamp);
$donnees['annee_courante'] = date('Y');
$donnees['generateur'] = 'DEL - SyndicationCommentaire';
$donnees['generateur_version'] = (preg_match('/([0-9]+)/', '$Revision$', $match)) ? $match[1] : '0';
return $donnees;
}
 
/**
* Générer le lien du flux RSS
* */
private function creerUrlService() {
$url_service = 'http://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
return $url_service;
}
 
/**
* Générer les données communes & spécifiques à chaque item
* */
private function construireDonneesCommunesAuxItems($info) {
$item = array();
$date_modification_timestamp = strtotime($info['date_vote']);
$item['date_maj_simple'] = strftime('%A %d %B %Y à %H:%M', $date_modification_timestamp);
$item['date_maj_RSS'] = date(DATE_RSS, $date_modification_timestamp);
$item['date_maj_ATOM'] = date(DATE_ATOM, $date_modification_timestamp);
$item['date_maj_W3C'] = date(DATE_W3C, $date_modification_timestamp);
$item['titre'] = $this->creerTitre($info);
$item['guid'] = $this->creerGuidItem($info);
$item['lien'] = $this->creerLienItem($info);
$item['categorie'] = $this->creerCategorie($item);
$item['description'] = $this->creerDescription($info, $item);
$item['description_encodee'] = htmlspecialchars($this->creerDescription($info, $item));
$item['modifier_par'] = $this->creerVotant($info);
return $item;
}
 
private function creerCategorie($element) {
$categorie = 'Vote protocole';
$categorie = htmlentities($categorie);
return $categorie;
}
 
private function creerGuidItem($element) {
$guid = sprintf($this->conteneur->getParametre('voteParProtocole'), $element['id_vote']);
return $guid;
}
 
private function creerLienItem($element) {
$lien = sprintf($this->conteneur->getParametre('pictofloraFicheObsTpl'), $element['id_observation']);
return $lien;
}
 
private function creerTitre($element) {
$noteVote = $element['valeur'];
$nomSci = htmlspecialchars($element['nom_sel']);
$votant = htmlspecialchars($this->creerVotant($element));
$observateur = htmlspecialchars($this->creerObservateur($element));
 
$titre = "Vote $noteVote par $votant pour $nomSci de $observateur";
return $titre;
}
 
private function creerDescription($donnees, $item) {
$idVote = htmlspecialchars($donnees['id_vote']);
$idObs = htmlspecialchars($donnees['id_observation']);
$idImg = htmlspecialchars($donnees['ce_image']);
$urlImg = $this->getUrlImage($donnees['ce_image']);
$miniatureUrl = $this->getUrlImage($donnees['ce_image'], 'CRS');
$nomSelActuel = htmlspecialchars($donnees['nom_sel']);
$dateObs = htmlspecialchars(str_replace(' 00:00:00', '', $donnees['date_observation']));
$lieuObs = htmlspecialchars($donnees['zone_geo']);
$protocole = htmlspecialchars($donnees['intitule']);
$votant = htmlspecialchars($this->creerVotant($donnees));
$dateVote = htmlspecialchars(strftime('%A %d %B %Y à %H:%M', strtotime($donnees['date_vote'])));
$observateur = htmlspecialchars($this->creerObservateur($donnees));
 
$description = '<style>.champ{color:grey} .gauche{float:left;padding:0 20px 0 0;} ul{list-style-type:none;padding:0;}</style>'.
'<h2>'."Vote pictoFlora #$idVote pour l'image #$idImg de l'observation #$idObs".'</h2>'.
'<div class="gauche">'.
' <a href="'.$urlImg.'">'.
' <img src="'.$miniatureUrl.'" alt="Img #'.$idImg.'"/>'.
' </a>'.
'</div>'.
'<div class="gauche">'.
" <h3>Image #$idImg de l'observation #$idObs</h3>".
' <ul>'.
' <li><span class="champ">'."Auteur de l'image :</span> $observateur</li>".
' <li><span class="champ">'."Nom saisi actuel :</span> <em>$nomSelActuel</em></li>".
' <li><span class="champ">'."Lieu :</span> $lieuObs</li>".
' <li><span class="champ">'."Date :</span> $dateObs</li>".
' </ul>'.
'</div>'.
'<div class="gauche">'.
" <h3>Vote #$idVote</h3>".
' <ul>'.
' <li><span class="champ">'."Protocole :</span> <strong>$protocole</strong></li>".
' <li><span class="champ">'."Valeur :</span> <strong>{$donnees['valeur']}</strong>/5</li>".
' <li><span class="champ">'."Votant :</span> $votant</li>".
' <li><span class="champ">'."À voté le :</span> $dateVote</li>".
' </ul>'.
'</div>';
return $description;
}
 
private function getUrlImage($id, $format = 'L') {
$url_tpl = $this->conteneur->getParametre('celImgUrlTpl');
$id = sprintf('%09s', $id).$format;
$url = sprintf($url_tpl, $id);
return $url;
}
 
private function creerVotant($info) {
$votant = 'Anonyme';
if (isset($info['votant_prenom']) && isset($info['votant_nom'])) {
$votant = $info['votant_prenom'].' '.$info['votant_nom'];
}
return $votant;
}
 
private function creerObservateur($info) {
$observateur = 'Anonyme';
if ($info['observateur_prenom'] != '' && $info['observateur_nom'] != '') {
$observateur = $info['observateur_prenom'].' '.$info['observateur_nom'];
}
return $observateur;
}
 
/**
* Retrouver les derniers votes image
* */
private function getDerniersVotesImage() {
$requete = 'SELECT DISTINCT id_vote, ce_image, valeur, divo.date AS date_vote, '.
' duo.prenom AS observateur_prenom, duo.nom AS observateur_nom, '.
' duv.prenom AS votant_prenom, duv.nom AS votant_nom, '.
' do.id_observation, do.nom_sel, do.zone_geo, do.date_observation, dip.intitule '.
'FROM del_image_vote AS divo '.
' INNER JOIN del_obs_image AS doi '.
' ON divo.ce_image = doi.id_image '.
' INNER JOIN del_observation AS do '.
' ON do.id_observation = doi.id_observation '.
' INNER JOIN del_image_protocole AS dip '.
' ON ce_protocole = id_protocole '.
' LEFT JOIN del_utilisateur AS duo '.
' ON do.ce_utilisateur = duo.id_utilisateur '.
' LEFT JOIN del_utilisateur AS duv '.
' ON if((CHAR_LENGTH(divo.ce_utilisateur) <> 32),CAST(divo.ce_utilisateur AS unsigned),0) '.
' = duv.id_utilisateur '.
$this->chargerClauseWhere().' '.
'ORDER BY divo.date DESC '.
'LIMIT '.$this->navigation->getDepart().','.$this->navigation->getLimite();
 
$elements = $this->gestionBdd->getBdd()->recupererTous($requete);
return $elements;
}
 
/**
* Charger la clause WHERE en fonction des paramètres de masque
* */
private function chargerClauseWhere() {
$where = array();
$tableauMasque = $this->masque->getMasque();
if (!empty($tableauMasque)) {
foreach($tableauMasque as $idMasque => $valeurMasque) {
$idMasque = str_replace('masque.', '', $idMasque);
switch ($idMasque) {
case 'image':
$where[] = ' '.$this->mappingFiltre[$idMasque].' = '.$this->gestionBdd->getBdd()->proteger($valeurMasque);
break;
case 'protocole':
$where[] = ' '.$this->mappingFiltre[$idMasque].' = '.$this->gestionBdd->getBdd()->proteger($valeurMasque).' ';
break;
default:
$where[] = ' '.$this->mappingFiltre[$idMasque].' = '.$this->gestionBdd->getBdd()->proteger($valeurMasque);
break;
}
}
}
if (!empty($where)) {
return ' WHERE '.implode('AND', $where);
} else {
return;
}
}
 
private function creerFiltreAuteur($valeurMasque) {
$masque = '';
$auteurId = $valeurMasque;
if (is_numeric($auteurId)) {
$masque = ' dc.ce_utilisateur = '.$auteurId;
} else {
if (strpos($auteurId, '@') === false) {
$tableauNomPrenom = explode(' ',$auteurId, 2);
if(count($tableauNomPrenom) == 2) {
// on teste potentiellement un nom prenom ou bien un prénom nom
$masque = '('.
'(dc.utilisateur_nom LIKE '.$this->gestionBdd->getBdd()->proteger($tableauNomPrenom[0].'%').' AND '.
'dc.utilisateur_prenom LIKE '.$this->gestionBdd->getBdd()->proteger($tableauNomPrenom[1].'%').') OR '.
'(dc.utilisateur_nom LIKE '.$this->gestionBdd->getBdd()->proteger($tableauNomPrenom[1].'%').' AND '.
'dc.utilisateur_prenom LIKE '.$this->gestionBdd->getBdd()->proteger($tableauNomPrenom[0].'%').')'.
')';
} else {
$masque = '(
(dc.utilisateur_nom LIKE '.$this->gestionBdd->getBdd()->proteger($auteurId.'%').' OR '.
'dc.utilisateur_prenom LIKE '.$this->gestionBdd->getBdd()->proteger($auteurId.'%').')'.
')';
}
} else {
$masque = " do.utilisateur_courriel LIKE ".$this->gestionBdd->getBdd()->proteger($valeurMasque.'%')." ";
}
}
return $masque;
}
}
?>
/tags/v1.1-helium/services/modules/0.1/syndication/squelettes/atom.tpl.xml
New file
0,0 → 1,36
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'."\n";?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><?=$titre?></title>
<link href="<?=$lien_service?>" rel="alternate" type="text/html" hreflang="fr" />
<link href="<?=$lien_service?>" rel="self" type="application/atom+xml"/>
<updated><?=$date_maj_ATOM?></updated>
<author>
<name><?=$editeur?></name>
</author>
<id><?=$guid?></id>
<rights>Copyright (c) <?=$annee_courante?>, <?=$editeur?></rights>
<generator uri="<?=$lien_service?>" version="<?=$generateur_version?>"><?=$generateur?></generator>
 
<?php if (isset($items)) : ?>
<?php foreach ($items as $item) : ?>
<entry>
<id><?=$item['guid']?></id>
<title><?=$item['titre']?></title>
<? if (isset($item['lien'])) : ?>
<link href="<?=$item['lien']?>"/>
<? endif; ?>
<updated><?=$item['date_maj_ATOM']?></updated>
<published><?=$item['date_maj_ATOM']?></published>
<author><name><?=$item['modifier_par']?></name></author>
<content type="xhtml" xml:lang="fr">
<div xmlns="http://www.w3.org/1999/xhtml">
<?=$item['description'];?>
</div>
</content>
</entry>
<?php endforeach; ?>
<?php endif; ?>
 
</feed>
/tags/v1.1-helium/services/modules/0.1/syndication/squelettes/opml.tpl.xml
New file
0,0 → 1,18
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'."\n";?>
<opml version="1.0">
<head>
<text/>
</head>
<body>
<outline text="DEL">
<?php foreach ($liste_flux as $flux) : ?>
<outline title="<?=$flux['titre']?>"
description="<?=$flux['description']?>"
htmlUrl="<?=$flux['url_html']?>"
xmlUrl="<?=$flux['url_xml']?>"
type="<?=$flux['type']?>"
text="<?=$flux['texte']?>"/>
<?php endforeach; ?>
</outline>
</body>
</opml>
/tags/v1.1-helium/services/modules/0.1/syndication/squelettes/rss1.tpl.xml
New file
0,0 → 1,44
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'."\n";?>
 
<!DOCTYPE rdf:RDF [
<!ENTITY % HTMLlat1 PUBLIC
"-//W3C//ENTITIES Latin 1 for XHTML//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">
%HTMLlat1;
]>
 
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns="http://purl.org/rss/1.0/">
 
<channel rdf:about="<?=$guid?>">
<title><?=$titre?></title>
<link><?=$lien_service?></link>
<description><?=$description?></description>
<dc:publisher><?=$editeur?></dc:publisher>
<dc:date><?=$date_maj_W3C?></dc:date>
<?php if (isset($items)) : ?>
<items>
<rdf:Seq>
<?php foreach ($items as $item) : ?>
<rdf:li resource="<?=$item['guid']?>" />
<?php endforeach; ?>
</rdf:Seq>
</items>
<?php endif; ?>
</channel>
 
<?php if (isset($items)) : ?>
<?php foreach ($items as $item) : ?>
<item rdf:about="<?=$item['guid']?>">
<title><?=$item['titre']?></title>
<link><?=(isset($item['lien'])) ? $item['lien'] : 'http://www.tela-botanica.org/'?></link>
<description><?=$item['description_encodee']?></description>
<dc:creator><?=$item['modifier_par']?></dc:creator>
<dc:date><?=$item['date_maj_W3C']?></dc:date>
</item>
<?php endforeach; ?>
<?php endif; ?>
</rdf:RDF>
/tags/v1.1-helium/services/modules/0.1/syndication/squelettes/rss2.tpl.xml
New file
0,0 → 1,26
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'."\n";?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title><?=$titre?></title>
<link><?=$lien_service?></link>
<atom:link href="<?=$lien_service?>" rel="self" type="application/rss+xml" />
<description><?=$description?></description>
<?php if (isset($items)) : ?>
<?php foreach ($items as $item) : ?>
<item>
<guid><?=$item['guid']?></guid>
<title><?=$item['titre']?></title>
<? if (isset($item['lien'])) : ?>
<link><?=$item['lien']?></link>
<? endif; ?>
<description><?=$item['description_encodee']?></description>
<category><?= $item['categorie'] ?></category>
<author><?=$item['modifier_par']?></author>
<pubDate><?=$item['date_maj_RSS']?></pubDate>
</item>
<?php endforeach; ?>
<?php endif; ?>
</channel>
</rss>
/tags/v1.1-helium/services/configurations/config_departements.ini
New file
0,0 → 1,101
Ain = 01
Aisne = 02
Allier = 03
Alpes-de-Haute-Provence = 04
Hautes-Alpes = 05
Alpes-Maritimes = 06
Ardèche = 07
Ardennes = 08
Ariège = 09
Aube = 10
Aude = 11
Aveyron = 12
Bouches-du-Rhône = 13
Calvados = 14
Cantal = 15
Charente = 16
Charente-Maritime = 17
Cher = 18
Corrèze = 19
Corse-du-Sud = 2A
Haute-Corse = 2B
Côte-d'Or = 21
Côtes-d'Armor = 22
Creuse = 23
Dordogne = 24
Doubs = 25
Drôme = 26
Eure = 27
Eure-et-Loir = 28
Finistère = 29
Gard = 30
Haute-Garonne = 31
Gers = 32
Gironde = 33
Hérault = 34
Ille-et-Vilaine = 35
Indre = 36
Indre-et-Loire = 37
Isère = 38
Jura = 39
Landes = 40
Loir-et-Cher = 41
Loire = 42
Haute-Loire = 43
Loire-Atlantique = 44
Loiret = 45
Lot = 46
Lot-et-Garonne = 47
Lozère = 48
Maine-et-Loire = 49
Manche = 50
Marne = 51
Haute-Marne = 52
Mayenne = 53
Meurthe-et-Moselle = 54
Meuse = 55
Morbihan = 56
Moselle = 57
Nièvre = 58
Nord = 59
Oise = 60
Orne = 61
Pas-de-Calais = 62
Puy-de-Dôme = 63
Pyrénées-Atlantiques = 64
Hautes-Pyrénées = 65
Pyrénées-Orientales = 66
Bas-Rhin = 67
Haut-Rhin = 68
Rhône = 69
Haute-Saône = 70
Saône-et-Loire = 71
Sarthe = 72
Savoie = 73
Haute-Savoie = 74
Paris = 75
Seine-Maritime = 76
Seine-et-Marne = 77
Yvelines = 78
Deux-Sèvres = 79
Somme = 80
Tarn = 81
Tarn-et-Garonne = 82
Var = 83
Vaucluse = 84
Vendée = 85
Vienne = 86
Haute-Vienne = 87
Vosges = 88
Yonne = 89
Territoire de Belfort = 90
Essonne = 91
Hauts-de-Seine = 92
Seine-Saint-Denis = 93
Val-de-Marne = 94
Val-d'Oise = 95
Guadeloupe = 971
Martinique = 972
Guyane = 973
La Réunion = 974
Mayotte = 976
/tags/v1.1-helium/services/configurations/config_syndication_tagsparprotocole.ini
New file
0,0 → 1,8
masques_possibles = "image,protocole";
url_service="{ref:url_base}eflore-test/del/services/0.1/syndication/tagsParProtocole"
pictoAppliLien = http://www.tela-botanica.org/appli:test:pictoflora
; +------------------------------------------------------------------------------------------------------+
[mapping_masque]
image = "id_image";
protocole = "ce_protocole"
/tags/v1.1-helium/services/configurations/config_utilisateurs.ini
New file
0,0 → 1,44
; Encodage : UTF-8
 
; Nom du projet
nom_projet = "del"
masques_possibles = "famille,genre,ns,nn,auteur,date,commune,departement,tag,espece"
 
['utilisateurs']
; URL de base des services de ce projet
url_service = "{ref:url_base}del/services/0.1/utilisateurs/"
url_images = "http://api.tela-botanica.org/img:%sXL.jpg"
 
; +------------------------------------------------------------------------------------------------------+
; Config spécifique au projet
; Noms des services disponibles pour ce projet
servicesDispo = "identification-anonyme,connecter,deconnecter"
 
 
[mapping_observation]
id_observation = "id_observation"
date_observation = "date_observation"
date_transmission = "date_transmission"
famille = "determination.famille"
nom_sel = "determination.ns"
nom_sel_nn = "determination.nn"
nt = "determination.nt"
courriel = "observateur"
ce_zone_geo = "id_zone_geo"
zone_geo = "zone_geo"
lieudit = "lieudit"
station = "station"
milieu = "milieu"
nom = "auteur.nom"
prenom = "auteur.prenom"
ce_utilisateur = "auteur.id"
 
[mapping_masque]
famille = "famille"
ns = "nom_sel"
nn = "nom_sel_nn"
date = "date_observation"
tag = "mots_cles_texte"
commune = "zone_geo"
id_zone_geo = "ce_zone_geo"
espece = "nom_sel"
/tags/v1.1-helium/services/configurations/config_syndication_votesparprotocole.ini
New file
0,0 → 1,8
masques_possibles = "image,protocole";
url_service="{ref:url_base}eflore-test/del/services/0.1/syndication/votesParProtocole"
pictoAppliLien = http://www.tela-botanica.org/appli:test:pictoflora
; +------------------------------------------------------------------------------------------------------+
[mapping_masque]
image = "ce_image";
protocole = "ce_protocole"
/tags/v1.1-helium/services/configurations/config_votes.ini
New file
0,0 → 1,14
; Encodage : UTF-8
 
; Nom du projet
nom_projet = "del"
masques_possibles = "id_image"
 
['images']
; URL de base des services de ce projet
url_service = "{ref:url_service_base}votes/Images"
 
; +------------------------------------------------------------------------------------------------------+
; Config spécifique au projet
; Noms des services disponibles pour ce projet
servicesDispo = "Images, Observations"
/tags/v1.1-helium/services/configurations/config_mapping_commentaires.ini
New file
0,0 → 1,17
; +------------------------------------------------------------------------------------------------------+
[mapping_commentaire]
id_commentaire = "id_commentaire"
ce_observation = "observation"
ce_proposition = "proposition"
ce_commentaire_parent = "id_parent"
ce_utilisateur = "auteur.id"
texte = "texte"
utilisateur_nom = "auteur.nom"
utilisateur_prenom = "auteur.prenom"
utilisateur_courriel = "auteur.courriel"
date = "date"
nom_sel = "nom_sel"
nom_sel_nn = "nom_sel_nn"
nom_ret_nn = nom_ret_nn
nom_referentiel = nom_referentiel
proposition_initiale = proposition_initiale;
/tags/v1.1-helium/services/configurations/config_determination.ini
New file
0,0 → 1,40
; Encodage : UTF-8
 
; Nom du projet
nom_projet = "del"
 
[images]
; URL de base des services de ce projet
url_service = "{ref:url_base}del/services/0.1/projets/del/images"
url_images = "http://api.tela-botanica.org/img:%sXL.jpg"
 
 
; +------------------------------------------------------------------------------------------------------+
; Config spécifique au projet
; Noms des services disponibles pour ce projet
servicesDispo = "Determinations"
 
[mapping_observation]
id_observation = "id_observation"
date_observation = "date_observation"
date_transmission = "date_transmission"
famille = "determination.famille"
nom_sel = "determination.ns"
nom_sel_nn = "determination.nn"
nt = "determination.nt"
ce_zone_geo = "id_zone_geo"
zone_geo = "zone_geo"
lieudit = "lieudit"
station = "station"
milieu = "milieu"
ce_utilisateur = "auteur.id"
nom = "auteur.nom"
prenom = "auteur.prenom"
 
[mapping_masque]
famille = "famille"
ns = "nom_sel"
nn = "nom_sel_nn"
date = "date_observation"
tag = "mots_cles_texte"
commune = "zone_geo"
/tags/v1.1-helium/services/configurations/config_mapping_mots_cles.ini
New file
0,0 → 1,7
; +------------------------------------------------------------------------------------------------------+
[mapping_mots_cles]
id_tag = "id_mot_cle"
ce_image = "image"
ce_utilisateur = "auteur.id"
date = "date"
tag = "mot_cle"
/tags/v1.1-helium/services/configurations/config_images.ini
New file
0,0 → 1,51
; Encodage : UTF-8
 
; Nom du projet
nom_projet = "del"
masques_possibles = "masque,famille,genre,ns,nn,nt,auteur,date,commune,departement,tag,espece,referentiel"
formats_possibles = "O,CRX2S,CRS,CXS,CS,XS,S,M,L,XL,X2L,X3L"
tris_possibles = "date_observation,votes,tags"
mots_cles_cel_affiches = "fleur,fleurs,feuille,feuilles,ecorce,fruit,fruits,port,defiphoto,plantnet"
 
[images]
; URL de base des services de ce projet
url_service = "{ref:url_service_base}images"
url_images = "http://api.tela-botanica.org/img:%09d%s.jpg";
 
; +------------------------------------------------------------------------------------------------------+
; Config spécifique au projet
; Noms des services disponibles pour ce projet
servicesDispo = "votes"
[mapping_service]
votes = "votes-image"
 
[mapping_observation]
id_observation = "id_observation"
date_observation = "date_observation"
date_transmission = "date_transmission"
famille = "determination.famille"
nom_sel = "determination.ns"
nom_sel_nn = "determination.nn"
nom_referentiel = "determination.referentiel"
nt = "determination.nt"
ce_zone_geo = "id_zone_geo"
zone_geo = "zone_geo"
lieudit = "lieudit"
station = "station"
milieu = "milieu"
ce_utilisateur = "auteur.id"
nom = "auteur.nom"
prenom = "auteur.prenom"
mots_cles_texte = "mots_cles_texte"
commentaire = "commentaire"
 
[mapping_masque]
famille = "famille"
ns = "nom_sel"
nn = "nom_sel_nn"
date = "date_observation"
tag = "mots_cles_texte"
tag_cel = "mots_cles_texte"
tag_pictoflora = "mots_cles_texte"
commune = "zone_geo"
referentiel = "nom_referentiel"
/tags/v1.1-helium/services/configurations/config_nomstaxons.ini
New file
0,0 → 1,15
; Encodage : UTF-8
 
; Nom du projet
nom_projet = "del"
masques_possibles = "nom,referentiel"
 
[commentaires]
; URL de base des services de ce projet
url_service="{ref:url_base}del/services/0.1/nomstaxons"
 
 
; +------------------------------------------------------------------------------------------------------+
; Config spécifique au projet
; Noms des services disponibles pour ce projet
servicesDispo = "liste-taxons"
/tags/v1.1-helium/services/configurations/config_departements_bruts.ini
New file
0,0 → 1,101
ain = 01
aisne = 02
allier = 03
alpes-de-haute-provence = 04
hautes-alpes = 05
alpes-maritimes = 06
ardeche = 07
ardennes = 08
ariege = 09
aube = 10
aude = 11
aveyron = 12
bouches-du-rhone = 13
calvados = 14
cantal = 15
charente = 16
charente-maritime = 17
cher = 18
correze = 19
corse-du-sud = 2a
haute-corse = 2b
cote-d'or = 21
cotes-d'armor = 22
creuse = 23
dordogne = 24
doubs = 25
drome = 26
eure = 27
eure-et-loir = 28
finistere = 29
gard = 30
haute-garonne = 31
gers = 32
gironde = 33
herault = 34
ille-et-vilaine = 35
indre = 36
indre-et-loire = 37
isere = 38
jura = 39
landes = 40
loir-et-cher = 41
loire = 42
haute-loire = 43
loire-atlantique = 44
loiret = 45
lot = 46
lot-et-garonne = 47
lozere = 48
maine-et-loire = 49
manche = 50
marne = 51
haute-marne = 52
mayenne = 53
meurthe-et-moselle = 54
meuse = 55
morbihan = 56
moselle = 57
nievre = 58
nord = 59
oise = 60
orne = 61
pas-de-calais = 62
puy-de-dome = 63
pyrenees-atlantiques = 64
hautes-pyrenees = 65
pyrenees-orientales = 66
bas-rhin = 67
haut-rhin = 68
rhone = 69
haute-saone = 70
saone-et-loire = 71
sarthe = 72
savoie = 73
haute-savoie = 74
paris = 75
seine-maritime = 76
seine-et-marne = 77
yvelines = 78
deux-sevres = 79
somme = 80
tarn = 81
tarn-et-garonne = 82
var = 83
vaucluse = 84
vendee = 85
vienne = 86
haute-vienne = 87
vosges = 88
yonne = 89
territoire-de-belfort = 90
essonne = 91
hauts-de-seine = 92
seine-saint-denis = 93
val-de-marne = 94
val-d-oise = 95
guadeloupe = 971
martinique = 972
guyane = 973
la-reunion = 974
mayotte = 976
/tags/v1.1-helium/services/configurations/config_mapping_votes.ini
New file
0,0 → 1,17
; +------------------------------------------------------------------------------------------------------+
[mapping_votes]
ce_protocole = "protocole.id"
ce_proposition = "proposition.id"
id_vote = "vote.id"
valeur = "vote"
ce_image = "image.id"
ce_utilisateur = "auteur.id"
nom = "auteur.nom"
prenom = "auteur.prenom"
courriel = "auteur.courriel"
date = "date"
id_protocole = "protocole.id"
intitule = "protocole.intitule"
descriptif = "protocole.descriptif"
tag = "protocole.tag"
mots_cles = "protocole.mots_cles"
/tags/v1.1-helium/services/configurations/config_observations.ini
New file
0,0 → 1,52
; Encodage : UTF-8
 
; Nom du projet
nom_projet = "del"
masques_possibles = "masque,famille,genre,ns,nn,auteur,date,commune,departement,tag,espece,type,referentiel"
tag_adeterminer = aDeterminer
nb_commentaires_discussion = 1
 
[observations]
; URL de base des services de ce projet
; url_service = "{ref:url_base}del/services/0.1/observations/"
url_service = "{ref:url_base}service:del:0.1/observations/"
url_images = "http://api.tela-botanica.org/img:%09dXL.jpg";
 
; +------------------------------------------------------------------------------------------------------+
; Config spécifique au projet
; Noms des services disponibles pour ce projet
servicesDispo = "observation, vote"
 
 
[mapping_observation]
id_observation = "id_observation"
date_observation = "date_observation"
date_transmission = "date_transmission"
famille = "determination.famille"
nom_sel = "determination.ns"
nom_sel_nn = "determination.nn"
nt = "determination.nt"
nom_referentiel = "determination.referentiel"
courriel = "observateur"
ce_zone_geo = "id_zone_geo"
zone_geo = "zone_geo"
lieudit = "lieudit"
station = "station"
milieu = "milieu"
nom = "auteur.nom"
prenom = "auteur.prenom"
ce_utilisateur = "auteur.id"
mots_cles_texte = "mots_cles_texte"
dob_commentaire = commentaire
 
 
[mapping_masque]
famille = "famille"
ns = "nom_sel"
nn = "nom_sel_nn"
date = "date_observation"
tag = "mots_cles_texte"
commune = "zone_geo"
id_zone_geo = "ce_zone_geo"
espece = "nom_sel"
referentiel = "nom_referentiel"
/tags/v1.1-helium/services/configurations/config_syndication.ini
New file
0,0 → 1,22
; +------------------------------------------------------------------------------------------------------+
servicesDispo = "commentaires,votesParProtocole,tagsParProtocole";
formatsRss = "rss1,rss2,atom";
 
; +------------------------------------------------------------------------------------------------------+
; Editeur du flux
editeur = "Tela Botanica";
 
; Format du Guid de DEL pour le flux de syndication
guidObsTpl = "urn:lsid:tela-botanica.org:del:%s";
voteParProtocole = "urn:lsid:tela-botanica.org:picto:vote%s"
tagParProtocole = "urn:lsid:tela-botanica.org:picto:tag%s"
 
; Lien de base vers l'appli DEL
delAppliLien = "http://www.tela-botanica.org/appli:identiplante";
 
; Lien de base vers la fiche de l'observation dans DEL
delFicheObsTpl = "{ref:delAppliLien}#page_validation~%s";
pictofloraFicheObsTpl = "{ref:delAppliLien}#page_recherche_images";
 
; Squelette d'Url permettant d'afficher une image du CEL (remplace %s par l'id de l'image sans underscore)
celImgUrlTpl = "http://api.tela-botanica.org/img:%s.jpg"
/tags/v1.1-helium/services/configurations/config_determinations.ini
New file
0,0 → 1,13
; Encodage : UTF-8
 
; Nom du projet
nom_projet = "del"
masques_possibles = "protocole,valeur_vote_min";
protocoles_possibles = "1,2,3,4";
mots_cles_cel_affiches = "fleur,fleurs,feuille,feuilles,ecorce,fruit,fruits,port,plantnet,plantscan_new";
 
[images]
; URL de base des services de ce projet
url_service = "{ref:url_base}del/services/0.1/determinations/images-determinations-probables";
url_images = "http://api.tela-botanica.org/img:%09dS.jpg";
url_fiche_eflore = "http://www.tela-botanica.org/nn%s";
/tags/v1.1-helium/services/configurations/config_commentaires.ini
New file
0,0 → 1,22
; Encodage : UTF-8
 
; Nom du projet
nom_projet = "del"
masques_possibles = "proposition,observation"
 
[commentaires]
; URL de base des services de ce projet
url_service="{ref:url_base}del/services/0.1/commentaires"
 
 
; +------------------------------------------------------------------------------------------------------+
; Config spécifique au projet
; Noms des services disponibles pour ce projet
servicesDispo = "votes"
 
[mapping_service]
votes = "votes-image"
[mapping_masque]
observation = "ce_observation"
proposition = "ce_proposition"
/tags/v1.1-helium/services/configurations/config_communes.ini
New file
0,0 → 1,15
; Encodage : UTF-8
 
; Nom du projet
nom_projet = "del"
masques_possibles = "nom"
 
[commentaires]
; URL de base des services de ce projet
url_service="{ref:url_base}del/services/0.1/communes"
 
 
; +------------------------------------------------------------------------------------------------------+
; Config spécifique au projet
; Noms des services disponibles pour ce projet
servicesDispo = "liste-communes"
/tags/v1.1-helium/services/configurations/config.defaut.ini
New file
0,0 → 1,79
; Encodage : UTF-8
 
; +------------------------------------------------------------------------------------------------------+
; URLs
; Le séparateur utilisé par le framework lorsqu'il génère des URL pour séparer les arguments.
; Pour remettre les valeurs par défaut, utitliser : "php:ini_get('arg_separator.output')"
url_arg_separateur_sortie = "&"
 
; +------------------------------------------------------------------------------------------------------+
; Info sur l'application
info.nom = Services d'Identiplante
; Abréviation de l'application
info.abr = del-services
; Version du Framework nécessaire au fonctionnement de cette application
info.framework.version = 0.3
;Encodage de l'application
encodage_appli = "UTF-8"
 
; +------------------------------------------------------------------------------------------------------+
; Débogage
; Indique si oui ou non on veut afficher le débogage.
debogage = true
; Indique sous quelle forme les méssages de débogage doivent s'afficher :
; - "php:Debug::MODE_ECHO" : le message est affiché en utilisant echo
; - "php:Debug::MODE_NOTICE" : le message est affiché en utilisant une erreur de type notice
; - "php:Debug::MODE_ENTETE_HTTP" : les messages sont envoyés dans un entête HTTP "X_REST_DEBOGAGE".
; - "Autre valeur" : les messages sont formatés puis retournés par la méthode de débogage utilisée.
debogage_mode = "php:Debug::MODE_ECHO"
; Indique si oui ou non on veut lancer le chronométrage
chronometrage = false
 
 
; +------------------------------------------------------------------------------------------------------+
; Paramètrage de la base de données.
; Abstraction de la base de données.
bdd_abstraction = pdo
; Protocole de la base de données.
bdd_protocole = mysql
; Nom du serveur de bases de données.
bdd_serveur = localhost
; Nom de l'utilisateur de la base de données.
bdd_utilisateur = ""
; Mot de passe de l'utilisateur de la base de données.
bdd_mot_de_passe = ""
; Nom de la base de données principale.
bdd_nom = "del"
; Encodage de la base de données principale au format base de données (ex. pour l'utf-8 ne pas mettre le tiret!).
bdd_encodage = "utf8"
 
; +------------------------------------------------------------------------------------------------------+
; Infos sur les services
;chemin direct aux services
serveur.baseURL = /del/services/
;URL à rediriger
serveur.baseAlternativeURL = /service:del:0.1/
 
; Version des service web du projet
service_version = 0.1
; Standard utilisé pour les codes de langue
langue_source = "ISO-639-1";
; Standard utilisé pour les codes de zones géographiques
zone_geo_source = "ISO-3166-1";
 
; URL de base des services
url_base="http://localhost/"
; URL de base des services
url_service_base='{ref:url_base}service:del:0.1/'
; URL de base du service appelé lors de la validation
; un POST est effectué à cette adresse, ce qui tolère les réécritures d'URL
; mais non les 30x. En cas de Cel distinct d'Eflore, et indépendemment de l'URI,
; pointer vers l'hôte final, eg: http://moncel/jrest/CelValidationObservation/
url_service_validation_base='{ref:url_base}service:cel:CelValidationObservation/';
 
; URL de base du service appelé pour autocompléter les noms de taxons
url_service_completion_base="{ref:url_base}service:eflore:0.1/%s/noms?masque=%s&recherche=etendue&retour.format=min&navigation.limite=50&ns.structure=au";
 
; +------------------------------------------------------------------------------------------------------+
; Administrateurs de del
admins = "accueil@tela-botanica.org,aurelien@tela-botanica.org,delphine@tela-botanica.org,gregoire@tela-botanica.org,jpm@tela-botanica.org";
/tags/v1.1-helium/services/configurations/config_mots_cles.ini
New file
0,0 → 1,17
; Encodage : UTF-8
 
; Nom du projet
nom_projet = "del"
masques_possibles = "image,auteur.id"
 
[motscles]
; URL de base des services de ce projet
url_service="{ref:url_base}del/services/0.1/motscles"
 
 
; +------------------------------------------------------------------------------------------------------+
; Config spécifique au projet
[mapping_masque]
image = "ce_image"
auteur.id = "ce_utilisateur"
/tags/v1.1-helium/services/configurations/config_protocoles.ini
New file
0,0 → 1,7
; Encodage : UTF-8
 
; Nom du projet
nom_projet = "del"
 
; pour le moment le fichier est quasiment vide mais il servira lors de l'ajout
; d'une interface d'admin des protocoles
/tags/v1.1-helium/services/configurations/config_syndication_commentaires.ini
New file
0,0 → 1,7
masques_possibles = "espece,auteur,observation";
url_service="{ref:url_base}eflore-test/del/services/0.1/syndication/commentaires"
 
; +------------------------------------------------------------------------------------------------------+
[mapping_masque]
espece = "nom_sel";
observation = "ce_observation";
/tags/v1.1-helium/services/configurations
New file
Property changes:
Added: svn:ignore
+config.ini
/tags/v1.1-helium/services/framework.defaut.php
New file
0,0 → 1,6
<?php
// Inclusion du Framework
// Renomer ce fichier en "framework.php"
// Indiquer ci-dessous le chemin absolu vers le fichier autoload.inc.php de la bonne version du Framework
require_once '/home/delphine/web/framework-0.3/framework/Framework.php';
?>
/tags/v1.1-helium/services/.htaccess
New file
0,0 → 1,9
<files *.ini>
order deny,allow
deny from all
</files>
 
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*$ index.php
/tags/v1.1-helium/services/README.txt
New file
0,0 → 1,5
Configurer le .htacces de la racine du serveur pour placer la ligne :
 
# Règle de ré-ecriture d'url pour l'accès au format eFlore
RewriteRule ^service:del:([0-9]\.[0-9])/([^/]+)/(v[0-9]+[_.][0-9]+|[+*]|v[0-9]+)/([^/]+)/?(.*)?$ /del/services/$1/projets/$2/$4/$5?version.projet=$3
RewriteRule ^service:del:([0-9]\.[0-9])/([^/]+)/(.+)$ /del/services/$1/projets/$2/$3
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/tags/v1.1-helium/services/bibliotheque/Commun.php
New file
0,0 → 1,419
<?php
/**
* Classe Commun.php est une classe abstraite qui contient les méthodes de base communes à tous les
* sous-services des projets.
*
* Encodage en entrée : utf8
* Encodage en sortie : utf8
* @package eflore-projets
* @author Jennifer DHÉ <jennifer.dhe@tela-botanica.org>
* @author Delphine CAUQUIL <delphine@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version 1.0
* @copyright 1999-2011 Tela Botanica (accueil@tela-botanica.org)
*/
 
abstract class Commun {
 
/** Objet Bdd. */
private $Bdd = null;
/** Objet Rest Client. */
private $RestClient = null;
 
/** Contients les paramètres. Doit remplacer table_param. */
protected $parametres = array();
/** Contients les ressources. Doit remplacer table_ressources. */
protected $ressources = array();
/** Le nom du service courrant. */
protected $serviceNom = null;
 
//Classe commune à tous les services web d'un projet. Contient par exemple les fonctions permettant de
//renvoyer la réponse http...
protected $entete_http; // Entete de la réponse correspondant au code de réponse de la requete http */
protected $corps_http; // Tableau de résultat à retourner au format json ou la description de l'erreur si elle existe */
protected $service; // Nom du service appelé
/** Stocke la version du projet demandée dans la requete
* - "*" : (/#projet/* /meta-donnees) Renvoi les meta-données de toutes les versions du projet
* - "numero de la version" : (/#projet/2.00/meta-donnees) Renvoi les meta-données de la version 2.00 du projet */
protected $version_projet = '+';
protected $table_version; //Stocke les noms des tables de toutes les versions du projet disponibles
/** tableau contenant tous les champs d'une table (est rempli par la fonction Commun::recupererNomChamp($table)) */
protected $champs_table = array();
private static $tri_multi_dimension = array();
private static $tri_type = '';
 
public function consulter($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
$this->chargerNomDuService();
 
$this->traiterParametres();
$this->traiterVersionProjet();
 
$resultats = '';
foreach ($this->table_version as $version) {
$this->table = $version; //on stocke le nom de la table correspondant à la version du projet en cours
$this->recupererNomChamp($this->table); //on récupère les noms des champs disponibles (Ds Commun.php)
$this->traiterRessources(); //dans CommunNomsTaxons.php
$requete = $this->assemblerLaRequete();
$resultat = $this->getBdd()->recupererTous($requete);
$versionResultat = $this->traiterResultat($resultat, $version, $requete);
if (count($this->table_version) > 1) {
$resultats[$version] = $versionResultat;
} else {
$resultats = $versionResultat;
}
}
 
return $resultats;
}
 
private function chargerNomDuService() {
$this->serviceNom = get_class($this);
}
 
public function traiterResultat($resultat, $version, $requete) {
$versionResultat = null;
if ($resultat == '') {
//cas ou la requete comporte des erreurs
$message = 'La requête SQL formée comporte une erreur!';
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
} elseif ($resultat) {
$versionResultat = $this->retournerResultatFormate($resultat, $version);
} else {
$message = 'Les données recherchées sont introuvables.';
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
return $versionResultat;
}
 
//+------------------------------------------------------------------------------------------------------+
// Méthodes concernant les paramètres
/**
* Permet de récupérer une liste des noms des champs de la table passée en paramètre
* @param $table : Nom de la table dont on souhaite connaitre les champs
*/
public function recupererNomChamp($table) {
$requete = 'SHOW FIELDS FROM '.$table;
 
$resultat = $this->getBdd()->recupererTous($requete);
if ($resultat == '') {
$e = 'La requête SQL formée comporte une erreur!';
$this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $e);
} elseif ($resultat) {
foreach ($resultat as $info) {
$this->champs_table[] = $info['Field'];
}
} else {
$m = "La table recherchée n'existe pas";
$this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $m);
}
}
 
/**
* Fonction permettant de creer la table dont le nom est passé en paramètre (champs_api, champs_bdtfx,
* correspondance_champs...). Les données de chaque table sont présentes dans le fichier de configuration config.ini
* @param String $table : Peut contenir plusieurs nom de table dont on souhaite récupérer les données : table,table,table.
* Ex : recupererTableConfig('champs_api,champs_bdtfx')
*/
public function recupererTableConfig($table) {
$tables = explode(',', $table);
foreach ($tables as $tab) {
$tableau = explode(',', Config::get($tab));
$tableau = array_map('trim', $tableau);
foreach ($tableau as $champ) {
list($code, $rang) = explode('=', $champ);
$tab_tampon[$code] = $rang;
}
$this->$tab = $tab_tampon;
$tab_tampon = array();
}
}
 
public function renvoyerErreur($entete, $message) {
throw new Exception($message, $entete);
}
 
/**
* Permet de remplir la variable version_projet et de retirer cette donnée du tableau des ressources
* @param $ressources
*/
public function traiterVersionProjet() {
if (isset($this->parametres['version.projet'])) {
if (preg_match('/^[0-9]+(?:[._][0-9]+|)$/', $this->parametres['version.projet'])) {
$this->version_projet = $this->parametres['version.projet'];
$this->version_projet = 'v'.str_replace('.', '_', $this->version_projet);
} else {
$this->version_projet = $this->parametres['version.projet'];
}
}
//si la liste des noms est demandée pr toutes les versions, on affiche seulement la dernière version :
if ($this->version_projet == '*' && $this->ressources == array()) {
$message = "L'affichage de plusieurs versions ne fonctionne que pour les ressources de type /ressources/#id";
$code = RestServeur::HTTP_CODE_MAUVAISE_REQUETE;
throw new Exception($message, $code);
}
//on recupère les versions du projet disponible dans la table des meta-donnees (utilisation service MetaDonnees)
$table_num_version = $this->recupererVersionDisponible();
//on recupere la liste des noms des tables de la bdd correspondant aux differentes versions du projet en fct de la ou les versions demandées
$this->recupererListeNomTablePrChaqueVersion($table_num_version);
}
 
/**
* Recupération des versions disponibles par appel du service metaDonnees
* Verification de l'existance du service recherché dans la requete (si précisé : hors *)
* @return array : tableau contenant le numéro de chaque version disponible
*/
public function recupererVersionDisponible() {
$versions_dispo = '';
$req_version = 'SELECT version FROM '.Config::get('bdd_table_meta');
$res_version = $this->getBdd()->recupererTous($req_version);
if ($res_version == '') { //cas ou la requete comporte des erreurs
$e = "La requête SQL de versionnage formée comporte une erreur : $req_version";
$this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $e);
} elseif ($res_version) {
foreach ($res_version as $version) {
$versions_dispo[] = $version['version'];
}
} else {
$m = 'Versions introuvables dans la table des méta-données';
$this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $m);
}
return $versions_dispo;
}
 
public function recupererListeNomTablePrChaqueVersion($table_num_version) {
switch ($this->serviceNom) {
case 'Ontologies' :
$prefixe_table = 'bdd_table_ontologies';
break;
default:
$prefixe_table = 'bdd_table';
}
switch ($this->version_projet) {
case '+' :
$derniere_version = $table_num_version[count($table_num_version) - 1];
$this->table_version[] = Config::get($prefixe_table).'_v'.str_replace('.', '_', $derniere_version);
break;
case '*' :
foreach ($table_num_version as $num_version) {
$this->table_version[] = Config::get($prefixe_table).'_v'.str_replace('.', '_', $num_version);
}
break;
default :
$this->table_version[] = Config::get($prefixe_table).'_'.$this->version_projet;
break;
}
}
 
/**
* Est appelée pour former l'url complete des resultats precedants ou suivants.
* @param int : Permet de connaitre le nombre de noms obtenus par la requete
* @return string Retourne l'url complete des resultats precedents ou suivant sous la forme d'un tableau
*/
public function formulerUrl($nb_resultat, $id = null) {
$url = array();
$debut_url = Config::get('url_service').$id.'?';
//on recré l'url sans les parametres de navigation qui seront rajouter ci-apres. On les enlève dc de la table des parametres
foreach($this->parametres as $cle => $val) {
$param_url[str_replace('_', '.', $cle)] = $val;
}
 
$this->recupererLesLimitesSuivantes($nb_resultat, $param_url);
if (isset($param_url['navigation.depart']) && isset($param_url['navigation.limite'])) {
$url['suivant'] = $debut_url.http_build_query($param_url);
}
 
$this->recupererLesLimitesPrecedentes($param_url);
if (isset($param_url['navigation.depart']) && isset($param_url['navigation.limite'])) {
$url['precedent'] = $debut_url.http_build_query($param_url);
}
return $url;
}
 
public function supprimerNavigation(&$param_url) {
unset($param_url['navigation.depart']);
unset($param_url['navigation.limite']);
}
 
/**
* Description :
* Permet de former les limites de la requete retournant les résultats suivants.
* Cette url sera afficher dans l'entete de la reponse retournée en format JSON (retour.format=defaut).
* @param int : $nb_resultat : Permet de connaitre le nombre de résultats obtenus par la requete
* @return string : la fin de l'url decrivant les limites des resultats suivants. Si aucun résultats ne suient,
* une chaine de caractère vide est retournée
*/
public function recupererLesLimitesSuivantes($nb_resultat, &$param_url_suiv) {
$this->supprimerNavigation($param_url);
$depart = $this->limite_requete['depart'];
$limite = $this->limite_requete['limite'];
$depart_suivant = $depart + $limite;
$limite_suivant = $limite;
if ($nb_resultat > $depart_suivant) {
$param_url_suiv['navigation.depart'] = $depart_suivant;
$param_url_suiv['navigation.limite'] = $limite_suivant;
} else {
$param_url_suiv['navigation.depart'] = null;
$param_url_suiv['navigation.limite'] = null;
}
}
 
/**
* Description :
* Permet de former les limites de la requete retournant les résultats precedents.
* Cette url sera afficher dans l'entete de la taxons/105reponse retournée en format JSON (retour.format=defaut)
* @return string : la fin de l'url decrivant les limites des resultats precedents.
* Si aucun résultats ne precedent, une chaine de caractère vide est retournée
*/
public function recupererLesLimitesPrecedentes(&$param_url) {
$this->supprimerNavigation($param_url);
$depart = $this->limite_requete['depart'];
$limite = $this->limite_requete['limite'];
if ($depart == 0) {
$url_precedente = '';
} else {
if (($depart - $limite) < 0) {
$depart_precedent = 0;
} else {
$depart_precedent = $depart - $limite;
}
$param_url['navigation.depart'] = $depart_precedent;
$param_url['navigation.limite'] = $limite;
}
}
 
public function ajouterHref($service, $val) {
// http://tela-botanica.org/service:eflore:0.1/[projet]/[version_projet]/[service]/[ressource]:[valeur]
if ($this->version_projet == '+') {
$url = Config::get('url_service_base').Config::get('nom_projet').'/'.$service.'/'.$val;
} else {
$url = Config::get('url_service_base').Config::get('nom_projet').'/'.$service.'/'.$val.'?version.projet='.ltrim($this->version_projet, 'v');
}
return $url;
}
 
public function ajouterHrefAutreProjet($service, $ressource, $valeur, $projet = null, $param = null) {
//on enleve les GA et Co, les meta ou les "_"
$this->transliterer($service, $valeur);
//on définit les nom des projets, des services et des ressources de l'url (dans les méta-donnees)
$tab = array(
'langue' => array('service' => 'langues', 'projet' => 'iso-639-1', 'ressource' => ''),
'couverture_spatiale' => array('service' => 'zone-geo', 'projet' => 'iso-3166-1', 'ressource' => ''),
'type' => array('service' => 'ontologies', 'projet' => 'eflore', 'ressource' => 'contactType:'),
'datum' => array('service' => 'ontologies', 'projet' => 'eflore', 'ressource' => 'datum:')
);
if (array_key_exists($service, $tab)) {
extract($tab[$service]);
} else {
if (strpos(Config::get('nom_projet'), 'bd') === 0 && $projet == null) {
$projet = 'bdnt';
$service = 'ontologies';
$ressource = '';
}
}
$param = ($param) ? "?".$param : "";
$url = Config::get('url_service_base').$projet.'/'.$service.'/'.$ressource.$valeur.$param;
return $url;
}
 
/**Permet de consulter une url et retourne le résultat ou une erreur
* @param $url */
public function consulterHref($url) {
$res = $this->getRestClient()->consulter($url);
$entete = $this->getRestClient()->getReponseEntetes();
//Si le service meta-donnees fonctionne correctement, l'entete comprend la clé wrapper_data
if (isset($entete['wrapper_data'])) {
$res = json_decode($res);
return $res;
} else {
$u = 'L\'url <a href="'.$url.'">'.$url.'</a> lancée via RestClient renvoie une erreur';
$this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $u);
}
}
 
public function transliterer(&$service, &$val) {
if (preg_match('/^.+:(.+)$/', $val, $match)) {
$val = $match[1];
}
$service = str_replace(array('_Ga','_Co','_meta'), '', $service);
if ($service == 'rang') {
$ressource = 'rangTaxo';
} elseif (preg_match('/^(statut)(?:_|-)([^_-]+)$/', $service, $match)) {
$service = $match[1].ucfirst($match[2]);
} elseif (strrpos($service, 'datum') !== false) {
$service = 'datum';
}
}
 
// prend en valeur la valeur de la recherche, les résultats approchés, le paramétre recherche
// retourne le tableau trié en fonction de la ressemble entre le résultat approché et la valeur recherchée
public function trierRechercheFloue($nom_demande, $tab_approchee, $nom) {
$trie = '';
$resultat = array();
foreach ($tab_approchee as $id => $tab) {
$nom_demande_ss = strtolower(Chaine::supprimerAccents($nom_demande));
$nom_flou_ss = strtolower(Chaine::supprimerAccents($tab[$nom]));
$stat = array();
// Prime pour la ressemblance globale :
$score = 500 - levenshtein($nom_flou_ss, $nom_demande_ss);
// On affine
$score = $score + (similar_text($nom_demande_ss, $nom_flou_ss) * 3);
$stat['score'] = $score;
foreach ($tab as $key => $valeur) {
$stat[$key] = $valeur;
}
$resultat[] = $stat;
}
 
 
// Vérification que nous avons bien trouvé un nom approché
if (count($resultat) > 0) {
$trie = Tableau::trierMD($resultat, array('score' => SORT_DESC));
}
return $trie;
}
 
protected function recupererTableauConfig($param) {
$tableau = array();
$tableauPartiel = explode(',', Config::get($param));
$tableauPartiel = array_map('trim', $tableauPartiel);
foreach ($tableauPartiel as $champ) {
if (strpos($champ, '=') === false) {
$tableau[] = $champ;
} else {
list($cle, $val) = explode('=', $champ);
$tableau[$cle] = $val;
}
}
return $tableau;
}
 
//+------------------------------------------------------------------------------------------------------+
// Méthodes d'accès aux objets du Framework
/**
* Méthode de connection à la base de données sur demande.
* Tous les services web n'ont pas besoin de s'y connecter.
*/
protected function getBdd() {
if (! isset($this->Bdd)) {
$this->Bdd = new Bdd();
}
return $this->Bdd;
}
 
/**
* Méthode permettant de faire appel à un client REST en fonction des besoins du service.
*/
protected function getRestClient() {
if (! isset($this->RestClient)) {
$this->RestClient = new RestClient();
}
return $this->RestClient;
}
}
?>
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/tags/v1.1-helium/services/bibliotheque/Navigation.php
New file
0,0 → 1,131
<?php
/**
* Navigation gère les url de navigation en fonction d'un départ et d'une limite
 
* @category php 5.2
* @package del
* @author Grégoire Duché <gregoire@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
*/
class Navigation {
 
private $parametres;
private $urlNavigation;
private $total;
 
/**
* Constructeur de la classe Navigation
* @param Array $parametres (optionnel) la liste des paramètre issus du Conteneur
* */
public function __construct($parametres = null) {
$this->parametres = $parametres;
}
 
/**
* Obtenir la valeur courante de départ
* */
public function getDepart() {
return isset($this->parametres['navigation.depart']) ? $this->parametres['navigation.depart'] : 0;
}
 
/**
* Obtenir la limite courante
* */
public function getLimite() {
$limite = 10;
if (isset($this->parametres['navigation.limite']) && is_numeric($this->parametres['navigation.limite'])) {
$limite = $this->parametres['navigation.limite'];
$limite = ($limite < 1000) ? $limite : 1000;// Pour éviter les abus !
}
return $limite;
}
 
/**
* Configurer l'Url de navigation en fonction du fichier de configuration
* */
public function chargerUrl() {
$this->urlNavigation = new Url(Config::get('url_service'));
$this->urlNavigation->setOption(Url::OPTION_ENCODER_VALEURS, true);
}
 
/**
* Obtenir l'url en fonction d'un départ et d'une limite donnée
* @param int $depart l'entier de départ
* @param int $limite le nombre d'éléments limite
* */
public function getUrl($depart = null, $limite = null) {
if ($depart == null && $limite == null) {
return $this->urlNavigation;
} else {
return $this->obtenirUrlNavigation($depart, $limite);
}
}
 
/**
* Récupérer l'url de navigation en concaténant d'éventuels paramètres
* @param $depart l'entier de départ de la recherche
* @param $limite le nombre de résultats à retourner
* @param $parametresAdditionnels le tableau contenant les parametres => valeurs additionnels
* */
private function obtenirUrlNavigation($depart, $limite) {
 
$parametres = $this->parametres;
$parametres['navigation.depart'] = $depart;
$parametres['navigation.limite'] = $limite;
 
$this->urlNavigation->setRequete($parametres);
$url = $this->urlNavigation->getURL();
return $url;
}
 
/**
* Récupérer le lien pour afficher les images précédentes en fonction des paramètres
* */
public function recupererHrefPrecedent() {
$departActuel = $this->getDepart();
$limite = $this->getLimite();
$departPrecedent = $departActuel - $limite;
 
$url = null;
 
if ($departActuel > 0) {
$url = $this->getUrl($departPrecedent, $limite);
}
return $url;
}
 
/**
* Récupérer le lien pour afficher les images suivantes en fonction des paramètres
* */
public function recupererHrefSuivant() {
 
$departActuel = $this->getDepart();
$limite = $this->getLimite();
$departSuivant = $departActuel + $limite;
$url = null;
if ($departSuivant < $this->total) {
$url = $this->getUrl($departSuivant, $limite);
}
return $url;
}
 
/**
* Retourner le nombre total d'éléments
* */
public function getTotal() {
return $this->total;
}
 
/**
* Enregistrer le nombre total d'éléments
* @param int $total le nombre d'éléments
* */
public function setTotal($total) {
$this->total = $total;
}
 
}
?>
/tags/v1.1-helium/services/bibliotheque/Outils.php
New file
0,0 → 1,21
<?php
class Outils {
 
public static function recupererTableauConfig($parametres) {
$tableau = array();
$tableauPartiel = explode(',', Config::get($parametres));
$tableauPartiel = array_map('trim', $tableauPartiel);
foreach ($tableauPartiel as $champ) {
if (strpos($champ, '=') === false) {
$tableau[] = $champ;
} else {
list($cle, $val) = explode('=', $champ);
$clePropre = trim($cle);
$valeurPropre = trim($val);
$tableau[$clePropre] = $valeurPropre;
}
}
return $tableau;
}
}
?>
/tags/v1.1-helium/services/bibliotheque/Conteneur.php
New file
0,0 → 1,168
<?php
/**
* Le conteneur encapsule les classe Masque, Navigation et GestionBdd
* Il gère leur instanciation, ainsi que la récupération des paramètres depuis l'url ou
* les fichiers de configuration
*
* @category php 5.2
* @package del
* @author Grégoire Duché <gregoire@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
*/
class Conteneur {
protected $parametres;
protected $navigation;
protected $masque;
protected $gestionBdd;
protected $sansLimite = false;
//TODO : initialiser tous les objets dans le conteneur
//TODO : créer un tableau de partage
/**
* Constructeur de la classe
* @param Array $parametres (optionnel) les paramètres additionnels à ajouter à ceux des fichiers de config
* */
public function __construct(array $parametres = null) {
$this->parametres = is_null($parametres) ? array() : $parametres;
}
/**
* Charger la configuration depuis le fichier
* @param String $chemin le chemin relatif depuis le dossier configurations du fichier
* */
public function chargerConfiguration($chemin) {
$cheminConfigurations = Config::get('chemin_configurations');
if ($cheminConfigurations == null || $cheminConfigurations == '') {
$message = 'Le chemin vers le répertoire Configurations n\'est pas renseigné';
$code = RestServeur::HTTP_CODE_ERREUR;
throw new Exception($message, $code);
}
Config::charger($cheminConfigurations.DS.$chemin);
if ($this->masque = $this->creerMasque()) {
$this->masque->chargerMasque();
} else {
$message = 'Erreur lors de la création du Masque';
$code = RestServeur::HTTP_CODE_ERREUR;
throw new Exception($message, $code);
}
if ($this->navigation = $this->creerNavigation()) {
$this->navigation->chargerUrl();
} else {
$message = 'Erreur lors de la création de la Navigation';
$code = RestServeur::HTTP_CODE_ERREUR;
throw new Exception($message, $code);
}
$this->creerGestionBdd($this->navigation, Config::get('schemaBdd'));
}
/**
* Créer l'objet Masque en fonction des configurations
* */
private function creerMasque() {
$this->masque = new Masque(Config::get('masques_possibles'), $this->parametres);
return $this->masque;
}
/**
* Créer l'objet navigation avec les paramètres
* */
private function creerNavigation() {
return ($this->navigation = new Navigation($this->parametres));
}
/**
* Créer l'objet Gestion BDD
* */
private function creerGestionBdd($navigation, $schemaBdd) {
$this->gestionBdd = new GestionBdd($navigation, $schemaBdd);
}
/**
* Récupérer l'objet GestionBdd
* */
public function getGestionBdd() {
return $this->gestionBdd;
}
 
/**
* Récupérer l'objet Navigation
* */
public function getNavigation() {
return $this->navigation;
}
/**
* Changer la valeur de sans limite pour ne pas l'afficher dans l'entete
* */
public function setSansLimite() {
$this->sansLimite = true;
}
/**
* Créer l'entête en fonction des paramètres donnés
* */
public function getEntete() {
$entete = array();
$entete['masque'] = $this->masque->getChaineMasque();
$entete['total'] = $this->navigation->getTotal();
if ($this->sansLimite == false) {
$entete['depart'] = $this->navigation->getDepart();
$entete['limite'] = $this->navigation->getLimite();
$lienPrecedent = $this->navigation->recupererHrefPrecedent();
if ($lienPrecedent != null) {
$entete['href.precedent'] = $lienPrecedent;
}
$lienSuivant = $this->navigation->recupererHrefSuivant();
if ($lienSuivant) {
$entete['href.suivant'] = $lienSuivant;
}
}
return $entete;
}
public function getRestClient() {
if (!isset($this->restClient)) {
$this->restClient = new RestClient();
}
return $this->restClient;
}
/**
* Récupérer l'objet Masque
* */
public function getMasque() {
return $this->masque;
}
/**
* Obtenir un paramètre depuis le tableau de paramètres ou depuis le fichier de config
* @param String $cle le nom du paramètre
* @return la valeur du paramètre
* */
public function getParametre($cle) {
$valeur = isset($this->parametres[$cle]) ? $this->parametres[$cle] : Config::get($cle);
return $valeur;
}
/**
* Enregistrer la valeur d'un paramètre
* */
public function setParametre($cle, $valeur) {
$this->parametres[$cle] = $valeur;
}
}
?>
/tags/v1.1-helium/services/bibliotheque/GestionBdd.php
New file
0,0 → 1,91
<?php
/**
* Gestion BDD permet l'appel à l'objet BDD du framework,
* gère les noms de table en fonction du schéma de la table
* ainsi que la limite SQL en fonction de l'objet Navigation
 
* @category php 5.2
* @package del
* @author Grégoire Duché <gregoire@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
*/
class GestionBdd {
private $bdd;
private $schemaBdd;
private $navigation;
/**
* Constructeur de la classe GestionBdd
* @param Navigation $navigation l'objet navigation issu du Conteneur, et contenant les informations de départ et limite
* @param String $schemaBdd (optionnel) le schéma de la base issu du fichier de config
* @param Bdd $bdd (optionnel) un objet Bdd pour la connection à la base de données
* */
public function __construct($navigation, $schemaBdd = null, $bdd = null) {
if ($navigation == null) {
$message = 'L\'objet Navigation est nécessaire pour configurer l\'objet GestionBdd';
$code = RestServeur::HTTP_CODE_ERREUR;
throw new Exception($message, $code);
} else {
$this->navigation = $navigation;
$this->schemaBdd = $schemaBdd;
if ($bdd == null) {
$this->bdd = new Bdd();
} else {
$this->bdd = $bdd;
}
}
}
/**
* Créer la chaine de limite de requête en fonction des paramètres donnés
* */
public function getLimitSql() {
return ' LIMIT '.$this->navigation->getDepart().', '.$this->navigation->getLimite();
}
/**
* Récupérer l'objet Bdd ou le créer s'il n'existe pas
* @return Bdd l'objet Bdd
* */
public function getBdd() {
if (!isset($this->bdd)){
$this->bdd = new Bdd();
}
return $this->bdd;
}
/** Formater un nom de table avec le schéma de la base de données, s'il existe
* @param String $table le nom de la table
* @param String $as (optionnel) l'alias de la table
* @return String la chaine de caractère sous la forme "schema.nomtable as nt"
* */
public function formaterTable($table, $as = null) {
$chaineTable = $table;
if ($this->schemaBdd != null) {
$chaineTable = $this->schemaBdd.'.'.$table;
}
if ($as != null && $as != '') {
$chaineTable .= ' as '.$as;
}
return $chaineTable.' ';
}
/** Formater des noms de table avec le schéma de la base de données, s'il existe
* @param Array $tables un tableau à deux dimensions contenant le nom et l'alias de la table
* Ex : Array("nom" => "as", "table" => "")
* @return String la chaine de caractère sous la forme "schema.nomtable as nt, schema.nomtable2 as nt2"
* */
public function formaterTables($tables) {
$tablesFormatees = array();
foreach ($tables as $nom => $as) {
$tablesFormatees[] = $this->formaterTable($nom, $as);
}
return implode(',', $tablesFormatees);
}
}
?>
/tags/v1.1-helium/services/bibliotheque/gestionUtilisateur.php
New file
0,0 → 1,88
<?php
class gestionUtilisateur {
private $conteneur;
private $gestionBdd;
private $bdd;
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->conteneur->chargerConfiguration('config_utilisateurs.ini');
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
$this->demarrerSession();
}
private function demarrerSession() {
if(session_id() == '') {
// modifier ce test lors du passage en php 5.4
session_start();
}
}
protected function getUtilisateurAnonyme() {
return array('connecte' => false,
'id_utilisateur' => session_id(),
'courriel' => '',
'mot_de_passe' => '',
'nom' => '',
'prenom' => '',
'session_id' => session_id()
);
}
protected function utilisateurEstIdentifie() {
$utilisateur = null;
$utilisateur = $this->utilisateurEstIdentifieCookie();
if ($utilisateur != null) {
$utilisateur['session_id'] = session_id();
}
return $utilisateur;
}
protected function utilisateurEstIdentifieCookie() {
$retour = null;
if(isset($_COOKIE["del_courriel"]) && isset($_COOKIE["del_mot_de_passe"])) {
$retour = $this->identifierUtilisateurSansEncryptionMotDePasse($_COOKIE["del_courriel"], $_COOKIE["del_mot_de_passe"]);
}
return $retour;
}
protected function identifierUtilisateur($login, $motDePasse) {
$requete = 'SELECT id_utilisateur, nom, prenom, courriel, mot_de_passe FROM '.$this->gestionBdd->formaterTable('del_utilisateur', 'du').
'WHERE courriel = '.$this->bdd->proteger($login).' '.
'AND mot_de_passe = MD5('.$this->bdd->proteger($motDePasse).')';
$utilisateur = $this->bdd->recupererTous($requete);
return $utilisateur;
}
protected function identifierUtilisateurSansEncryptionMotDePasse($login, $mot_de_passe) {
$requete = 'SELECT id_utilisateur, nom, prenom, courriel, mot_de_passe FROM '.$this->gestionBdd->formaterTable('del_utilisateur', 'du').
'WHERE courriel = '.$this->bdd->proteger($login).' '.
'AND mot_de_passe = '.$this->bdd->proteger($mot_de_passe);
$utilisateur = $this->bdd->recuperer($requete);
return $utilisateur;
}
protected function setUtilisateur($utilisateur) {
$utilisateur['session_id'] = session_id();
$utilisateur['connecte'] = true;
$this->setPersistentCookie("del_courriel", $utilisateur['courriel'], 1);
$this->setPersistentCookie("del_mot_de_passe", $utilisateur['mot_de_passe'], 1);
return $utilisateur;
}
protected function setPersistentCookie($name, $value, $remember = 1) {
setcookie($name, $value, time() + ($remember ? (60*60*24*100) : (60*60)),'/');
}
protected function oublierUtilisateur() {
setcookie("del_courriel", $_COOKIE['del_courriel'], time()-3600, '/');
setcookie("del_mot_de_passe", $_COOKIE['del_mot_de_passe'], time()-3600, '/');
unset($_COOKIE['del_courriel']);
unset($_COOKIE['del_mot_de_passe']);
}
}
?>
/tags/v1.1-helium/services/bibliotheque/ControleAcces.php
New file
0,0 → 1,143
<?php
/**
* Classe de controle d'accès utilisant l'authentification http pour bloquer ou autoriser l'accès.
* Elle offre des méthodes permettant de réserver l'accès à une section aux admins ou bien aux utilisateurs identifiés
*
* @category php 5.2
* @package del
* @author Aurélien Peronnet <aurelien@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
*/
class ControleAcces {
private $conteneur;
private $gestionBdd;
private $bdd;
public function __construct($conteneur) {
$this->conteneur = $conteneur;
$this->gestionBdd = $conteneur->getGestionBdd();
$this->bdd = $this->gestionBdd->getBdd();
}
public function demanderAuthentificationAdmin() {
if(!$this->etreAdminAutorise()) {
$this->authentifierAdmin();
}
}
public function demanderAuthentificationUtilisateur() {
if(!$this->etreUtilisateurAutorise()) {
$this->authentifierUtilisateur();
}
}
public function etreUtilisateurAutorise() {
$identifiant = $this->getAuthIdentifiant();
$mdp = $this->getAuthMotDePasse();
$existe = $this->obtenirUtilisateur($identifiant, $mdp);
$autorisation = (isset($existe) && $existe) ? true :false;
return $autorisation;
}
private function obtenirUtilisateur($login, $motDePasse) {
$requete = 'SELECT id_utilisateur, nom, prenom, courriel, mot_de_passe FROM '.$this->gestionBdd->formaterTable('del_utilisateur', 'du').
'WHERE courriel = '.$this->gestionBdd->getBdd()->proteger($login).' '.
'AND mot_de_passe = MD5('.$this->gestionBdd->getBdd()->proteger($motDePasse).')';
$utilisateur = $this->gestionBdd->getBdd()->recuperer($requete . ' -- ' . __FILE__ . ':' . __LINE__);
return $utilisateur;
}
private function obtenirUtilisateurSansEncryptionMdp($login, $motDePasseEncrypte) {
$requete = 'SELECT id_utilisateur, nom, prenom, courriel, mot_de_passe FROM '.$this->gestionBdd->formaterTable('del_utilisateur', 'du').
'WHERE courriel = '.$this->gestionBdd->getBdd()->proteger($login).' '.
'AND mot_de_passe = '.$this->gestionBdd->getBdd()->proteger($motDePasseEncrypte).' ';
$utilisateur = $this->gestionBdd->getBdd()->recuperer($requete . ' -- ' . __FILE__ . ':' . __LINE__);
return $utilisateur;
}
public function etreAdminAutorise() {
$identifiant = $this->getAuthIdentifiant();
$autorisation = ($this->etreAdminDel($identifiant) && $this->etreUtilisateurAutorise()) ? true : false;
return $autorisation;
}
public function etreAdminDel($courriel) {
$admins = Config::get('admins');
$courriels_autorises = explode(',', $admins);
$autorisation = (in_array($courriel, $courriels_autorises)) ? true : false ;
return $autorisation;
}
private function getAuthIdentifiant() {
$id = (isset($_SERVER['PHP_AUTH_USER'])) ? $_SERVER['PHP_AUTH_USER'] : null;
return $id;
}
private function getAuthMotDePasse() {
$mdp = (isset($_SERVER['PHP_AUTH_PW'])) ? $_SERVER['PHP_AUTH_PW'] : null;
return $mdp;
}
//TODO: externaliser noms et adresses spécifiques à Tela Botanica
private function authentifierAdmin() {
$message_accueil = "Veuillez vous identifier avec votre compte administrateur Tela Botanica.";
$message_echec = "Accès limité aux administrateurs de DEL.\n".
"Votre tentative d'identification a échoué.\n".
"Actualiser la page pour essayer à nouveau si vous êtes bien inscrit comme administrateur.";
return $this->authentifier($message_accueil, $message_echec, 'Admin');
}
private function authentifierUtilisateur() {
$message_accueil = "Veuillez vous identifier avec votre compte Tela Botanica.";
$message_echec = "Accès limité aux utilisateurs de DEL.\n".
"Inscrivez vous http://www.tela-botanica.org/page:inscription pour le devenir.\n".
"Votre tentative d'identification a échoué.\n".
"Actualiser la page pour essayer à nouveau si vous êtes déjà inscrit ou contacter 'accueil@tela-botanica.org'.";
return $this->authentifier($message_accueil, $message_echec, 'Utilisateur');
}
private function authentifier($message_accueil, $message_echec, $type) {
$id = $this->getAuthIdentifiant();
if (!isset($id)) {
$this->envoyerAuth($message_accueil, $message_echec);
} else {
if ($type == 'Utilisateur' && $this->getAuthMotDePasse() == 'debug') {
$autorisation = true;
} else {
$methodeAutorisation = "etre{$type}Autorise";
$autorisation = $this->$methodeAutorisation();
}
if ($autorisation == false) {
$this->envoyerAuth($message_accueil, $message_echec);
}
}
return true;
}
public function getInfosUtilisateurConnecte() {
if(isset($_COOKIE["del_courriel"])) {
$utilisateur = array('del_courriel' => $_COOKIE["del_courriel"],
'del_mot_de_passe' => $_COOKIE["del_mot_de_passe"]);
$utilisateur = $this->obtenirUtilisateurSansEncryptionMdp($utilisateur['del_courriel'], $utilisateur['del_mot_de_passe']);
}
return $utilisateur;
}
public function getIdAnonymeTemporaire() {
$this->demarrerSession();
return session_id();
}
private function demarrerSession() {
if(session_id() == '') {
// modifier ce test lors du passage en php 5.4
session_start();
}
}
}
/tags/v1.1-helium/services/bibliotheque/EnteteHttp.php
New file
0,0 → 1,7
<?php
class EnteteHttp {
public $code = RestServeur::HTTP_CODE_OK;
public $encodage = 'utf-8';
public $mime = 'application/json';
}
?>
/tags/v1.1-helium/services/bibliotheque/ResultatService.php
New file
0,0 → 1,7
<?php
class ResultatService {
public $mime = 'application/json';
public $encodage = 'utf-8';
public $corps = '';
}
?>
/tags/v1.1-helium/services/bibliotheque/Masque.php
New file
0,0 → 1,80
<?php
/**
* Navigation gère les url de navigation en fonction d'un départ et d'une limite
 
* @category php 5.2
* @package del
* @author Grégoire Duché <gregoire@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $
*/
class Masque {
const prefixe = 'masque.';
const masqueGeneral = 'masque';
private $masquesPossibles;
private $parametres;
private $masque;
/**
* Constructeur de la classe Masque
* @param $masquesPossibles la liste des masques autorisés séparé par des ','
* */
public function __construct($masquesPossibles, $parametres = null) {
if ($masquesPossibles != null && trim($masquesPossibles) == '') {
$message = 'La liste des masques possibles est obligatoire';
$code = RestServeur::HTTP_CODE_ERREUR;
throw new Exception($message, $code);
}
$this->masquesPossibles = explode(',', $masquesPossibles);
$this->parametres = $parametres;
$this->chargerMasque();
}
/**
* Parcourir le tableau Paramètres pour trouver tous les champs masque
*/
public function chargerMasque() {
if ($this->parametres != null) {
foreach ($this->parametres as $id => $parametre) {
if (strpos($id, self::prefixe) === 0 || $id == self::masqueGeneral) {
if (in_array(str_replace(self::prefixe, '', $id), $this->masquesPossibles)) {
$this->masque[$id] = $parametre;
}
}
}
}
}
/**
* Retourner les masques sous forme de chaine
* @return String la chaine de caractère sous la forme masque=valeur&masque2=valeur*/
public function getChaineMasque() {
if (!empty($this->masque)) {
$chaine = array();
foreach ($this->masque as $id => $valeur) {
$chaine[] = $id.'='.$valeur;
}
return implode('&', $chaine);
} else {
return '';
}
}
/**
* Récupérer tout ou partie du masque
* @param String $id (optionnel) l'idenfiant du masque
* @return une chaine de caractère si l'identifiant est passé en paramètre, un tableau sinon
* */
public function getMasque($id = null) {
if (isset($id)) {
return $this->masque[self::prefixe.$id];
} else {
return $this->masque;
}
}
}
?>
/tags/v1.1-helium/services/bibliotheque/ReponseHttp.php
New file
0,0 → 1,62
<?php
class ReponseHttp {
 
private $resultatService = null;
private $erreurs = array();
 
public function __construct() {
$this->resultatService = new ResultatService();
}
 
public function setResultatService($resultat) {
if (!($resultat instanceof ResultatService)) {
$this->resultatService->corps = $resultat;
} else {
$this->resultatService = $resultat;
}
}
 
public function getCorps() {
if ($this->etreEnErreur()) {
$this->resultatService->corps = $this->erreurs[0]['message'];
} else {
$this->transformerReponseCorpsSuivantMime();
}
return $this->resultatService->corps;
}
 
public function ajouterErreur(Exception $e) {
$this->erreurs[] = array('entete' => $e->getCode(), 'message' => $e->getMessage());
}
 
public function emettreLesEntetes() {
$enteteHttp = new EnteteHttp();
if ($this->etreEnErreur()) {
$enteteHttp->code = $this->erreurs[0]['entete'];
$enteteHttp->mime = 'text/html';
} else {
$enteteHttp->encodage = $this->resultatService->encodage;
$enteteHttp->mime = $this->resultatService->mime;
}
header("Content-Type: $enteteHttp->mime; charset=$enteteHttp->encodage");
RestServeur::envoyerEnteteStatutHttp($enteteHttp->code);
}
 
private function etreEnErreur() {
$enErreur = false;
if (count($this->erreurs) > 0) {
$enErreur = true;
}
return $enErreur;
}
 
private function transformerReponseCorpsSuivantMime() {
switch ($this->resultatService->mime) {
case 'application/json' :
$this->resultatService->corps = json_encode($this->resultatService->corps);
break;
}
}
 
}
?>
/tags/v1.1-helium/services/index.php
New file
0,0 → 1,43
<?php
// Encodage : UTF-8
// Permet d'afficher le temps d'execution du service
$temps_debut = (isset($_GET['chrono']) && $_GET['chrono'] == 1) ? microtime(true) : '';
// +-------------------------------------------------------------------------------------------------------------------+
/**
* Serveur
*
* Description : initialise le chargement et l'exécution des services web.
*
//Auteur original :
* @author auteur <aut@tela-botanica.org>
* @copyright Tela-Botanica 1999-2008
* @licence GPL v3 & CeCILL v2
* @version $Id$
*/
// +-------------------------------------------------------------------------------------------------------------------+
 
// Le fichier autoload.inc.php du Framework de Tela Botanica doit être appelée avant tout autre chose dans l'application.
// Sinon, rien ne sera chargé.
// Chemin du fichier chargeant le framework requis
$framework = dirname(__FILE__).DIRECTORY_SEPARATOR.'framework.php';
if (!file_exists($framework)) {
$e = "Veuillez paramétrer l'emplacement et la version du Framework dans le fichier $framework";
trigger_error($e, E_USER_ERROR);
} else {
// Inclusion du Framework
require_once $framework;
// Ajout d'information concernant cette application
Framework::setCheminAppli(__FILE__);// Obligatoire
Framework::setInfoAppli(Config::get('info'));
// Initialisation et lancement du serveur
$Serveur = new RestServeur();
$Serveur->executer();
// Affiche le temps d'execution du service
if (isset($_GET['chrono']) && $_GET['chrono'] == 1) {
$temps_fin = microtime(true);
echo 'Temps d\'execution : '.round($temps_fin - $temps_debut, 4);
}
}
?>
/tags/v1.1-helium/services/tests/0.1/observations/masque=G-date=2009.data.json
New file
0,0 → 1,0
{"entete":{"masque":"masque=Grand&masque.date=2009","total":8,"depart":"0","limite":"12"},"resultats":{"\"44174\"":{"id_observation":"44174","date_observation":"2009-06-08 00:00:00","date_transmission":"2010-12-21 21:16:09","determination.famille":"Apiaceae","determination.ns":"Orlaya grandiflora (L.) Hoffm.","determination.nn":"46423","determination.nt":"235","determination.referentiel":"bdtfx:v1.01","observateur":"paul.fabre19@gmail.com","id_zone_geo":"INSEE-C:07334","zone_geo":"Les Vans","lieudit":null,"station":"Les Gras","milieu":"Garrigue de thym","auteur.nom":"FABRE","auteur.prenom":"Paul","auteur.id":"11326","mots_cles_texte":null,"commentaire":"sol calcaire","images":[{"id_image":"15653","date":"2009-06-08 12:47:28","hauteur":"2112","largeur":"2816","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000015653XL.jpg"},{"id_image":"15654","date":"2009-06-08 12:47:39","hauteur":"2816","largeur":"2112","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000015654XL.jpg"}]},"\"619435\"":{"id_observation":"619435","date_observation":"2009-06-14 00:00:00","date_transmission":"2011-11-23 08:03:58","determination.famille":"Lamiaceae","determination.ns":"Clinopodium grandiflorum (L.) Kuntze","determination.nn":"18255","determination.nt":"3527","determination.referentiel":"bdtfx:v1.01","observateur":"houdrejj@free.fr","id_zone_geo":"INSEE-C:15073","zone_geo":"Fridefont","lieudit":null,"station":null,"milieu":null,"auteur.nom":"HOUDR\u00c9","auteur.prenom":"Jean-Jacques","auteur.id":"1503","mots_cles_texte":"null","commentaire":null,"images":[{"id_image":"51994","date":"2009-06-14 07:54:10","hauteur":"1602","largeur":"2394","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000051994XL.jpg"}]},"\"619700\"":{"id_observation":"619700","date_observation":"2009-07-12 00:00:00","date_transmission":"2011-11-25 22:37:48","determination.famille":"Plantaginaceae","determination.ns":"Digitalis grandiflora Mill.","determination.nn":"22409","determination.nt":"5321","determination.referentiel":"bdtfx:v1.01","observateur":"houdrejj@free.fr","id_zone_geo":"INSEE-C:73024","zone_geo":"Les Avanchers-Valmorel","lieudit":null,"station":null,"milieu":null,"auteur.nom":"HOUDR\u00c9","auteur.prenom":"Jean-Jacques","auteur.id":"1503","mots_cles_texte":null,"commentaire":null,"images":[{"id_image":"52237","date":"2009-07-12 08:37:18","hauteur":"2008","largeur":"3000","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000052237XL.jpg"},{"id_image":"52238","date":"2009-07-12 08:37:37","hauteur":"3000","largeur":"2008","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000052238XL.jpg"}],"commentaires":[{"2863":{"nb_commentaires":"0","id_commentaire":"2863","observation":"619700","proposition":"0","id_parent":"0","auteur.id":"1503","auteur.nom":"HOUDR\u00c9","auteur.prenom":"Jean-Jacques","auteur.courriel":"houdrejj@free.fr","date":"0000-00-00 00:00:00","nom_sel":"Digitalis grandiflora Mill.","nom_sel_nn":"22409","nom_ret_nn":"22409","proposition_initiale":"1","votes":{"3741":{"vote.id":"3741","proposition.id":"2863","auteur.id":"20207","vote":"1","date":"2013-04-11 22:30:20"}}}}]},"\"722604\"":{"id_observation":"722604","date_observation":"2009-06-10 00:00:00","date_transmission":"2012-02-14 15:47:50","determination.famille":"Apiaceae","determination.ns":"Orlaya grandiflora (L.) Hoffm.","determination.nn":"46423","determination.nt":"235","determination.referentiel":"bdtfx:v1.01","observateur":"mathieumenand@yahoo.fr","id_zone_geo":"INSEE-C:84143","zone_geo":"Venasque","lieudit":null,"station":null,"milieu":null,"auteur.nom":"MENAND","auteur.prenom":"Mathieu","auteur.id":"4967","mots_cles_texte":null,"commentaire":null,"images":[{"id_image":"18638","date":"2009-06-10 17:12:11","hauteur":"600","largeur":"800","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000018638XL.jpg"},{"id_image":"18832","date":"2009-06-10 17:14:26","hauteur":"600","largeur":"800","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000018832XL.jpg"}]},"\"724855\"":{"id_observation":"724855","date_observation":"2009-07-21 00:00:00","date_transmission":"2012-02-14 19:09:59","determination.famille":"Lentibulariaceae","determination.ns":"Pinguicula grandiflora Lam.","determination.nn":"49553","determination.nt":"5654","determination.referentiel":"bdtfx:v1.01","observateur":"avreliane@botaniste-en-herbe.net","id_zone_geo":"INSEE-C:09100","zone_geo":"Couflens","lieudit":null,"station":null,"milieu":null,"auteur.nom":"MAHYEUX","auteur.prenom":"Catherine","auteur.id":"8082","mots_cles_texte":null,"commentaire":null,"images":[{"id_image":"60639","date":"2009-07-21 16:41:58","hauteur":"488","largeur":"650","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000060639XL.jpg"},{"id_image":"60640","date":"2009-07-21 16:27:45","hauteur":"488","largeur":"650","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000060640XL.jpg"}]},"\"1021817\"":{"id_observation":"1021817","date_observation":"2009-06-27 00:00:00","date_transmission":"2013-07-16 12:01:26","determination.famille":"LINACEAE","determination.ns":"Linum alpinum Jacq.","determination.nn":"39369","determination.nt":"3751","determination.referentiel":"bdtfx:v1.01","observateur":"claude.figureau.plantnet@gmail.com","id_zone_geo":"INSEE-C:","zone_geo":"Grand Montrond lelex","lieudit":"","station":"","milieu":"","auteur.nom":"FIGUREAU","auteur.prenom":"Claude","auteur.id":"22878","mots_cles_texte":"Projets coop\u00e9ratifs","commentaire":"","images":[{"id_image":"165267","date":"2009-06-27 12:06:27","hauteur":"450","largeur":"600","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000165267XL.jpg"},{"id_image":"165266","date":"2009-06-27 12:06:51","hauteur":"450","largeur":"600","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000165266XL.jpg"},{"id_image":"165264","date":"2009-06-27 12:06:41","hauteur":"450","largeur":"600","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000165264XL.jpg"}]},"\"1032660\"":{"id_observation":"1032660","date_observation":"2009-04-04 00:00:00","date_transmission":"2013-08-02 18:55:42","determination.famille":"Fabaceae","determination.ns":"Agati grandiflora (L.) Desv.","determination.nn":"284","determination.nt":"2809","determination.referentiel":"bdtxa:1.00","observateur":"valbrasse@orange.fr","id_zone_geo":"INSEE-C:63099","zone_geo":"Ch\u00e2teaugay","lieudit":"","station":"","milieu":"","auteur.nom":"BRASSE","auteur.prenom":"Val\u00e9rie","auteur.id":"11681","mots_cles_texte":"WidgetSaisie,aDeterminer,Projets coop\u00e9ratifs","commentaire":"vue en Guadeloupe","images":[{"id_image":"179865","date":"2009-03-18 16:14:59","hauteur":"2816","largeur":"2112","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000179865XL.jpg"}]},"\"1032667\"":{"id_observation":"1032667","date_observation":"2009-04-04 00:00:00","date_transmission":"2013-08-02 19:05:53","determination.famille":"Aristolochiaceae","determination.ns":"Aristolochia grandiflora Sw.","determination.nn":"876","determination.nt":"273","determination.referentiel":"bdtxa:1.00","observateur":"valbrasse@orange.fr","id_zone_geo":"INSEE-C:63099","zone_geo":"Ch\u00e2teaugay","lieudit":"","station":"","milieu":"","auteur.nom":"BRASSE","auteur.prenom":"Val\u00e9rie","auteur.id":"11681","mots_cles_texte":"WidgetSaisie,aDeterminer,Projets coop\u00e9ratifs","commentaire":"vue en Guadeloupe (fleur)","images":[{"id_image":"179872","date":"2009-03-13 20:30:52","hauteur":"2816","largeur":"2112","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000179872XL.jpg"}]}}}
/tags/v1.1-helium/services/tests/0.1/observations/ObservationsTest.php
New file
0,0 → 1,162
<?php
require_once __DIR__ . '/../ServiceDelPhpUnit.php';
error_reporting(E_ALL);
 
class ObservationsTest extends ServiceDelPhpUnit {
//static function creerUrl($service, $ressources, $parametres = NULL) {
public function testNonExistant() {
$url = $this->creerUrl('observations');
$i = new Observations();
$retour = $this->consulterDirectJson($i->consulter([0], []),
$url);
// doit retourner une 404
$this->assertEmpty($retour, "Le json doit retourner un tableau vide. Voir : $url");
}
 
public function testExistant() {
$url = $this->creerUrl('observations');
$i = new Observations();
$retour = $this->consulterDirectJson($i->consulter([1043942], []),
$url);
 
$this->hasKeysAndNotEmpty($retour, ['auteur.id', 'auteur.nom', 'date_transmission', 'observateur', 'id_observation'], $url);
$this->hasKeys($retour, ['auteur.nom'], $url);
$this->assertArrayHasKey('auteur.id', $retour, "attribut auteur.id manquant. Voir : $url");
}
 
 
public function testExistantEtContenu() {
$url = $this->creerUrl('observations');
$i = new Observations();
$retour = $this->consulterDirectJson($i->consulter([1043942], []),
$url);
 
// from
// "http://www.tela-botanica.org/eflore/del/services/0.1/observations/1048532
$expected = json_decode(file_get_contents("obs-1048532-complete.data.json"), true);
 
self::ignoreNullValuesAndSort($expected);
self::ignoreNullValuesAndSort($retour);
 
// echo implode(',', array_keys($retour['resultats'])) . "\n" . implode(',', array_keys($expected['resultats']));die;
$this->clefsIdentiques($expected, $retour, $url);
$this->assertEquals($expected['resultats'], $retour['resultats'], "Différences dans le tableau pour l'obs 1048532, $url");
}
 
public function testSansImage() {
$url = $this->creerUrl('observations');
$i = new Observations();
$retour = $this->consulterDirectJson($i->consulter([14203], []),
$url);
// doit retourner une 404
$this->assertEmpty($retour, "Observation sans image devrait ne rien retourner. Voir : $url");
}
 
public function testRechercheNoObs() {
$url = $this->creerUrl('observations');
$i = new Observations();
$retour = $this->consulterDirectJson($i->consulter([], ['masque.date'=>-1e11]), // 10^11 secondes avant 1970
$url);
// doit retourner une 404
$this->assertEquals(0, $retour['entete']['total'], "Incongruité sur ['entete'][0]. Voir : $url");
$this->assertEmpty($retour['resultats'], "Absence d'observation devrait retourner un result-set vide. Voir : $url");
}
 
/* guidelines pour des tests pérennes:
* - Utiliser ordre=asc pour prendre les enregistrement les plus anciens, moins susceptibles de changer
* - Restreindre par date (évite les date_transmission = NULL, qui, après des GROUP BY affectent le result-set
* - Utiliser moins de "$limite" résultats à cause de la sélection (arbitraire[GROUP-BY])) des obs ayant la même date */
public function testMasque() {
$url = $this->creerUrl('observations');
$i = new Observations();
$retour = $this->consulterDirectJson($i->consulter([], ['navigation.depart'=>0,'navigation.limite'=>12,'ordre'=>'asc','masque'=>'Grand','masque.date'=>2009]),
$url);
// from
// "http://www.tela-botanica.org/eflore/del/services/0.1/observations?navigation.depart=0&navigation.limite=12&masque=Grand&masque.date=2009&ordre=asc"
$expected = json_decode(file_get_contents("masque=G-date=2009.data.json"), true);
 
self::ignoreNullValuesAndSort($expected);
self::ignoreNullValuesAndSort($retour);
 
// echo implode(',', array_keys($retour['resultats'])) . "\n" . implode(',', array_keys($expected['resultats']));die;
$this->clefsIdentiques($expected, $retour, $url);
$this->assertEquals($expected['resultats'], $retour['resultats'], "Différences dans le tableau, $url");
}
 
public function testType() {
@$url = $this->creerUrl('observations');
$i = new Observations();
$retour = $this->consulterDirectJson($i->consulter([], ['ordre'=>'asc','masque.type'=>'endiscussion']),
$url);
if(Config::get('nb_commentaires_discussion') != 1) {
printf("can't do test: Config::get('nb_commentaires_discussion') == %d <> 1\n", Config::get('nb_commentaires_discussion'));
return;
}
 
// from
// "http://www.tela-botanica.org/eflore/del/services/0.1/observations?masque.type=endiscussion&ordre=asc"
$expected = json_decode(file_get_contents("masque.type=endiscussion.data.json"), true);
 
self::ignoreNullValuesAndSort($expected);
self::ignoreNullValuesAndSort($retour);
 
// echo implode(',', array_keys($retour['resultats'])) . "\n" . implode(',', array_keys($expected['resultats']));die;
$this->clefsIdentiques($expected, $retour, $url);
$this->assertEquals($expected['resultats'], $retour['resultats'], "Différences dans le tableau, $url");
}
 
 
public function testMasqueEtType() {
@$url = $this->creerUrl('observations');
$i = new Observations();
$retour = $this->consulterDirectJson($i->consulter([], ['navigation.depart'=>0,'navigation.limite'=>12,'ordre'=>'asc','masque'=>'G','masque.type'=>'endiscussion']),
$url);
 
$expected = json_decode(file_get_contents("masque=G-masque.type=endiscussion.data.json"), true);
 
self::ignoreNullValuesAndSort($expected);
self::ignoreNullValuesAndSort($retour);
 
// echo implode(',', array_keys($retour['resultats'])) . "\n" . implode(',', array_keys($expected['resultats']));die;
$this->clefsIdentiques($expected, $retour, $url);
$this->assertEquals($expected['resultats'], $retour['resultats'], "Différences dans le tableau, $url");
}
 
 
 
public function hasKeys($arr, $keys, $url) {
foreach($keys as $k) {
$this->assertArrayHasKey($k, $arr, "attribut {$k} manquant. Voir : $url");
}
}
 
public function hasKeysAndNotEmpty($arr, $keys, $url) {
foreach($keys as $k) {
$this->assertArrayHasKey($k, $arr, "attribut {$k} manquant. Voir : $url");
$this->assertNotEmpty($arr[$k], "attribut {$k} vide. Voir : $url");
}
}
 
static function ignoreNullValuesAndSort(&$arr) {
$arr['resultats'] = array_map('array_filter', $arr['resultats']);
ksort($arr['resultats']);
}
 
public function clefsIdentiques($e, $r, $url) {
$e = array_map(function($a) { return intval(trim($a, '"')); }, array_keys($e['resultats']));
sort($e, SORT_NUMERIC);
$r = array_map(function($a) { return intval(trim($a, '"')); }, array_keys($r['resultats']));
sort($r, SORT_NUMERIC);
$this->assertEquals($e, $r, "Différences dans les clefs du tableau, $url");
}
 
// obs-1048891-masque.ns=Fleur+violette-masque.comune=Arette.data.json
// test la présence des commentaires en général
 
// obs-1047949-masque.ns=Echium+wildpretii+Pearson-masque.commune=Vilaflor.data.json
// test la présence des commentaires parents: "1047949"[commentaires][7730][nb_commentaires] == 1 ?
 
// obs-1043671-masque.ns=plante+rose-masque.departement=38451
// idem
}
/tags/v1.1-helium/services/tests/0.1/observations/obs-1047949-masque.ns=Echium+wildpretii+Pearson-masque.commune=Vilaflor.data.json
New file
0,0 → 1,0
{"entete":{"masque":"masque.ns=Echium wildpretii Pearson&masque.commune=Vilaflor","total":1,"depart":0,"limite":10},"resultats":{"\"1047949\"":{"id_observation":"1047949","date_observation":"2013-05-23 00:00:00","date_transmission":"2013-09-19 00:20:22","determination.famille":null,"determination.ns":"Echium wildpretii Pearson ex Hook.f.","determination.nn":null,"determination.nt":null,"observateur":"pdesnos45@free.fr","id_zone_geo":null,"zone_geo":"Vilaflor - Tenerife - Espagne","lieudit":"Caldeira du Teide","station":null,"milieu":"Sable","auteur.nom":"DESNOS","auteur.prenom":"Pat","auteur.id":"22894","mots_cles_texte":"","commentaire":null,"images":[{"id_image":"187515","date":"2013-05-23 12:17:54","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000187515XL.jpg","hauteur":"964"},{"id_image":"187516","date":"2013-05-23 12:16:36","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000187516XL.jpg","hauteur":"964"},{"id_image":"187517","date":"2013-05-23 12:17:46","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000187517XL.jpg","hauteur":"963"},{"id_image":"187518","date":"2013-05-23 12:18:13","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000187518XL.jpg","hauteur":"964"},{"id_image":"187519","date":"2013-05-23 12:18:19","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000187519XL.jpg","hauteur":"962"},{"id_image":"187520","date":"2013-05-23 12:20:34","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000187520XL.jpg","hauteur":"963"}],"commentaires":{"7730":{"nb_commentaires":"1","id_commentaire":"7730","observation":"1047949","proposition":"0","id_parent":"0","auteur.id":"22894","auteur.nom":"DESNOS","auteur.prenom":"Pat","auteur.courriel":"pdesnos45@free.fr","date":"2013-09-20 11:14:33","nom_sel":"Echium wildpretii Pearson ex Hook.f.","proposition_initiale":"1","votes":{"9451":{"vote.id":"9451","proposition.id":"7730","auteur.id":"3c6ef2d001a39ff75df2327b86d3666b","vote":"1","date":"2013-09-20 11:14:33"}}}}}}}
/tags/v1.1-helium/services/tests/0.1/observations/obs-1043671-masque.ns=plante+rose-masque.departement=38451.data.json
New file
0,0 → 1,0
{"entete":{"masque":"masque.ns=plante rose&masque.departement=38451","total":1,"depart":0,"limite":10},"resultats":{"\"1043671\"":{"id_observation":"1043671","date_observation":"2013-09-06 00:00:00","date_transmission":"2013-09-09 21:14:23","determination.famille":"","determination.ns":"plante rose","determination.nn":"0","determination.nt":"0","observateur":"mhusson.bonetti@hotmail.fr","id_zone_geo":"INSEE-C:38451","zone_geo":"Saint-Romain-de-Jalionas","lieudit":"","station":"","milieu":"","auteur.nom":"HUSSON","auteur.prenom":"Margaux","auteur.id":"20497","mots_cles_texte":"Projets coop\u00e9ratifs,WidgetSaisie","commentaire":"","images":[{"id_image":"185842","date":"2013-09-06 19:26:55","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000185842XL.jpg","hauteur":"3000"}],"commentaires":{"7502":{"nb_commentaires":"0","id_commentaire":"7502","observation":"1043671","proposition":"0","id_parent":"0","auteur.id":"20497","auteur.nom":"HUSSON","auteur.prenom":"Margaux","auteur.courriel":"mhusson.bonetti@hotmail.fr","date":"2013-09-10 10:43:15","nom_sel":"plante rose","nom_sel_nn":"0","nom_ret_nn":"0","proposition_initiale":"1"},"7506":{"nb_commentaires":"3","id_commentaire":"7506","observation":"1043671","proposition":"0","id_parent":"0","auteur.id":"11851","auteur.nom":"GO\u00cbAU","auteur.prenom":"Herv\u00e9","auteur.courriel":"herve.goeau@inria.fr","date":"2013-09-10 12:04:58","nom_sel":"Silene flos-cuculi (L.) Clairv.","nom_sel_nn":"75377","proposition_initiale":"0","votes":{"9222":{"vote.id":"9222","proposition.id":"7506","auteur.id":"11851","vote":"0","date":"2013-09-12 16:16:03"},"9260":{"vote.id":"9260","proposition.id":"7506","auteur.id":"13366","vote":"0","date":"2013-09-11 13:00:07"}}},"7560":{"nb_commentaires":"0","id_commentaire":"7560","observation":"1043671","proposition":"0","id_parent":"0","auteur.id":"11851","auteur.nom":"GO\u00cbAU","auteur.prenom":"Herv\u00e9","auteur.courriel":"herve.goeau@inria.fr","date":"2013-09-12 16:15:59","nom_sel":"Centaurea jacea L.","nom_sel_nn":"15248","proposition_initiale":"0","votes":{"9279":{"vote.id":"9279","proposition.id":"7560","auteur.id":"11851","vote":"1","date":"2013-09-12 16:18:07"}}}}}}}
/tags/v1.1-helium/services/tests/0.1/observations/obs-1048891-masque.ns=Fleur+violette-masque.comune=Arette.data.json
New file
0,0 → 1,0
{"entete":{"masque":"masque.ns=Fleur violette&masque.commune=Arette","total":1,"depart":0,"limite":10},"resultats":{"\"1048891\"":{"id_observation":"1048891","date_observation":"0000-00-00 00:00:00","date_transmission":"2013-09-23 18:17:55","determination.famille":"","determination.ns":"Fleur violette","determination.nn":"0","determination.nt":"0","observateur":null,"id_zone_geo":"INSEE-C:64040","zone_geo":"Arette","lieudit":"","station":"","milieu":"","auteur.nom":"","auteur.prenom":"","auteur.id":"0","mots_cles_texte":"aDeterminer,WidgetSaisie,Projets coop\u00e9ratifs","commentaire":"Bonjour, je n'ai pas beaucoup d'information \u00e0 vous donner sur cette fleur car c'est un ami qui m'a donn\u00e9 cette photo \u00e0 d\u00e9terminer et je ne sais pas ce que c'est. Au sol j'ai l'impression que c'est des feuilles de Dryas octopetala. C'est tout ce que je peux vous dire.\n\nMerci","images":[{"id_image":"188102","date":"2012-05-31 08:36:26","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000188102XL.jpg","hauteur":"1920"}],"commentaires":{"7785":{"nb_commentaires":"0","id_commentaire":"7785","observation":"1048891","proposition":"0","id_parent":"0","auteur.id":"0","auteur.nom":"","auteur.prenom":"","auteur.courriel":"","date":"2013-09-24 12:36:53","nom_sel":"Fleur violette","nom_sel_nn":"0","nom_ret_nn":"0","proposition_initiale":"1"},"7786":{"nb_commentaires":"0","id_commentaire":"7786","observation":"1048891","proposition":"0","id_parent":"0","auteur.id":"11851","texte":"je tente ma chance avec cette esp\u00e8ce sans conviction","auteur.nom":"GO\u00cbAU","auteur.prenom":"Herv\u00e9","auteur.courriel":"herve.goeau@inria.fr","date":"2013-09-24 12:36:53","nom_sel":"Jasione crispa (Pourr.) Samp.","nom_sel_nn":"36248","proposition_initiale":"0"},"7804":{"nb_commentaires":"0","id_commentaire":"7804","observation":"1048891","proposition":"0","id_parent":"0","auteur.id":"10104","texte":"Je pense \u00e0 une V\u00e9ronique.\n4 p\u00e9tales, 2 \u00e9tamines ... mais je ne saurais dire laquelle...","auteur.nom":"BECK","auteur.prenom":"Florent","auteur.courriel":"beckflorent@gmail.com","date":"2013-09-24 22:58:12","nom_sel":"Veronica sp.","proposition_initiale":"0"},"7864":{"nb_commentaires":"0","id_commentaire":"7864","observation":"1048891","proposition":"0","id_parent":"0","auteur.id":"23407","texte":"Suite \u00e0 vos commentaire j'ai vu sur internet cette esp\u00e8ce mais qui m'a l'air bien plus velue","auteur.nom":"LABEYRIE","auteur.prenom":"Vincent","auteur.courriel":"vincent.labeyrie@hotmail.fr","date":"2013-09-26 15:21:43","nom_sel":"Jasione crispa subsp. amethystina (Lag. & Rodr.) Tutin","nom_sel_nn":"83547","proposition_initiale":"0"}}}}}
/tags/v1.1-helium/services/tests/0.1/observations/masque=G-masque.type=endiscussion.data.json
New file
0,0 → 1,0
{"entete":{"masque":"masque=G&masque.type%5Bendiscussion%5D=0","total":349,"depart":0,"limite":12,"href.precedent":null,"href.suivant":"http:\/\/eflore?navigation.depart=12&navigation.limite=12&tri=date_transmission&ordre=asc&masque=G&masque.type%5Bendiscussion%5D=0"},"resultats":{"\"16117\"":{"id_observation":"16117","determination.ns":"Ophrys scolopax Cav.","determination.nt":"30471","determination.nn":"75479","determination.famille":"Orchidaceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:34131","zone_geo":"Lauret","date_observation":"2009-05-20 00:00:00","mots_cles_texte":"Mes observations,aurelienperonnet","date_transmission":"2009-09-03 22:54:35","auteur.id":"11623","auteur.prenom":"Gr\u00e9goire","auteur.nom":"DUCH\u00c9","observateur":"gregoire@tela-botanica.org","images":[{"id_image":"6969","date":"2009-05-20 18:09:59","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006969XL.jpg"},{"id_image":"6968","date":"2009-05-20 18:09:28","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006968XL.jpg"},{"id_image":"6970","date":"2009-05-20 18:11:22","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006970XL.jpg"},{"id_image":"6971","date":"2009-05-20 18:13:29","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006971XL.jpg"},{"id_image":"6972","date":"2009-05-20 18:14:22","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006972XL.jpg"},{"id_image":"6973","date":"2009-05-20 18:15:15","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006973XL.jpg"},{"id_image":"6974","date":"2009-05-20 18:15:39","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006974XL.jpg"},{"id_image":"6975","date":"2009-05-20 18:16:15","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006975XL.jpg"},{"id_image":"6976","date":"2009-05-20 18:16:50","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006976XL.jpg"},{"id_image":"6977","date":"2009-05-20 18:16:58","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006977XL.jpg"},{"id_image":"6978","date":"2009-05-20 18:25:52","hauteur":"2304","largeur":"1759","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006978XL.jpg"}],"commentaires":[{"3911":{"nb_commentaires":"0","id_commentaire":"3911","observation":"16117","proposition":"0","id_parent":"0","auteur.id":"11623","auteur.nom":"DUCH\u00c9","auteur.prenom":"Gr\u00e9goire","auteur.courriel":"gregoire@tela-botanica.org","date":"2013-05-13 11:09:03","nom_sel":"Ophrys scolopax Cav.","nom_sel_nn":"75479","nom_ret_nn":"75479","proposition_initiale":"1","votes":{"5151":{"vote.id":"5151","proposition.id":"3911","auteur.id":"11623","vote":"0","date":"2013-05-13 11:09:07"}}}},{"3912":{"nb_commentaires":"0","id_commentaire":"3912","observation":"16117","proposition":"0","id_parent":"0","auteur.id":"11623","texte":"je crois","auteur.nom":"DUCH\u00c9","auteur.prenom":"Gr\u00e9goire","auteur.courriel":"gregoire@tela-botanica.org","date":"2013-05-13 11:09:03","nom_sel":"Ophrys apifera Huds.","nom_sel_nn":"45064","proposition_initiale":"0","votes":{"5150":{"vote.id":"5150","proposition.id":"3912","auteur.id":"11623","vote":"1","date":"2013-05-13 11:09:06"}}}}]},"\"15282\"":{"id_observation":"15282","determination.ns":"Mespilus germanica L.","determination.nt":"4763","determination.nn":"42397","determination.famille":"Rosaceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:30033","zone_geo":"Beauvoisin","lieudit":"La Passeronne","station":"43\u00b043'02.2\"N 04\u00b019'02.2\"E","date_observation":"2009-08-06 00:00:00","date_transmission":"2010-11-04 15:46:31","auteur.id":"7303","auteur.prenom":"Ruddy","auteur.nom":"BENEZET","observateur":"ruddy.benezet@gmail.com","images":[{"id_image":"6410","date":"0000-00-00 00:00:00","hauteur":"1494","largeur":"1528","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006410XL.jpg"},{"id_image":"6409","date":"0000-00-00 00:00:00","hauteur":"1918","largeur":"1719","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006409XL.jpg"},{"id_image":"6408","date":"0000-00-00 00:00:00","hauteur":"2162","largeur":"1371","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006408XL.jpg"},{"id_image":"6407","date":"0000-00-00 00:00:00","hauteur":"3510","largeur":"2226","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006407XL.jpg"},{"id_image":"6406","date":"0000-00-00 00:00:00","hauteur":"3092","largeur":"1975","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006406XL.jpg"},{"id_image":"6405","date":"0000-00-00 00:00:00","hauteur":"3057","largeur":"1989","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006405XL.jpg"},{"id_image":"6404","date":"0000-00-00 00:00:00","hauteur":"1755","largeur":"1275","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006404XL.jpg"},{"id_image":"6881","date":"0000-00-00 00:00:00","hauteur":"1755","largeur":"1275","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006881XL.jpg"},{"id_image":"6882","date":"0000-00-00 00:00:00","hauteur":"2739","largeur":"1509","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006882XL.jpg"},{"id_image":"6883","date":"0000-00-00 00:00:00","hauteur":"2671","largeur":"1995","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006883XL.jpg"},{"id_image":"6884","date":"0000-00-00 00:00:00","hauteur":"3201","largeur":"2376","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006884XL.jpg"},{"id_image":"6885","date":"0000-00-00 00:00:00","hauteur":"2559","largeur":"2374","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006885XL.jpg"},{"id_image":"6886","date":"0000-00-00 00:00:00","hauteur":"2466","largeur":"2376","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006886XL.jpg"},{"id_image":"6887","date":"0000-00-00 00:00:00","hauteur":"2829","largeur":"1539","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006887XL.jpg"},{"id_image":"6888","date":"0000-00-00 00:00:00","hauteur":"3254","largeur":"1495","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006888XL.jpg"},{"id_image":"6889","date":"0000-00-00 00:00:00","hauteur":"2933","largeur":"1969","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006889XL.jpg"},{"id_image":"6890","date":"0000-00-00 00:00:00","hauteur":"2994","largeur":"2376","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006890XL.jpg"}],"commentaires":[{"3937":{"nb_commentaires":"0","id_commentaire":"3937","observation":"15282","proposition":"0","id_parent":"0","auteur.id":"7303","auteur.nom":"BENEZET","auteur.prenom":"Ruddy","auteur.courriel":"ruddy.benezet@gmail.com","date":"2013-05-13 22:49:10","nom_sel":"Mespilus germanica L.","nom_sel_nn":"42397","nom_ret_nn":"42397","proposition_initiale":"1"}},{"3938":{"nb_commentaires":"0","id_commentaire":"3938","observation":"15282","proposition":"0","id_parent":"0","auteur.id":"121","auteur.nom":"BARTH\u00c9L\u00c9MY","auteur.prenom":"Daniel","auteur.courriel":"daniel.barthelemy@cirad.fr","date":"2013-05-13 22:49:10","nom_sel":"Eriobotrya japonica (Thunb.) Lindl.","nom_sel_nn":"24979","proposition_initiale":"0"}}]},"\"167375\"":{"id_observation":"167375","determination.ns":"Carduus tenuiflorus Curtis","determination.nt":"545","determination.nn":"13358","determination.famille":"Asteraceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:84007","zone_geo":"Avignon","lieudit":"Avenue de Tarascon","station":"Culture abandonn\u00e9e","milieu":"Prairie","date_observation":"2009-05-03 00:00:00","mots_cles_texte":"Vigie-Flore,Maille 4202-G","date_transmission":"2010-12-28 23:23:13","auteur.id":"5","auteur.prenom":"Daniel","auteur.nom":"MATHIEU","observateur":"dmathieu@tela-botanica.org","images":[{"id_image":"15974","date":"2009-05-03 10:49:16","hauteur":"800","largeur":"535","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000015974XL.jpg"}],"commentaires":[{"3465":{"nb_commentaires":"0","id_commentaire":"3465","observation":"167375","proposition":"0","id_parent":"0","auteur.id":"5","auteur.nom":"MATHIEU","auteur.prenom":"Daniel","auteur.courriel":"dmathieu@tela-botanica.org","date":"2013-04-28 01:35:25","nom_sel":"Carduus tenuiflorus Curtis","nom_sel_nn":"13358","nom_ret_nn":"13358","proposition_initiale":"1","votes":{"4479":{"vote.id":"4479","proposition.id":"3465","auteur.id":"7163","vote":"0","date":"2013-04-28 01:35:28"}}}},{"3466":{"nb_commentaires":"0","id_commentaire":"3466","observation":"167375","proposition":"0","id_parent":"0","auteur.id":"7163","auteur.nom":"MERCIER","auteur.prenom":"David","auteur.courriel":"davidpmercier@yahoo.fr","date":"2013-04-28 01:35:25","nom_sel":"Carduus pycnocephalus L.","nom_sel_nn":"75026","proposition_initiale":"0"}}]},"\"350814\"":{"id_observation":"350814","determination.ns":"Gagea granatelli (Parl.) Parl.","determination.nt":"6315","determination.nn":"28634","determination.famille":"Liliaceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:34129","zone_geo":"Lattes","lieudit":"Mas Mannier","date_observation":"2005-03-01 00:00:00","date_transmission":"2011-08-04 11:20:23","auteur.id":"16995","auteur.prenom":"Christophe","auteur.nom":"BERNIER","observateur":"christophe.bernier@tela-botanica.org","images":[{"id_image":"39928","date":"2005-03-08 17:47:39","hauteur":"1536","largeur":"2048","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000039928XL.jpg"},{"id_image":"39927","date":"2005-03-08 17:41:21","hauteur":"1536","largeur":"2048","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000039927XL.jpg"}],"commentaires":[{"1142":{"nb_commentaires":"0","id_commentaire":"1142","observation":"350814","proposition":"0","id_parent":"0","auteur.id":"44","texte":"la gag\u00e9e des garrigues calcaires autour de Montpellier est G. lacaitae. G. granatelli pousse plus \u00e0 l'ouest, dans le Minervois","auteur.nom":"GIROD","auteur.prenom":"Christophe","auteur.courriel":"chrisgir2@yahoo.fr","date":"2013-02-04 20:38:15","nom_sel":"Gagea lacaitae A.Terracc.","proposition_initiale":"0"}},{"1150":{"nb_commentaires":"0","id_commentaire":"1150","observation":"350814","proposition":"0","id_parent":"0","auteur.id":"16995","auteur.nom":"BERNIER","auteur.prenom":"Christophe","auteur.courriel":"christophe.bernier@tela-botanica.org","date":"2011-08-04 11:20:23","nom_sel":"Gagea granatelli (Parl.) Parl.","nom_sel_nn":"28634","nom_ret_nn":"28634","proposition_initiale":"1","votes":{"1434":{"vote.id":"1434","proposition.id":"1150","auteur.id":"44","vote":"0","date":"2013-02-04 20:40:41"},"1564":{"vote.id":"1564","proposition.id":"1150","auteur.id":"389470bbca344f8cdc4905d2c791395b","vote":"0","date":"2013-02-14 16:11:42"}}}}]},"\"350815\"":{"id_observation":"350815","determination.ns":"Gagea granatelli (Parl.) Parl.","determination.nt":"6315","determination.nn":"28634","determination.famille":"Liliaceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:34129","zone_geo":"Lattes","lieudit":"Mas Mannier","date_observation":"2005-03-08 00:00:00","date_transmission":"2011-08-04 11:20:23","auteur.id":"16995","auteur.prenom":"Christophe","auteur.nom":"BERNIER","observateur":"christophe.bernier@tela-botanica.org","images":[{"id_image":"39930","date":"0000-00-00 00:00:00","hauteur":"1173","largeur":"1969","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000039930XL.jpg"},{"id_image":"39929","date":"0000-00-00 00:00:00","hauteur":"1224","largeur":"1944","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000039929XL.jpg"}],"commentaires":[{"1151":{"nb_commentaires":"0","id_commentaire":"1151","observation":"350815","proposition":"0","id_parent":"0","auteur.id":"16995","auteur.nom":"BERNIER","auteur.prenom":"Christophe","auteur.courriel":"christophe.bernier@tela-botanica.org","date":"2011-08-04 11:20:23","nom_sel":"Gagea granatelli (Parl.) Parl.","nom_sel_nn":"28634","nom_ret_nn":"28634","proposition_initiale":"1","votes":{"1435":{"vote.id":"1435","proposition.id":"1151","auteur.id":"44","vote":"0","date":"2013-02-04 20:40:47"}}}},{"1152":{"nb_commentaires":"0","id_commentaire":"1152","observation":"350815","proposition":"0","id_parent":"0","auteur.id":"44","texte":"la gag\u00e9e des garrigues calcaires autour de Montpellier est G. lacaitae. G. granatelli pousse plus \u00e0 l'ouest, dans le Minervois","auteur.nom":"GIROD","auteur.prenom":"Christophe","auteur.courriel":"chrisgir2@yahoo.fr","date":"2013-02-04 20:40:56","nom_sel":"Gagea lacaitae A.Terracc.","proposition_initiale":"0"}}]},"\"374880\"":{"id_observation":"374880","determination.ns":"Carduus tenuiflorus Curtis","determination.nt":"545","determination.nn":"13358","determination.famille":"Asteraceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:49117","zone_geo":"La Dagueni\u00e8re","milieu":"bord de rivi\u00e8re","date_observation":"2004-05-29 00:00:00","date_transmission":"2011-10-08 19:00:59","auteur.id":"2143","auteur.prenom":"Augustin","auteur.nom":"ROCHE","observateur":"augustin.roche@gmail.com","images":[{"id_image":"26280","date":"2004-05-29 16:06:11","hauteur":"1600","largeur":"1200","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000026280XL.jpg"},{"id_image":"26368","date":"2004-05-29 16:06:20","hauteur":"1600","largeur":"1200","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000026368XL.jpg"},{"id_image":"26279","date":"2004-05-29 16:06:27","hauteur":"1600","largeur":"1200","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000026279XL.jpg"}],"commentaires":[{"3435":{"nb_commentaires":"0","id_commentaire":"3435","observation":"374880","proposition":"0","id_parent":"0","auteur.id":"2143","auteur.nom":"ROCHE","auteur.prenom":"Augustin","auteur.courriel":"augustin.roche@gmail.com","date":"2013-04-28 01:14:57","nom_sel":"Carduus tenuiflorus Curtis","nom_sel_nn":"13358","nom_ret_nn":"13358","proposition_initiale":"1","votes":{"4451":{"vote.id":"4451","proposition.id":"3435","auteur.id":"7163","vote":"0","date":"2013-04-28 01:14:57"}}}},{"3436":{"nb_commentaires":"0","id_commentaire":"3436","observation":"374880","proposition":"0","id_parent":"0","auteur.id":"7163","texte":"Les fleurons d\u00e9passent nettement les bract\u00e9es, ces derni\u00e8res \u00e9tant tr\u00e8s aran\u00e9euses sur le dos : il s'agit de C. pycnocephalus. Les confusions sont fr\u00e9quentes entre C. pycnocephalus et tenuiflorus, pour cause de flores indiquant des caract\u00e8res peu fiables (tiges ail\u00e9es ou non, capitules regroup\u00e9s en t\u00eates plus ou moins fournies, couleurs de fleurs). La flore des champs cultiv\u00e9s (Jauzein 1995) est plus fiable.","auteur.nom":"MERCIER","auteur.prenom":"David","auteur.courriel":"davidpmercier@yahoo.fr","date":"2013-04-28 01:19:29","nom_sel":"Carduus pycnocephalus L.","nom_sel_nn":"75026","proposition_initiale":"0","votes":{"4467":{"vote.id":"4467","proposition.id":"3436","auteur.id":"7163","vote":"1","date":"2013-04-28 01:28:42"}}}}]},"\"386183\"":{"id_observation":"386183","determination.ns":"Fritillaria meleagris L.","determination.nt":"6305","determination.nn":"28311","determination.famille":"Liliaceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:37242","zone_geo":"Savigny-en-V\u00e9ron","milieu":"prairie humide","date_observation":"2011-04-07 00:00:00","date_transmission":"2011-11-04 15:07:41","auteur.id":"17106","auteur.prenom":"H\u00e9l\u00e8ne","auteur.nom":"LABALTE","observateur":"labalte.h@wanadoo.fr","images":[{"id_image":"50739","date":"2011-04-07 16:34:51","hauteur":"3264","largeur":"2448","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000050739XL.jpg"}],"commentaires":[{"2634":{"nb_commentaires":"0","id_commentaire":"2634","observation":"386183","proposition":"0","id_parent":"0","auteur.id":"17106","auteur.nom":"LABALTE","auteur.prenom":"H\u00e9l\u00e8ne","auteur.courriel":"labalte.h@wanadoo.fr","date":"2011-11-04 15:07:41","nom_sel":"Fritillaria","nom_sel_nn":"100649","nom_ret_nn":"100649","proposition_initiale":"1","votes":{"3499":{"vote.id":"3499","proposition.id":"2634","auteur.id":"20207","vote":"1","date":"2013-04-10 08:55:13"}}}},{"2635":{"nb_commentaires":"0","id_commentaire":"2635","observation":"386183","proposition":"0","id_parent":"0","auteur.id":"20207","auteur.nom":"SUTTER","auteur.prenom":"Claire","auteur.courriel":"jardin-de-claire@orange.fr","date":"2013-04-10 08:55:07","nom_sel":"Fritillaria meleagris L.","proposition_initiale":"0","votes":{"4708":{"vote.id":"4708","proposition.id":"2635","auteur.id":"121","vote":"1","date":"2013-05-01 16:37:25"},"5434":{"vote.id":"5434","proposition.id":"2635","auteur.id":"2819","vote":"1","date":"2013-05-22 14:47:55"}}}}]},"\"629145\"":{"id_observation":"629145","determination.ns":"Gagea granatelli (Parl.) Parl.","determination.nt":"6315","determination.nn":"28634","determination.famille":"Liliaceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:34270","zone_geo":"Saint-Jean-de-V\u00e9das","milieu":"gazon \u00e0 brachypodes en pente douce, sol l\u00e9g\u00e8rement humide","date_observation":"2012-01-17 00:00:00","mots_cles_texte":"module veiller","date_transmission":"2012-01-18 15:45:47","auteur.id":"18043","auteur.prenom":"L\u00e9o","auteur.nom":"PICHON","observateur":"pichon.leo@gmail.com","commentaire":"10 \u00e0 15 individus observ\u00e9s sur une zone tr\u00e8s localis\u00e9e d'environ 1m\u00e8tre carr\u00e9, assez dense en brachypodes","images":[{"id_image":"55446","date":"2012-01-17 16:03:01","hauteur":"1632","largeur":"1224","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000055446XL.jpg"}],"commentaires":[{"1139":{"nb_commentaires":"0","id_commentaire":"1139","observation":"629145","proposition":"0","id_parent":"0","auteur.id":"44","texte":"la gag\u00e9e des garrigues calcaires autour de Montpellier est G. lacaitae. G. granatelli pousse plus \u00e0 l'ouest, dans le Minervois","auteur.nom":"GIROD","auteur.prenom":"Christophe","auteur.courriel":"chrisgir2@yahoo.fr","date":"2013-02-04 20:37:34","nom_sel":"Gagea lacaitae A.Terracc.","proposition_initiale":"0"}},{"1141":{"nb_commentaires":"0","id_commentaire":"1141","observation":"629145","proposition":"0","id_parent":"0","auteur.id":"18043","auteur.nom":"PICHON","auteur.prenom":"L\u00e9o","auteur.courriel":"pichon.leo@gmail.com","date":"2012-01-18 15:45:47","nom_sel":"Gagea granatelli (Parl.) Parl.","nom_sel_nn":"28634","nom_ret_nn":"28634","proposition_initiale":"1","votes":{"1427":{"vote.id":"1427","proposition.id":"1141","auteur.id":"44","vote":"0","date":"2013-02-04 20:37:38"}}}}]},"\"636442\"":{"id_observation":"636442","determination.ns":"Clematis vitalba L.","determination.nt":"4436","determination.nn":"18235","determination.famille":"Ranunculaceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:05061","zone_geo":"Gap","date_observation":"1863-08-16 00:00:00","mots_cles_texte":"Herbier:Inconnu,Liasse:HG8,Herbarium:MPU,Collecteur:inconnu,France","date_transmission":"2012-01-26 09:35:21","auteur.id":"18133","auteur.prenom":"Jean-Pascal","auteur.nom":"MILCENT","observateur":"mpu-jp.milcent@tela-botanica.org","commentaire":"num_part:3;","images":[{"id_image":"55822","date":"2012-01-24 15:05:52","hauteur":"3279","largeur":"2034","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000055822XL.jpg"},{"id_image":"55823","date":"2012-01-24 15:05:52","hauteur":"450","largeur":"921","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000055823XL.jpg"}],"commentaires":[{"2986":{"nb_commentaires":"0","id_commentaire":"2986","observation":"636442","proposition":"0","id_parent":"0","auteur.id":"18133","auteur.nom":"MILCENT","auteur.prenom":"Jean-Pascal","auteur.courriel":"mpu-jp.milcent@tela-botanica.org","date":"2013-04-15 14:18:10","nom_sel":"Clematis vitalba L.","nom_sel_nn":"18235","nom_ret_nn":"18235","proposition_initiale":"1"}},{"2987":{"nb_commentaires":"0","id_commentaire":"2987","observation":"636442","proposition":"0","id_parent":"0","auteur.id":"10229","auteur.nom":"PERONNET","auteur.prenom":"Aur\u00e9lien","auteur.courriel":"aurelien@tela-botanica.org","date":"2013-04-15 14:18:10","nom_sel":"Clematis alpina (L.) Mill.","nom_sel_nn":"75058","proposition_initiale":"0","votes":{"3900":{"vote.id":"3900","proposition.id":"2987","auteur.id":"10229","vote":"1","date":"2013-04-15 14:18:14"}}}}]},"\"719147\"":{"id_observation":"719147","determination.ns":"Sagina apetala Ard.","determination.nt":"2161","determination.nn":"59056","determination.famille":"Caryophyllaceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:85166","zone_geo":"Olonne-sur-Mer","date_observation":"2006-08-30 00:00:00","date_transmission":"2012-02-14 15:47:50","auteur.id":"4967","auteur.prenom":"Mathieu","auteur.nom":"MENAND","observateur":"mathieumenand@yahoo.fr","images":[{"id_image":"20637","date":"2008-04-19 17:06:01","hauteur":"600","largeur":"800","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000020637XL.jpg"}],"commentaires":[{"3416":{"nb_commentaires":"0","id_commentaire":"3416","observation":"719147","proposition":"0","id_parent":"0","auteur.id":"4967","auteur.nom":"MENAND","auteur.prenom":"Mathieu","auteur.courriel":"mathieumenand@yahoo.fr","date":"2013-04-28 00:52:47","nom_sel":"Sagina apetala Ard.","nom_sel_nn":"59056","nom_ret_nn":"59056","proposition_initiale":"1"}},{"3417":{"nb_commentaires":"0","id_commentaire":"3417","observation":"719147","proposition":"0","id_parent":"0","auteur.id":"7163","texte":"C'est la sous-esp\u00e8ce erecta \u00e0 s\u00e9pales courts et \u00e9tal\u00e9s","auteur.nom":"MERCIER","auteur.prenom":"David","auteur.courriel":"davidpmercier@yahoo.fr","date":"2013-04-28 00:52:47","nom_sel":"Sagina apetala subsp. erecta F.Herm.","nom_sel_nn":"59061","proposition_initiale":"0","votes":{"4434":{"vote.id":"4434","proposition.id":"3417","auteur.id":"7163","vote":"1","date":"2013-04-28 00:55:36"}}}}]},"\"720368\"":{"id_observation":"720368","determination.ns":"Sagina apetala Ard.","determination.nt":"2161","determination.nn":"59056","determination.famille":"Caryophyllaceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:31022","zone_geo":"Aucamville","date_observation":"2008-04-10 00:00:00","date_transmission":"2012-02-14 15:47:50","auteur.id":"4967","auteur.prenom":"Mathieu","auteur.nom":"MENAND","observateur":"mathieumenand@yahoo.fr","images":[{"id_image":"20627","date":"2008-04-10 12:01:54","hauteur":"600","largeur":"800","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000020627XL.jpg"}],"commentaires":[{"3420":{"nb_commentaires":"0","id_commentaire":"3420","observation":"720368","proposition":"0","id_parent":"0","auteur.id":"4967","auteur.nom":"MENAND","auteur.prenom":"Mathieu","auteur.courriel":"mathieumenand@yahoo.fr","date":"2013-04-28 01:01:07","nom_sel":"Sagina apetala Ard.","nom_sel_nn":"59056","nom_ret_nn":"59056","proposition_initiale":"1"}},{"3421":{"nb_commentaires":"1","id_commentaire":"3421","observation":"720368","proposition":"0","id_parent":"0","auteur.id":"7163","texte":"Il semble qu'il s'agisse de cette esp\u00e8ce : les s\u00e9pales sont grands, les feuilles larges et la plante est apparemment vivace. Mais la photo est difficile \u00e0 interpr\u00e9ter, donc je reste avec un l\u00e9ger doute.","auteur.nom":"MERCIER","auteur.prenom":"David","auteur.courriel":"davidpmercier@yahoo.fr","date":"2013-04-28 01:01:07","nom_sel":"Sagina procumbens L.","nom_sel_nn":"59112","proposition_initiale":"0","votes":{"4442":{"vote.id":"4442","proposition.id":"3421","auteur.id":"7163","vote":"0","date":"2013-04-28 01:06:35"}}}},{"3428":{"nb_commentaires":"0","id_commentaire":"3428","observation":"720368","proposition":"0","id_parent":"0","auteur.id":"7163","texte":"J'ai d'abord pris cette plante pour S. procumbens : voir le commentaires sous ce nom.","auteur.nom":"MERCIER","auteur.prenom":"David","auteur.courriel":"davidpmercier@yahoo.fr","date":"2013-04-28 01:09:34","nom_sel":"Sagina apetala subsp. erecta F.Herm.","nom_sel_nn":"59061","proposition_initiale":"0","votes":{"4443":{"vote.id":"4443","proposition.id":"3428","auteur.id":"7163","vote":"1","date":"2013-04-28 01:09:37"}}}}]},"\"720471\"":{"id_observation":"720471","determination.ns":"Gagea bohemica (Zauschn.) Schult. & Schult.f.","determination.nt":"10135","determination.nn":"28606","determination.famille":"Liliaceae","determination.referentiel":"bdtfx:v1.01","zone_geo":"Cr\u00e8te","date_observation":"2008-04-23 00:00:00","date_transmission":"2012-02-14 15:47:50","auteur.id":"4967","auteur.prenom":"Mathieu","auteur.nom":"MENAND","observateur":"mathieumenand@yahoo.fr","images":[{"id_image":"22952","date":"2008-04-30 14:42:08","hauteur":"600","largeur":"800","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000022952XL.jpg"},{"id_image":"22965","date":"2008-04-30 14:42:35","hauteur":"600","largeur":"800","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000022965XL.jpg"}],"commentaires":[{"1134":{"nb_commentaires":"0","id_commentaire":"1134","observation":"720471","proposition":"0","id_parent":"0","auteur.id":"4967","auteur.nom":"MENAND","auteur.prenom":"Mathieu","auteur.courriel":"mathieumenand@yahoo.fr","date":"2012-02-14 15:47:50","nom_sel":"Gagea bohemica (Zauschn.) Schult. & Schult.f.","nom_sel_nn":"28606","nom_ret_nn":"28606","proposition_initiale":"1","votes":{"1422":{"vote.id":"1422","proposition.id":"1134","auteur.id":"44","vote":"0","date":"2013-02-04 20:36:18"}}}}]}}}
/tags/v1.1-helium/services/tests/0.1/observations/obs-1048532-complete.data.json
New file
0,0 → 1,0
{"id_observation":"1048532","date_observation":"2013-09-19 00:00:00","date_transmission":"2013-09-19 20:48:46","determination.famille":"Berberidaceae","determination.ns":"Mahonia aquifolium (Pursh) Nutt.","determination.nn":"40676","determination.nt":"1317","determination.referentiel":"bdtfx","observateur":"herve.goeau@inria.fr","id_zone_geo":"INSEE-C:","zone_geo":"Sainte-Genevi\u00e8ve-des-Bois","lieudit":"","station":"","milieu":"","auteur.nom":"GO\u00cbAU","auteur.prenom":"Herv\u00e9","auteur.id":"11851","mots_cles_texte":"plantnet,plantnet-mobile,Projets coop\u00e9ratifs","commentaire":"","images":[{"id_image":"187550","date":"0000-00-00 00:00:00","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000187550XL.jpg","hauteur":"563","protocoles_votes":{"3":{"protocole.id":"3","protocole.intitule":"Capitalisation d'images","protocole.descriptif":"photographier en ext\u00e9rieur les organes (feuille, fruit, tronc, etc.) de plantes et transmettre les photos via le Carnet en ligne.","protocole.tag":"Plantnet","votes":{"120014":{"vote.id":"120014","image.id":"187550","auteur.id":"11851","vote":"3","date":"2013-09-19 23:19:10"}}}}},{"id_image":"187551","date":"0000-00-00 00:00:00","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000187551XL.jpg","hauteur":"563","protocoles_votes":{"3":{"protocole.id":"3","protocole.intitule":"Capitalisation d'images","protocole.descriptif":"photographier en ext\u00e9rieur les organes (feuille, fruit, tronc, etc.) de plantes et transmettre les photos via le Carnet en ligne.","protocole.tag":"Plantnet","votes":{"120013":{"vote.id":"120013","image.id":"187551","auteur.id":"11851","vote":"3","date":"2013-09-19 23:19:08"}}}}},{"id_image":"187552","date":"0000-00-00 00:00:00","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000187552XL.jpg","hauteur":"563","protocoles_votes":{"3":{"protocole.id":"3","protocole.intitule":"Capitalisation d'images","protocole.descriptif":"photographier en ext\u00e9rieur les organes (feuille, fruit, tronc, etc.) de plantes et transmettre les photos via le Carnet en ligne.","protocole.tag":"Plantnet","votes":{"120017":{"vote.id":"120017","image.id":"187552","auteur.id":"11851","vote":"3","date":"2013-09-19 23:19:27"}}}}},{"id_image":"187553","date":"0000-00-00 00:00:00","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000187553XL.jpg","hauteur":"563","protocoles_votes":{"3":{"protocole.id":"3","protocole.intitule":"Capitalisation d'images","protocole.descriptif":"photographier en ext\u00e9rieur les organes (feuille, fruit, tronc, etc.) de plantes et transmettre les photos via le Carnet en ligne.","protocole.tag":"Plantnet","votes":{"120016":{"vote.id":"120016","image.id":"187553","auteur.id":"11851","vote":"3","date":"2013-09-19 23:19:16"}}}}},{"id_image":"187554","date":"0000-00-00 00:00:00","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000187554XL.jpg","hauteur":"563","protocoles_votes":{"3":{"protocole.id":"3","protocole.intitule":"Capitalisation d'images","protocole.descriptif":"photographier en ext\u00e9rieur les organes (feuille, fruit, tronc, etc.) de plantes et transmettre les photos via le Carnet en ligne.","protocole.tag":"Plantnet","votes":{"120015":{"vote.id":"120015","image.id":"187554","auteur.id":"11851","vote":"3","date":"2013-09-19 23:19:13"}}}}}],"commentaires":{"7725":{"id_commentaire":"7725","observation":"1048532","proposition":"0","id_parent":"0","auteur.id":"11851","auteur.nom":"GO\u00cbAU","auteur.prenom":"Herv\u00e9","auteur.courriel":"herve.goeau@inria.fr","date":"2013-09-19 23:25:19","nom_sel":"","nom_sel_nn":"0","nom_ret_nn":"0","proposition_initiale":"1"},"7726":{"id_commentaire":"7726","observation":"1048532","proposition":"0","id_parent":"0","auteur.id":"11851","auteur.nom":"GO\u00cbAU","auteur.prenom":"Herv\u00e9","auteur.courriel":"herve.goeau@inria.fr","date":"2013-09-19 23:25:19","nom_sel":"Mahonia aquifolium (Pursh) Nutt.","nom_sel_nn":"40676","proposition_initiale":"0","votes":{"9447":{"vote.id":"9447","proposition.id":"7726","auteur.id":"11851","vote":"1","date":"2013-09-19 23:25:21"}}}}}
/tags/v1.1-helium/services/tests/0.1/observations/masque.type=endiscussion.data.json
New file
0,0 → 1,0
{"entete":{"masque":"masque.type%5Bendiscussion%5D=0","total":610,"depart":0,"limite":10,"href.precedent":null,"href.suivant":"http:\/\/eflore?navigation.depart=10&navigation.limite=10&tri=date_transmission&ordre=asc&masque.type%5Bendiscussion%5D=0"},"resultats":{"\"8654\"":{"id_observation":"8654","determination.ns":"Pulmonaria officinalis L.","determination.nt":"1453","determination.nn":"54018","determination.famille":"Boraginaceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:80021","zone_geo":"Amiens","station":"Centre ville, jardin.","date_observation":"2008-03-05 00:00:00","date_transmission":"2008-07-18 10:35:51","auteur.id":"7890","auteur.prenom":"Laurent","auteur.nom":"PETIT","observateur":"yanyan80@free.fr","images":[{"id_image":"49865","date":"0000-00-00 00:00:00","hauteur":"1870","largeur":"1320","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000049865XL.jpg"},{"id_image":"49866","date":"2007-03-09 10:39:40","hauteur":"768","largeur":"1024","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000049866XL.jpg"},{"id_image":"49867","date":"2007-03-09 10:43:37","hauteur":"1024","largeur":"768","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000049867XL.jpg"}],"commentaires":[{"957":{"nb_commentaires":"0","id_commentaire":"957","observation":"8654","proposition":"0","id_parent":"0","auteur.id":"7890","auteur.nom":"Petit","auteur.prenom":"Laurent","auteur.courriel":"yanyan80@free.fr","date":"2008-07-18 10:35:51","nom_sel":"Pulmonaria officinalis L.","nom_sel_nn":"54018","nom_ret_nn":"54018","proposition_initiale":"1","votes":{"1253":{"vote.id":"1253","proposition.id":"957","auteur.id":"f85a381e68eda1c1c2e300700735d407","vote":"1","date":"2012-11-29 13:43:06"}}}}]},"\"16117\"":{"id_observation":"16117","determination.ns":"Ophrys scolopax Cav.","determination.nt":"30471","determination.nn":"75479","determination.famille":"Orchidaceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:34131","zone_geo":"Lauret","date_observation":"2009-05-20 00:00:00","mots_cles_texte":"Mes observations,aurelienperonnet","date_transmission":"2009-09-03 22:54:35","auteur.id":"11623","auteur.prenom":"Gr\u00e9goire","auteur.nom":"DUCH\u00c9","observateur":"gregoire@tela-botanica.org","images":[{"id_image":"6969","date":"2009-05-20 18:09:59","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006969XL.jpg"},{"id_image":"6968","date":"2009-05-20 18:09:28","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006968XL.jpg"},{"id_image":"6970","date":"2009-05-20 18:11:22","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006970XL.jpg"},{"id_image":"6971","date":"2009-05-20 18:13:29","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006971XL.jpg"},{"id_image":"6972","date":"2009-05-20 18:14:22","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006972XL.jpg"},{"id_image":"6973","date":"2009-05-20 18:15:15","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006973XL.jpg"},{"id_image":"6974","date":"2009-05-20 18:15:39","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006974XL.jpg"},{"id_image":"6975","date":"2009-05-20 18:16:15","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006975XL.jpg"},{"id_image":"6976","date":"2009-05-20 18:16:50","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006976XL.jpg"},{"id_image":"6977","date":"2009-05-20 18:16:58","hauteur":"4288","largeur":"2848","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006977XL.jpg"},{"id_image":"6978","date":"2009-05-20 18:25:52","hauteur":"2304","largeur":"1759","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006978XL.jpg"}],"commentaires":[{"3911":{"nb_commentaires":"0","id_commentaire":"3911","observation":"16117","proposition":"0","id_parent":"0","auteur.id":"11623","auteur.nom":"DUCH\u00c9","auteur.prenom":"Gr\u00e9goire","auteur.courriel":"gregoire@tela-botanica.org","date":"2013-05-13 11:09:03","nom_sel":"Ophrys scolopax Cav.","nom_sel_nn":"75479","nom_ret_nn":"75479","proposition_initiale":"1","votes":{"5151":{"vote.id":"5151","proposition.id":"3911","auteur.id":"11623","vote":"0","date":"2013-05-13 11:09:07"}}}},{"3912":{"nb_commentaires":"0","id_commentaire":"3912","observation":"16117","proposition":"0","id_parent":"0","auteur.id":"11623","texte":"je crois","auteur.nom":"DUCH\u00c9","auteur.prenom":"Gr\u00e9goire","auteur.courriel":"gregoire@tela-botanica.org","date":"2013-05-13 11:09:03","nom_sel":"Ophrys apifera Huds.","nom_sel_nn":"45064","proposition_initiale":"0","votes":{"5150":{"vote.id":"5150","proposition.id":"3912","auteur.id":"11623","vote":"1","date":"2013-05-13 11:09:06"}}}}]},"\"19507\"":{"id_observation":"19507","determination.ns":"Pulmonaria","determination.nt":"50636","determination.nn":"100636","determination.famille":"Boraginaceae","determination.referentiel":"bdtfx:v1.01","zone_geo":"Saint-Antonin-Noble-Val","lieudit":"Montpalach","date_observation":"2010-04-10 00:00:00","date_transmission":"2010-04-12 15:46:54","auteur.id":"51af35965b5e53f4073081fe2c0c5d94","observateur":"nscotto@club-internet.fr","images":[{"id_image":"12904","date":"2008-11-19 19:06:19","hauteur":"2736","largeur":"3648","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000012904XL.jpg"}],"commentaires":[{"3277":{"nb_commentaires":"0","id_commentaire":"3277","observation":"19507","proposition":"0","id_parent":"0","auteur.id":"0","auteur.nom":"","auteur.prenom":"","auteur.courriel":"","date":"2013-04-22 21:06:41","nom_sel":"Pulmonaria","nom_sel_nn":"100636","nom_ret_nn":"100636","proposition_initiale":"1","votes":{"4546":{"vote.id":"4546","proposition.id":"3277","auteur.id":"4657","vote":"1","date":"2013-04-30 12:34:04"},"5436":{"vote.id":"5436","proposition.id":"3277","auteur.id":"2819","vote":"1","date":"2013-05-22 14:48:34"}}}},{"4644":{"nb_commentaires":"0","id_commentaire":"4644","observation":"19507","proposition":"0","id_parent":"0","auteur.id":"13389","auteur.nom":"SABBAG","auteur.prenom":"Claude","auteur.courriel":"sabbag.claude13@gmail.com","date":"2013-06-04 15:41:57","nom_sel":"Pulmonaria longifolia subsp. longifolia","nom_sel_nn":"54005","proposition_initiale":"0"}}]},"\"15282\"":{"id_observation":"15282","determination.ns":"Mespilus germanica L.","determination.nt":"4763","determination.nn":"42397","determination.famille":"Rosaceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:30033","zone_geo":"Beauvoisin","lieudit":"La Passeronne","station":"43\u00b043'02.2\"N 04\u00b019'02.2\"E","date_observation":"2009-08-06 00:00:00","date_transmission":"2010-11-04 15:46:31","auteur.id":"7303","auteur.prenom":"Ruddy","auteur.nom":"BENEZET","observateur":"ruddy.benezet@gmail.com","images":[{"id_image":"6410","date":"0000-00-00 00:00:00","hauteur":"1494","largeur":"1528","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006410XL.jpg"},{"id_image":"6409","date":"0000-00-00 00:00:00","hauteur":"1918","largeur":"1719","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006409XL.jpg"},{"id_image":"6408","date":"0000-00-00 00:00:00","hauteur":"2162","largeur":"1371","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006408XL.jpg"},{"id_image":"6407","date":"0000-00-00 00:00:00","hauteur":"3510","largeur":"2226","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006407XL.jpg"},{"id_image":"6406","date":"0000-00-00 00:00:00","hauteur":"3092","largeur":"1975","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006406XL.jpg"},{"id_image":"6405","date":"0000-00-00 00:00:00","hauteur":"3057","largeur":"1989","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006405XL.jpg"},{"id_image":"6404","date":"0000-00-00 00:00:00","hauteur":"1755","largeur":"1275","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006404XL.jpg"},{"id_image":"6881","date":"0000-00-00 00:00:00","hauteur":"1755","largeur":"1275","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006881XL.jpg"},{"id_image":"6882","date":"0000-00-00 00:00:00","hauteur":"2739","largeur":"1509","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006882XL.jpg"},{"id_image":"6883","date":"0000-00-00 00:00:00","hauteur":"2671","largeur":"1995","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006883XL.jpg"},{"id_image":"6884","date":"0000-00-00 00:00:00","hauteur":"3201","largeur":"2376","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006884XL.jpg"},{"id_image":"6885","date":"0000-00-00 00:00:00","hauteur":"2559","largeur":"2374","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006885XL.jpg"},{"id_image":"6886","date":"0000-00-00 00:00:00","hauteur":"2466","largeur":"2376","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006886XL.jpg"},{"id_image":"6887","date":"0000-00-00 00:00:00","hauteur":"2829","largeur":"1539","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006887XL.jpg"},{"id_image":"6888","date":"0000-00-00 00:00:00","hauteur":"3254","largeur":"1495","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006888XL.jpg"},{"id_image":"6889","date":"0000-00-00 00:00:00","hauteur":"2933","largeur":"1969","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006889XL.jpg"},{"id_image":"6890","date":"0000-00-00 00:00:00","hauteur":"2994","largeur":"2376","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000006890XL.jpg"}],"commentaires":[{"3937":{"nb_commentaires":"0","id_commentaire":"3937","observation":"15282","proposition":"0","id_parent":"0","auteur.id":"7303","auteur.nom":"BENEZET","auteur.prenom":"Ruddy","auteur.courriel":"ruddy.benezet@gmail.com","date":"2013-05-13 22:49:10","nom_sel":"Mespilus germanica L.","nom_sel_nn":"42397","nom_ret_nn":"42397","proposition_initiale":"1"}},{"3938":{"nb_commentaires":"0","id_commentaire":"3938","observation":"15282","proposition":"0","id_parent":"0","auteur.id":"121","auteur.nom":"BARTH\u00c9L\u00c9MY","auteur.prenom":"Daniel","auteur.courriel":"daniel.barthelemy@cirad.fr","date":"2013-05-13 22:49:10","nom_sel":"Eriobotrya japonica (Thunb.) Lindl.","nom_sel_nn":"24979","proposition_initiale":"0"}}]},"\"167375\"":{"id_observation":"167375","determination.ns":"Carduus tenuiflorus Curtis","determination.nt":"545","determination.nn":"13358","determination.famille":"Asteraceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:84007","zone_geo":"Avignon","lieudit":"Avenue de Tarascon","station":"Culture abandonn\u00e9e","milieu":"Prairie","date_observation":"2009-05-03 00:00:00","mots_cles_texte":"Vigie-Flore,Maille 4202-G","date_transmission":"2010-12-28 23:23:13","auteur.id":"5","auteur.prenom":"Daniel","auteur.nom":"MATHIEU","observateur":"dmathieu@tela-botanica.org","images":[{"id_image":"15974","date":"2009-05-03 10:49:16","hauteur":"800","largeur":"535","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000015974XL.jpg"}],"commentaires":[{"3465":{"nb_commentaires":"0","id_commentaire":"3465","observation":"167375","proposition":"0","id_parent":"0","auteur.id":"5","auteur.nom":"MATHIEU","auteur.prenom":"Daniel","auteur.courriel":"dmathieu@tela-botanica.org","date":"2013-04-28 01:35:25","nom_sel":"Carduus tenuiflorus Curtis","nom_sel_nn":"13358","nom_ret_nn":"13358","proposition_initiale":"1","votes":{"4479":{"vote.id":"4479","proposition.id":"3465","auteur.id":"7163","vote":"0","date":"2013-04-28 01:35:28"}}}},{"3466":{"nb_commentaires":"0","id_commentaire":"3466","observation":"167375","proposition":"0","id_parent":"0","auteur.id":"7163","auteur.nom":"MERCIER","auteur.prenom":"David","auteur.courriel":"davidpmercier@yahoo.fr","date":"2013-04-28 01:35:25","nom_sel":"Carduus pycnocephalus L.","nom_sel_nn":"75026","proposition_initiale":"0"}}]},"\"40099\"":{"id_observation":"40099","determination.ns":"Neotinea ustulata subsp. ustulata","determination.nt":"13044","determination.nn":"78364","determination.famille":"Orchidaceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:30153","zone_geo":"Malons-et-Elze","station":"MDA","milieu":"Prairie humide","date_observation":"2010-05-23 00:00:00","mots_cles_texte":"Orchid\u00e9es","date_transmission":"2011-01-01 18:20:46","auteur.id":"11326","auteur.prenom":"Paul","auteur.nom":"Fabre","observateur":"paul.fabre19@gmail.com","commentaire":"Plante discr\u00e8te, d\u00e9licate et tr\u00e8s esth\u00e9tique","images":[{"id_image":"16423","date":"2010-05-23 13:40:33","hauteur":"2816","largeur":"2112","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000016423XL.jpg"},{"id_image":"16584","date":"2010-05-23 14:01:13","hauteur":"2816","largeur":"2112","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000016584XL.jpg"}],"commentaires":[{"356":{"nb_commentaires":"0","id_commentaire":"356","observation":"40099","proposition":"0","id_parent":"0","auteur.id":"11326","auteur.nom":"Fabre","auteur.prenom":"Paul","auteur.courriel":"paul.fabre19@gmail.com","date":"2011-01-01 18:20:46","nom_sel":"Neotinea ustulata subsp. ustulata","nom_sel_nn":"78364","nom_ret_nn":"78364","proposition_initiale":"1","votes":{"543":{"vote.id":"543","proposition.id":"356","auteur.id":"bd60d1e88277ffd39837715ac37fa11a","vote":"1","date":"2012-11-07 20:34:18"},"712":{"vote.id":"712","proposition.id":"356","auteur.id":"f3bb43f8949a9f87052a39850d570fb5","vote":"1","date":"2012-11-22 13:44:09"},"746":{"vote.id":"746","proposition.id":"356","auteur.id":"075162d89e6afe9fec2093b6a03cb87f","vote":"1","date":"2012-11-22 20:47:54"},"1139":{"vote.id":"1139","proposition.id":"356","auteur.id":"d28354f594fac20684eaee3924fc001f","vote":"1","date":"2012-11-27 17:06:32"},"1150":{"vote.id":"1150","proposition.id":"356","auteur.id":"4323cb26721a24199955441fd4ee6dc4","vote":"1","date":"2012-11-29 09:45:49"},"1506":{"vote.id":"1506","proposition.id":"356","auteur.id":"712aefda23de9dcff28d902d66d20959","vote":"1","date":"2013-02-12 18:11:02"},"1558":{"vote.id":"1558","proposition.id":"356","auteur.id":"20482","vote":"1","date":"2013-02-14 15:57:14"},"1630":{"vote.id":"1630","proposition.id":"356","auteur.id":"7887","vote":"1","date":"2013-02-16 18:08:45"},"2217":{"vote.id":"2217","proposition.id":"356","auteur.id":"d5d4b8ed2629ef534b5087c580520121","vote":"1","date":"2013-03-23 16:38:57"},"4710":{"vote.id":"4710","proposition.id":"356","auteur.id":"121","vote":"1","date":"2013-05-01 16:37:50"}}}}]},"\"19081\"":{"id_observation":"19081","determination.ns":"Spiranthes spiralis (L.) Chevall.","determination.nt":"6567","determination.nn":"65818","determination.famille":"Orchidaceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:34154","zone_geo":"Mauguio","lieudit":"Bois de la Mourre","date_observation":"2008-03-03 00:00:00","date_transmission":"2011-01-09 12:29:27","auteur.id":"12799","auteur.prenom":"Julien","auteur.nom":"BARATAUD","observateur":"julien.barataud@laposte.net","images":[{"id_image":"9815","date":"2008-03-03 18:51:18","hauteur":"1200","largeur":"1600","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000009815XL.jpg"},{"id_image":"9816","date":"2008-03-03 18:51:18","hauteur":"1200","largeur":"1600","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000009816XL.jpg"},{"id_image":"9817","date":"2008-03-03 18:51:09","hauteur":"1600","largeur":"1200","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000009817XL.jpg"}],"commentaires":[{"1567":{"nb_commentaires":"0","id_commentaire":"1567","observation":"19081","proposition":"0","id_parent":"0","auteur.id":"12799","auteur.nom":"BARATAUD","auteur.prenom":"Julien","auteur.courriel":"julien.barataud@laposte.net","date":"0000-00-00 00:00:00","nom_sel":"Spiranthes spiralis (L.) Chevall.","nom_sel_nn":"65818","nom_ret_nn":"65818","proposition_initiale":"0","votes":{"2049":{"vote.id":"2049","proposition.id":"1567","auteur.id":"18748","vote":"0","date":"2013-03-14 15:56:12"}}}}]},"\"313463\"":{"id_observation":"313463","determination.ns":"Urtica urens L.","determination.nt":"5650","determination.nn":"70431","determination.famille":"Urticaceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:83126","zone_geo":"La Seyne-sur-Mer","milieu":"friche","date_observation":"2011-04-10 00:00:00","date_transmission":"2011-04-11 09:32:28","auteur.id":"76","auteur.prenom":"Frederic","auteur.nom":"BOUFFARD","observateur":"facama@orange.fr","images":[{"id_image":"27152","date":"2011-04-09 23:17:59","hauteur":"3240","largeur":"4320","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000027152XL.jpg"}],"commentaires":[{"1523":{"nb_commentaires":"0","id_commentaire":"1523","observation":"313463","proposition":"0","id_parent":"0","auteur.id":"76","auteur.nom":"bouffard","auteur.prenom":"frederic","auteur.courriel":"facama@orange.fr","date":"0000-00-00 00:00:00","nom_sel":"Urtica urens L.","nom_sel_nn":"70431","nom_ret_nn":"70431","proposition_initiale":"0","votes":{"2001":{"vote.id":"2001","proposition.id":"1523","auteur.id":"1356","vote":"0","date":"2013-03-10 10:15:15"},"2218":{"vote.id":"2218","proposition.id":"1523","auteur.id":"d5d4b8ed2629ef534b5087c580520121","vote":"1","date":"2013-03-23 16:39:03"}}}}]},"\"350814\"":{"id_observation":"350814","determination.ns":"Gagea granatelli (Parl.) Parl.","determination.nt":"6315","determination.nn":"28634","determination.famille":"Liliaceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:34129","zone_geo":"Lattes","lieudit":"Mas Mannier","date_observation":"2005-03-01 00:00:00","date_transmission":"2011-08-04 11:20:23","auteur.id":"16995","auteur.prenom":"Christophe","auteur.nom":"BERNIER","observateur":"christophe.bernier@tela-botanica.org","images":[{"id_image":"39928","date":"2005-03-08 17:47:39","hauteur":"1536","largeur":"2048","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000039928XL.jpg"},{"id_image":"39927","date":"2005-03-08 17:41:21","hauteur":"1536","largeur":"2048","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000039927XL.jpg"}],"commentaires":[{"1142":{"nb_commentaires":"0","id_commentaire":"1142","observation":"350814","proposition":"0","id_parent":"0","auteur.id":"44","texte":"la gag\u00e9e des garrigues calcaires autour de Montpellier est G. lacaitae. G. granatelli pousse plus \u00e0 l'ouest, dans le Minervois","auteur.nom":"GIROD","auteur.prenom":"Christophe","auteur.courriel":"chrisgir2@yahoo.fr","date":"2013-02-04 20:38:15","nom_sel":"Gagea lacaitae A.Terracc.","proposition_initiale":"0"}},{"1150":{"nb_commentaires":"0","id_commentaire":"1150","observation":"350814","proposition":"0","id_parent":"0","auteur.id":"16995","auteur.nom":"BERNIER","auteur.prenom":"Christophe","auteur.courriel":"christophe.bernier@tela-botanica.org","date":"2011-08-04 11:20:23","nom_sel":"Gagea granatelli (Parl.) Parl.","nom_sel_nn":"28634","nom_ret_nn":"28634","proposition_initiale":"1","votes":{"1434":{"vote.id":"1434","proposition.id":"1150","auteur.id":"44","vote":"0","date":"2013-02-04 20:40:41"},"1564":{"vote.id":"1564","proposition.id":"1150","auteur.id":"389470bbca344f8cdc4905d2c791395b","vote":"0","date":"2013-02-14 16:11:42"}}}}]},"\"350815\"":{"id_observation":"350815","determination.ns":"Gagea granatelli (Parl.) Parl.","determination.nt":"6315","determination.nn":"28634","determination.famille":"Liliaceae","determination.referentiel":"bdtfx:v1.01","id_zone_geo":"INSEE-C:34129","zone_geo":"Lattes","lieudit":"Mas Mannier","date_observation":"2005-03-08 00:00:00","date_transmission":"2011-08-04 11:20:23","auteur.id":"16995","auteur.prenom":"Christophe","auteur.nom":"BERNIER","observateur":"christophe.bernier@tela-botanica.org","images":[{"id_image":"39930","date":"0000-00-00 00:00:00","hauteur":"1173","largeur":"1969","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000039930XL.jpg"},{"id_image":"39929","date":"0000-00-00 00:00:00","hauteur":"1224","largeur":"1944","binaire.href":"http:\/\/www.tela-botanica.org\/appli:cel-img:000039929XL.jpg"}],"commentaires":[{"1151":{"nb_commentaires":"0","id_commentaire":"1151","observation":"350815","proposition":"0","id_parent":"0","auteur.id":"16995","auteur.nom":"BERNIER","auteur.prenom":"Christophe","auteur.courriel":"christophe.bernier@tela-botanica.org","date":"2011-08-04 11:20:23","nom_sel":"Gagea granatelli (Parl.) Parl.","nom_sel_nn":"28634","nom_ret_nn":"28634","proposition_initiale":"1","votes":{"1435":{"vote.id":"1435","proposition.id":"1151","auteur.id":"44","vote":"0","date":"2013-02-04 20:40:47"}}}},{"1152":{"nb_commentaires":"0","id_commentaire":"1152","observation":"350815","proposition":"0","id_parent":"0","auteur.id":"44","texte":"la gag\u00e9e des garrigues calcaires autour de Montpellier est G. lacaitae. G. granatelli pousse plus \u00e0 l'ouest, dans le Minervois","auteur.nom":"GIROD","auteur.prenom":"Christophe","auteur.courriel":"chrisgir2@yahoo.fr","date":"2013-02-04 20:40:56","nom_sel":"Gagea lacaitae A.Terracc.","proposition_initiale":"0"}}]}}}
/tags/v1.1-helium/services/tests/0.1/ServiceDelPhpUnit.php
New file
0,0 → 1,166
<?php
/**
* Classe contenant des méthodes :
* - d'intialisation des tests,
* - refactorisant le code des tests,
* - facilitant les tests.
*
* @category php 5.4
* @package Tests/Services
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Raphaël Droz <raphael@tela-botanica.org>
* @copyright Copyright (c) 2011, 2013 Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
*/
 
abstract class ServiceDelPhpUnit extends PHPUnit_Framework_TestCase {
 
/** Définir la valeur de cet attribut dans le constructeur de la classe de test.*/
protected $projet = '';
/** Définir la valeur de cet attribut dans le constructeur de la classe de test.*/
protected $service = '';
 
//+------------------------------------------------------------------------------------------------------+
// Intialisation
 
public static function setUpBeforeClass() {
error_reporting(E_ALL);
 
self::chargerFramework();
 
// Enregistrement en première position des autoload de la méthode gérant les classes des services
spl_autoload_register(array(get_class(), 'chargerClasseAuto'));
}
 
public static function chargerClasseAuto($classe) {
if (class_exists($classe)) {
return null;
}
$cheminBase = realpath(__DIR__.'/../../modules/0.1').'/';
$cheminsTests = __DIR__.'/';
$chemins = array($cheminBase, $cheminsTests);
foreach ($chemins as $chemin) {
$chemin = $chemin.$classe.'.php';
if (file_exists($chemin)) {
require_once $chemin;
}
}
}
 
private static function chargerFramework() {
$cheminRacine = realpath(dirname(__FILE__).'/../..').'/';
$framework = $cheminRacine.'framework.php';
if (!file_exists($framework)) {
$e = "Veuillez paramétrer l'emplacement et la version du Framework dans le fichier $framework";
trigger_error($e, E_USER_ERROR);
} else {
// Inclusion du Framework
require_once $framework;
 
// Ajout d'information concernant cette application
Framework::setCheminAppli($cheminRacine);// Obligatoire
}
}
 
//+------------------------------------------------------------------------------------------------------+
// Refactorisation
protected function consulterJson($ressources, $parametres) {
$retourJson = $this->consulterBrut($ressources, $parametres);
$retour = json_decode($retourJson, true);
$url = $this->creerUrl($ressources, $parametres);
$this->assertEquals(JSON_ERROR_NONE, json_last_error(), "Le json contient des erreurs qui bloquent le décodage. Voir : $url\n".print_r($retourJson, true));
return $retour;
}
 
public function consulterDirectJson($json, $url) {
$retour = json_decode($json, true);
$this->assertEquals(JSON_ERROR_NONE,
json_last_error(),
"Le json contient des erreurs qui bloquent le décodage. Voir : $url\n" .
print_r($json, true));
return $retour;
}
 
protected function consulterBrut($ressources, $parametres) {
array_unshift($ressources, $this->service);
array_unshift($ressources, $this->projet);
$projets = new Determinations();
$retourJson = $projets->consulter($ressources, $parametres);
return $retourJson;
}
 
 
protected function creerUrl($ressources, $parametres = []) {
$version = '';
$ressourcesUrl = array();
foreach ($ressources as $ressource) {
$ressourcesUrl[] = $ressource;
}
$ressourcesUrl = count($ressourcesUrl) > 0 ? '/'.implode('/', $ressourcesUrl) : '';
 
$parametresUrl = '';
if (count($parametres) > 0) {
foreach ($parametres as $cle => $valeur) {
$parametresUrl[] = $cle.'='.rawurlencode($valeur);
}
$parametresUrl = '?'.implode('&', $parametresUrl);
}
 
$url = Config::get('url_service').'/'.$version.$this->service.$ressourcesUrl.$parametresUrl;
return $url;
}
 
//+------------------------------------------------------------------------------------------------------+
// Méthodes facilitant les tests
 
/**
* Récupère un bouchon de classe abstraite.
* Comment l'utiliser :
* $classeAstraite = $this->getClasseAbstraite('MaClasse', array('param1', 'param2'));
* $foo = $classeAstraite->methodeConcretePublique();
*
* @param String $classeNom Le nom de la classe
* @param Array $parametres Les paramètres à passer au constructeur.
* @return Object Le bouchon de la classe abstraite
*/
public function getClasseAbstraite($classeNom, Array $parametres) {
$efloreScript = $this->getMockForAbstractClass($classeNom, $parametres);
return $efloreScript;
}
 
/**
* Récupère une méthode privée d'une classe pour tester/documenter.
* Comment l'utiliser :
* MyClass->foo():
* $cls = new MyClass();
* $foo = self::getPrivateMethode($cls, 'foo');
* $foo->invoke($cls, $...);
*
* @param object $objet Une instance de votre classe
* @param string $methode Le nom de la méthode private
* @return ReflectionMethod La méthode demandée
*/
public static function getMethodePrivee($objet, $nomMethode) {
$classe = new ReflectionClass($objet);
$methode = $classe->getMethod($nomMethode);
$methode->setAccessible(true);
return $methode;
}
 
/**
* Récupère une méthode protégée d'une classe pour tester/documenter.
* Comment l'utiliser :
* MyClass->foo():
* $cls = new MyClass();
* $foo = self::getProtectedMethode($cls, 'foo');
* $foo->invoke($cls, $...);
* @param object $objet Une instance de votre classe
* @param string $methode Le nom de la méthode protected
* @return ReflectionMethod La méthode demandée
*/
public static function getMethodeProtegee($objet, $nomMethode) {
return self::getMethodePrivee($objet, $nomMethode);
}
}
?>
/tags/v1.1-helium/services/tests/0.1/images/ImagesTest.php
New file
0,0 → 1,45
<?php
/*
* @author Grégoire DUCHE <gregoire@tela-botanica.org>
* @author Raphaël Droz <raphael@tela-botanica.org>
* @copyright Copyright (c) 2012, 2013 Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
*
* Classe de test pour /del/services/0.1/images
*/
require_once dirname(__FILE__).'/../ServiceDelPhpUnit.php';
 
class ImagesTest extends ServiceDelPhpUnit {
 
const nbResultatsGregoire = 409;
public function testCoherenceResultat() {
$url = $this->creerUrl('images');
$i = new Images();
$retour = $this->consulterDirectJson($i->consulter([], []),
$url);
 
$this->assertArrayHasKey('entete', $retour, "Le json ne contient pas d'attribut : entete. Voir : $url");
$this->assertArrayHasKey('resultats', $retour, "Le json ne contient pas d'attribut : resultat. Voir : $url");
}
 
public function testNbObsEnFonctionDeLauteur() {
$parametres = ['masque.auteur' => 'gregoire'];
$url = $this->creerUrl('images', $parametres);
$i = new Images();
$retour = $this->consulterDirectJson($i->consulter([], $parametres),
$url);
$this->assertEquals(self::nbResultatsGregoire,
$retour['entete']['total'],
'Le total des observations de Grégoire n\'est pas égal à '.self::nbResultatsGregoire);
}
 
 
// del:services:0.1/images?navigation.depart=0&navigation.limite=12&tri=date_observation&ordre=asc
// doit avoir 12 éléments
}
?>
/tags/v1.1-helium/services
New file
Property changes:
Added: svn:ignore
+framework.php
/tags/v1.1-helium/widget/.htaccess
New file
0,0 → 1,13
<files *.ini>
order deny,allow
deny from all
</files>
 
#AddHandler x-httpd-php5 .php
AddDefaultCharset UTF-8
 
RewriteEngine On
# Redirections générale vers le fichier principal de Widget.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*$ index.php/
/tags/v1.1-helium/widget/bibliotheque/WidgetCommun.php
New file
0,0 → 1,405
<?php
abstract class WidgetCommun {
protected $config = null;
protected $parametres = null;
protected $messages = array();
protected $debug = array();
public function __construct($config, $parametres) {
$this->config = $config;
$this->parserFichierIni($config['chemins']['widgetCourantDossier'].'config.ini');
$this->parametres = $parametres;
}
/**
* Parse le fichier ini donné en paramètre
* @param string $fichier_ini nom du fichier ini à parser
* @return boolean true si le fichier ini a été trouvé.
*/
private function parserFichierIni($fichier_ini) {
$retour = false;
if (file_exists($fichier_ini)) {
$ini = parse_ini_file($fichier_ini, true);
$this->fusionner($ini);
$retour = true;
}
return $retour;
}
 
/**
* fusionne un tableau de paramètres avec le tableau de config global
* @param array $ini le tableau à fusionner
*/
private function fusionner(array $ini) {
$this->config = array_merge($this->config, $ini);
}
protected function traiterNomMethodeExecuter($nom) {
$methode = 'executer';
$methode .= str_replace(' ', '', ucwords(str_replace('-', ' ', strtolower($nom))));
return $methode;
}
//+----------------------------------------------------------------------------------------------------------------+
// GESTION des CLASSES CHARGÉES à la DEMANDE
protected function getDao() {
if (! isset($this->dao)) {
$this->dao = new Dao();
}
return $this->dao;
}
//+----------------------------------------------------------------------------------------------------------------+
// GESTION DE MÉTHODES COMMUNES ENTRE LES SERVICES
protected function getUrlImage($id, $format = 'L') {
$url_tpl = $this->config['chemins']['celImgUrlTpl'];
$id = sprintf('%09s', $id).$format;
$url = sprintf($url_tpl, $id);
return $url;
}
protected function encoderMotCle($mot_cle) {
return md5(mb_strtolower($mot_cle));
}
private function protegerMotsCles($mots_cles, $type) {
$separateur = ($type == self::TYPE_IMG) ? ',' : ';' ;
$mots_cles_a_proteger = explode($separateur,rtrim(trim($mots_cles), $separateur));
foreach ($mots_cles_a_proteger as $mot) {
$mots_cles_proteges[] = $this->bdd->quote($mot);
}
$mots_cles = implode(',', $mots_cles_proteges);
return $mots_cles;
}
protected function tronquerCourriel($courriel) {
$courriel = preg_replace('/[^@]+$/i', '...', $courriel);
return $courriel;
}
protected function nettoyerTableau($tableau) {
foreach ($tableau as $cle => $valeur) {
if (is_array($valeur)) {
$valeur = $this->nettoyerTableau($valeur);
} else {
$valeur = $this->nettoyerTexte($valeur);
}
$tableau[$cle] = $valeur;
}
return $tableau;
}
protected function nettoyerTexte($txt) {
$txt = preg_replace('/&(?!([a-z]+|#[0-9]+|#x[0-9][a-f]+);)/i', '&amp;', $txt);
$txt = preg_replace('/^(?:000null|null)$/i', '', $txt);
return $txt;
}
protected function etreVide($valeur) {
$vide = false;
if ($valeur == '' || $valeur == 'null'|| $valeur == '000null' || $valeur == '0') {
$vide = true;
}
return $vide;
}
protected function formaterDate($date_heure_mysql, $format = '%A %d %B %Y à %H:%M') {
$date_formatee = '';
if (!$this->etreVide($date_heure_mysql)) {
$timestamp = $this->convertirDateHeureMysqlEnTimestamp($date_heure_mysql);
$date_formatee = strftime($format, $timestamp);
}
return $date_formatee;
}
 
protected function convertirDateHeureMysqlEnTimestamp($date_heure_mysql){
$val = explode(' ', $date_heure_mysql);
$date = explode('-', $val[0]);
$heure = explode(':', $val[1]);
return mktime((int) $heure[0], (int) $heure[1], (int) $heure[2], (int) $date[1], (int) $date[2], (int) $date[0]);
}
//+----------------------------------------------------------------------------------------------------------------+
// GESTION DE L'IDENTIFICATION et des UTILISATEURS
protected function getAuthIdentifiant() {
$id = (isset($_SERVER['PHP_AUTH_USER'])) ? $_SERVER['PHP_AUTH_USER'] : null;
return $id;
}
protected function getAuthMotDePasse() {
$mdp = (isset($_SERVER['PHP_AUTH_PW'])) ? $_SERVER['PHP_AUTH_PW'] : null;
return $mdp;
}
protected function authentifierAdmin() {
$message_accueil = "Veuillez vous identifier avec votre compte Tela Botanica.";
$message_echec = "Accès limité aux administrateurs du CEL.\n".
"Votre tentative d'identification a échoué.\n".
"Actualiser la page pour essayer à nouveau si vous êtes bien inscrit comme administrateur.";
return $this->authentifier($message_accueil, $message_echec, 'Admin');
}
protected function authentifierUtilisateur() {
$message_accueil = "Veuillez vous identifier avec votre compte Tela Botanica.";
$message_echec = "Accès limité aux utilisateur du CEL.\n".
"Inscrivez vous http://www.tela-botanica.org/page:inscription pour le devenir.\n".
"Votre tentative d'identification a échoué.\n".
"Actualiser la page pour essayer à nouveau si vous êtes déjà inscrit ou contacter 'accueil@tela-botanica.org'.";
return $this->authentifier($message_accueil, $message_echec, 'Utilisateur');
}
private function authentifier($message_accueil, $message_echec, $type) {
$id = $this->getAuthIdentifiant();
if (!isset($id)) {
$this->envoyerAuth($message_accueil, $message_echec);
} else {
if ($type == 'Utilisateur' && $this->getAuthMotDePasse() == 'debug') {
$autorisation = true;
} else {
$methodeAutorisation = "etre{$type}Autorise";
$autorisation = $this->$methodeAutorisation();
}
if ($autorisation == false) {
$this->envoyerAuth($message_accueil, $message_echec);
}
}
return true;
}
protected function etreUtilisateurAutorise() {
$identifiant = $this->getAuthIdentifiant();
$mdp = md5($this->getAuthMotDePasse());
$url = sprintf($this->config['authentification']['serviceUrlTpl'], $identifiant, $mdp);
$json = $this->getDao()->consulter($url);
$existe = json_decode($json);
$autorisation = (isset($existe) && $existe) ? true :false;
return $autorisation;
}
protected function etreAdminAutorise($identifiant) {
$identifiant = $this->getAuthIdentifiant();
$autorisation = ($this->etreUtilisateurAutorise() && $this->etreAdminCel($identifiant)) ? true : false;
return $autorisation;
}
protected function etreAdminCel($courriel) {
$admins = $this->config['authentification']['administrateurs'];
$courriels_autorises = explode(',', $admins);
 
$autorisation = (in_array($courriel, $courriels_autorises)) ? true : false ;
return $autorisation;
}
protected function recupererUtilisateursIdentite(Array $courriels) {
// Récupération des données au format Json
$service = "utilisateur/identite-par-courriel/".implode(',', $courriels);
$url = sprintf($this->config['chemins']['baseURLServicesAnnuaireTpl'], $service);
$json = $this->getDao()->consulter($url);
$utilisateurs = json_decode($json);
foreach ($courriels as $courriel) {
$info = array('id' => null, 'intitule' => '');
if (isset($utilisateurs->$courriel)) {
$info['intitule'] = $utilisateurs->$courriel->intitule;
$info['id'] = $utilisateurs->$courriel->id;
} else {
$info['intitule'] = $this->tronquerCourriel($courriel);
}
$noms[$courriel] = $info;
}
return $noms;
}
//+----------------------------------------------------------------------------------------------------------------+
// GESTION de l'ENVOIE au NAVIGATEUR
 
protected function envoyerJsonp($donnees = null, $encodage = 'utf-8') {
$contenu = $_GET['callback'].'('.json_encode($donnees).');';
$this->envoyer($contenu, 'text/html', $encodage);
}
protected function envoyer($donnees = null, $mime = 'text/html', $encodage = 'utf-8') {
// Traitements des messages d'erreurs et données
if (count($this->messages) != 0) {
header('HTTP/1.1 500 Internal Server Error');
$mime = 'text/html';
$encodage = 'utf-8';
$sortie = '<html>'.
'<head><title>Messages</title></head>'.
'<body><pre>'.implode("\n", $this->messages).'</pre><body>'.
'</html>';
} else {
$sortie = $donnees;
if (is_null($donnees)) {
$sortie = 'OK';
}
}
 
// Gestion de l'envoie du déboguage
$this->envoyerDebogage();
 
// Envoie sur la sortie standard
$this->envoyerContenu($encodage, $mime, $sortie);
}
 
private function envoyerDebogage() {
if (!is_array($this->debug)) {
$this->debug[] = $this->debug;
}
if (count($this->debug) != 0) {
foreach ($this->debug as $cle => $val) {
if (is_array($val)) {
$this->debug[$cle] = print_r($val, true);
}
}
header('X-DebugJrest-Data:'.json_encode($this->debug));
}
}
 
private function envoyerContenu($encodage, $mime, $contenu) {
if (!is_null($mime) && !is_null($encodage)) {
header("Content-Type: $mime; charset=$encodage");
} else if (!is_null($mime) && is_null($encodage)) {
header("Content-Type: $mime");
}
print_r($contenu);
}
private function envoyerAuth($message_accueil, $message_echec) {
header('HTTP/1.0 401 Unauthorized');
header('WWW-Authenticate: Basic realm="'.mb_convert_encoding($message_accueil, 'ISO-8859-1', 'UTF-8').'"');
header('Content-type: text/plain; charset=UTF-8');
print $message_echec;
exit(0);
}
//+----------------------------------------------------------------------------------------------------------------+
// GESTION DES SQUELETTES (PHP, TXT...)
/**
* Méthode prenant en paramètre un tableau associatif, les clés seront recherchées dans le texte pour être
* remplacer par la valeur. Dans le texte, les clés devront être entre accolades : {}
*
* @param String $txt le texte où chercher les motifs.
* @param Array $donnees un tableau associatif contenant les motifs à remplacer.
*
* @return String le texte avec les motifs remplacer par les valeurs du tableau.
*/
protected static function traiterSqueletteTxt($txt, Array $donnees = array()) {
$motifs = array();
$valeurs = array();
foreach ($donnees as $cle => $valeur) {
if (strpos($cle, '{') === false && strpos($cle, '}') === false) {
$motifs = '{'.$cle.'}';
$valeurs = $valeur;
}
}
$txt = str_replace($motifs, $valeurs, $txt);
return $txt;
}
 
/**
* Méthode prenant en paramètre un chemin de fichier squelette et un tableau associatif de données,
* en extrait les variables, charge le squelette et retourne le résultat des deux combinés.
*
* @param String $fichier le chemin du fichier du squelette
* @param Array $donnees un tableau associatif contenant les variables a injecter dans le squelette.
*
* @return boolean false si le squelette n'existe pas, sinon la chaine résultat.
*/
protected static function traiterSquelettePhp($fichier, Array $donnees = array()) {
$sortie = false;
if (file_exists($fichier)) {
// Extraction des variables du tableau de données
extract($donnees);
// Démarage de la bufferisation de sortie
ob_start();
// Si les tags courts sont activés
if ((bool) @ini_get('short_open_tag') === true) {
// Simple inclusion du squelette
include $fichier;
} else {
// Sinon, remplacement des tags courts par la syntaxe classique avec echo
$html_et_code_php = self::traiterTagsCourts($fichier);
// Pour évaluer du php mélangé dans du html il est nécessaire de fermer la balise php ouverte par eval
$html_et_code_php = '?>'.$html_et_code_php;
// Interprétation du html et du php dans le buffer
echo eval($html_et_code_php);
}
// Récupèration du contenu du buffer
$sortie = ob_get_contents();
// Suppression du buffer
@ob_end_clean();
} else {
$msg = "Le fichier du squelette '$fichier' n'existe pas.";
trigger_error($msg, E_USER_WARNING);
}
// Retourne le contenu
return $sortie;
}
 
/**
* Fonction chargeant le contenu du squelette et remplaçant les tags court php (<?= ...) par un tag long avec echo.
*
* @param String $chemin_squelette le chemin du fichier du squelette
*
* @return string le contenu du fichier du squelette php avec les tags courts remplacés.
*/
private static function traiterTagsCourts($chemin_squelette) {
$contenu = file_get_contents($chemin_squelette);
// Remplacement de tags courts par un tag long avec echo
$contenu = str_replace('<?=', '<?php echo ', $contenu);
// Ajout systématique d'un point virgule avant la fermeture php
$contenu = preg_replace("/;*\s*\?>/", "; ?>", $contenu);
return $contenu;
}
//+----------------------------------------------------------------------------------------------------------------+
// UTILITAIRES
/**
* Permet de trier un tableau multi-dimenssionnel en gardant l'ordre des clés.
*
* @param Array $array le tableau à trier
* @param Array $cols tableau indiquant en clé la colonne à trier et en valeur l'ordre avec SORT_ASC ou SORT_DESC
* @author cagret at gmail dot com
* @see http://fr.php.net/manual/fr/function.array-multisort.php Post du 21-Jun-2009 12:38
*/
public static function trierTableauMd($array, $cols) {
$colarr = array();
foreach ($cols as $col => $order) {
$colarr[$col] = array();
foreach ($array as $k => $row) {
$colarr[$col]['_'.$k] = strtolower($row[$col]);
}
}
$params = array();
foreach ($cols as $col => $order) {
$params[] =& $colarr[$col];
$params = array_merge($params, (array)$order);
}
call_user_func_array('array_multisort', $params);
$ret = array();
$keys = array();
$first = true;
foreach ($colarr as $col => $arr) {
foreach ($arr as $k => $v) {
if ($first) {
$keys[$k] = substr($k,1);
}
$k = $keys[$k];
if (!isset($ret[$k])) {
$ret[$k] = $array[$k];
}
$ret[$k][$col] = $array[$k][$col];
}
$first = false;
}
return $ret;
}
}
?>
/tags/v1.1-helium/widget/bibliotheque/Dao.php
New file
0,0 → 1,155
<?php
// declare(encoding='UTF-8');
/**
* Classe modèle spécifique à l'application, donc d'accés au données, elle ne devrait pas être appelée de l'extérieur.
*
* @category php5
* @package Widget
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright 2010 Tela-Botanica
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version SVN: $Id$
*/
class Dao {
const HTTP_URL_REQUETE_SEPARATEUR = '&';
const HTTP_URL_REQUETE_CLE_VALEUR_SEPARATEUR = '=';
private $http_methodes = array('GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS', 'CONNECT', 'TRACE');
protected $parametres = null;
private $url = null;
private $reponse_entetes = null;
//+----------------------------------------------------------------------------------------------------------------+
// ACCESSEURS
public function getReponseEntetes($cle) {
return $this->reponse_entetes;
}
public function getParametre($cle) {
$valeur = (isset($this->parametres[$cle])) ? $this->parametres[$cle] : null;
return $valeur;
}
public function ajouterParametre($cle, $valeur) {
$this->parametres[$cle] = $valeur;
}
public function supprimerParametre($cle) {
unset($this->parametres[$cle]);
}
public function nettoyerParametres() {
$this->parametres = null;
}
//+----------------------------------------------------------------------------------------------------------------+
// MÉTHODES
public function consulter($url) {
$retour = $this->envoyerRequete($url, 'GET');
return $retour;
}
public function ajouter($url, Array $donnees) {
$retour = $this->envoyerRequete($url, 'PUT', $donnees);
return $retour;
}
public function modifier($url, Array $donnees) {
$retour = $this->envoyerRequete($url, 'POST', $donnees);
return $retour;
}
public function supprimer($url) {
$retour = $this->envoyerRequete($url, 'DELETE');
return $retour;
}
public function envoyerRequete($url, $mode, Array $donnees = array()) {
$this->url = $url;
$contenu = false;
if (! in_array($mode, $this->http_methodes)) {
$e = "Le mode de requête '$mode' n'est pas accepté!";
trigger_error($e, E_USER_WARNING);
} else {
if ($mode == 'GET') {
$this->traiterUrlParametres();
}
$contexte = stream_context_create(array(
'http' => array(
'method' => $mode,
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'content' => http_build_query($donnees, null, self::HTTP_URL_REQUETE_SEPARATEUR))));
$flux = @fopen($this->url, 'r', false, $contexte);
if (!$flux) {
$this->reponse_entetes = $http_response_header;
$e = "L'ouverture de l'url '{$this->url}' par la méthode HTTP '$mode' a échoué!";
trigger_error($e, E_USER_WARNING);
} else {
// Informations sur les en-têtes et métadonnées du flux
$this->reponse_entetes = stream_get_meta_data($flux);
// Contenu actuel de $url
$contenu = stream_get_contents($flux);
fclose($flux);
}
$this->traiterEntete();
}
$this->reinitialiser();
return $contenu;
}
private function traiterUrlParametres() {
$parametres = array();
if (count($this->parametres) > 0) {
foreach ($this->parametres as $cle => $valeur) {
$cle = rawurlencode($cle);
$valeur = rawurlencode($valeur);
$parametres[] = $cle.self::HTTP_URL_REQUETE_CLE_VALEUR_SEPARATEUR.$valeur;
}
$url_parametres = implode(self::HTTP_URL_REQUETE_SEPARATEUR, $parametres);
$this->url = $this->url.'?'.$url_parametres;
}
}
private function traiterEntete() {
$infos = $this->analyserEntete();
$this->traiterEnteteDebogage($infos);
}
private function analyserEntete() {
$entetes = $this->reponse_entetes;
$infos = array('date' => null, 'uri' => $this->url, 'debogages' => null);
if (isset($entetes['wrapper_data'])) {
$entetes = $entetes['wrapper_data'];
}
foreach ($entetes as $entete) {
if (preg_match('/^X_REST_DEBOGAGE_MESSAGES: (.+)$/', $entete, $match)) {
$infos['debogages'] = json_decode($match[1]);
}
if (preg_match('/^Date: .+ ([012][0-9]:[012345][0-9]:[012345][0-9]) .*$/', $entete, $match)) {
$infos['date'] = $match[1];
}
}
return $infos;
}
private function traiterEnteteDebogage($entetes_analyses) {
if (isset($entetes['debogages'])) {
$date = $entetes['date'];
$uri = $entetes['uri'];
$debogages = $entetes['debogages'];
foreach ($debogages as $debogage) {
$e = "DEBOGAGE : $date - $uri :\n$debogage";
trigger_error($e, E_USER_NOTICE);
}
}
}
private function reinitialiser() {
$this->nettoyerParametres();
}
}
/tags/v1.1-helium/widget/index.php
New file
0,0 → 1,5
<?php
require 'Widget.php';
$widget = new Widget();
$widget->executer();
?>
/tags/v1.1-helium/widget/widget.ini.defaut.php
New file
0,0 → 1,39
;<?/*
[parametres]
;Memoire maxi pour les services : 128Mo = 134217728 ; 256Mo = 268435456 ; 512Mo = 536870912 ; 1Go = 1073741824
limiteMemoire = "512M"
; Niveau d'erreur PHP
erreurNiveau = 30719 ; E_ALL = 30719
; Séparateur d'url en entrée
argSeparatorInput = "&"
; Indication de la locale (setLocale(LC_ALL, ?)) pour les classes appelées par Widget.php
locale = "fr_FR.UTF-8"
; Indication du fuseau horraire par défaut date_default_timezone_set(?)pour les classes appelées par Widget.php
fuseauHoraire = "Europe/Paris"
 
[chemins]
; Chemins à utiliser dans la méthode autoload des widgets
autoload = "bibliotheque/"
; Dossier contenant les widgets
widgetsDossier = "modules/"
; Dossier contenant le widget demandé construit dynamiquement dans le fichier Widget.php
widgetCourantDossier = ""
; Dossier contenant les fichiers des bibliothèques tierces
bibliothequeDossier = "bibliotheque/"
; Base de l'url servant à appeler les widgets
baseURL = "/widget/"
; URL de base absolue des Widgets du CEL construit dynamiquement dans le fichier WidgetCommun.php
baseURLAbsoluDyn = ""
; URL des services web du CEL sous forme de template à utiliser avec sprintf
baseURLServicesCelTpl = "http://www.tela-botanica.org/service:cel:%s"
; URL des services web du CEL sous forme de template à utiliser avec sprintf
baseURLServicesAnnuaireTpl = "http://www.tela-botanica.org/service:annuaire:%s"
; Squelette d'Url permettant d'afficher une image du CEL (remplace %s par l'id de l'image sans underscore)
celImgUrlTpl = "http://api.tela-botanica.org/img:%s.jpg"
; Squelette d'URL pour les services web d'eFlore.
baseURLServicesEfloreTpl = "http://www.tela-botanica.org/service:eflore:{projetCode}/{apiVersion}/{serviceNom}"
 
[authentification]
serviceUrlTpl = "http://www.tela-botanica.org/client/annuaire_nouveau/actuelle/jrest/TestLoginMdp/%s/%s"
administrateurs = aurelien@tela-botanica.org,david.delon@clapas.net,jpm@tela-botanica.org,marie@tela-botanica.org
;*/?>
/tags/v1.1-helium/widget/modules/vote/squelettes/images/tri_decroissant.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/widget/modules/vote/squelettes/images/tri_decroissant.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/widget/modules/vote/squelettes/images/chargement.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/widget/modules/vote/squelettes/images/chargement.gif
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/widget/modules/vote/squelettes/images/fermeture.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/widget/modules/vote/squelettes/images/fermeture.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/widget/modules/vote/squelettes/images/tri.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/widget/modules/vote/squelettes/images/tri.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/widget/modules/vote/squelettes/images/ouverture.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/widget/modules/vote/squelettes/images/ouverture.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/widget/modules/vote/squelettes/images/tri_croissant.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/widget/modules/vote/squelettes/images/tri_croissant.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/widget/modules/vote/squelettes/images/information.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/widget/modules/vote/squelettes/images/information.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/widget/modules/vote/squelettes/scripts/vote.js
New file
0,0 → 1,162
/**----------------------------------------------------------------------------------------------------------*/
/** Variables globales et initialisation
* Variables crées par php dans le squelettes
*
* var g_idObservation : id de l'observation en cours de consultation
* var g_urlServiceVotes : url du service web des votes à appeler
* var g_urlServiceUtilisateurs : url du service web utilisateur à appeler
* var g_votes : tableau des votes
*
*/
var boutonClique = null;
var g_idUtilisateur = null;
 
$(document).ready(function() {
getIdUtilisateur();
gererEvenementsClicsVotes();
gererEvenementClicImageSecondaire();
});
 
$(document).bind('pageload', function() {
gererEvenementsClicsVotes();
mettreEnValeurVotesUtilisateur();
});
 
function getIdUtilisateur() {
$.getJSON(g_urlServiceUtilisateurs, function(data) {
g_idUtilisateur = data.id_utilisateur;
mettreEnValeurVotesUtilisateur();
});
}
 
function gererEvenementsClicsVotes() {
$('.bouton_vote').unbind('click');
$('.bouton_vote').click(function(event) {
boutonClique = $(this);
voter(getValeurVote());
});
}
 
function gererEvenementClicImageSecondaire() {
$('.image_secondaire').live('click', function(event) {
$('.image_secondaire').removeClass('image_active');
var urlImageSecondaire = $(this).attr('src');
urlImageSecondaireAgrandie = urlImageSecondaire.replace('CRX2S','CRS');
var urlImagePrincipale = $('.image_principale').attr('src');
urlImagePrincipaleMiniature = urlImagePrincipale.replace('CRS','CRX2S');
$(this).addClass('image_active');
$('.image_principale').attr('src', urlImageSecondaireAgrandie);
});
}
 
 
function getValeurVote() {
valeur = 0;
if(boutonClique.hasClass('bouton_vote_oui')) {
valeur = 1;
}
return valeur;
}
 
function getIdProposition() {
var chaineProposition = boutonClique.parent().attr('id');
return chaineProposition.replace('vote_determination_', '');
}
 
 
/**----------------------------------------------------------------------------------------------------------*/
/** Affichage **/
 
function mettreEnValeurBoutonClique() {
boutonClique.parent().find(".bouton_vote").removeClass("bouton_selectionne");
boutonClique.effect("highlight", {}, 500, function() {$(this).addClass("bouton_selectionne");});
}
 
function mettreEnValeurVotesUtilisateur() {
$('.votes_determination').each(function() {
var id_proposition = $(this).attr('id').replace('vote_determination_', '');
if(g_votes[id_proposition] != undefined && g_votes[id_proposition][g_idUtilisateur] != undefined) {
if(g_votes[id_proposition][g_idUtilisateur] == 1) {
$(this).children('.bouton_vote_oui').addClass("bouton_selectionne");
} else {
$(this).children('.bouton_vote_non').addClass("bouton_selectionne");
}
}
});
}
 
function mettreAJourAffichageNbVotes(idProposition) {
affichageVotes = boutonClique.parent().find(".nb_votes");
affichageVotes.each(function() {
if($(this).hasClass("nb_votes_oui")) {
$(this).html(calculerVotes(idProposition,1));
}
if($(this).hasClass("nb_votes_non")) {
$(this).html(calculerVotes(idProposition,0));
}
});
}
 
/**----------------------------------------------------------------------------------------------------------*/
/** Requetes **/
 
function getUrlVoteProposition(idProposition) {
return g_urlServiceVotes+'/'+idProposition+'/vote/';
}
 
function getMethodeRequete(idProposition, idUtilisateur) {
var methode = "PUT";
if(g_votes[idProposition] != undefined && g_votes[idProposition] != null &&
g_votes[idProposition][idUtilisateur] != undefined && g_votes[idProposition][idUtilisateur] != null) {
methode = "POST";
}
return methode;
}
 
function voter(ouiOuNon) {
var idProposition = getIdProposition();
var urlVote = getUrlVoteProposition(idProposition);
var type = getMethodeRequete(idProposition, g_idUtilisateur);
if(!voteEstIdentique(idProposition, g_idUtilisateur, ouiOuNon)) {
$.ajax({
url : urlVote,
type: type,
data: "utilisateur="+g_idUtilisateur+"&valeur="+ouiOuNon
}).done(function(data) {
mettreAjourTableauVotes(idProposition, g_idUtilisateur, ouiOuNon);
mettreAJourAffichageNbVotes(idProposition);
mettreEnValeurBoutonClique();
boutonClique = null;
});
}
}
 
/**----------------------------------------------------------------------------------------------------------*/
/** Mise à jour et accès au tableau des votes **/
 
function mettreAjourTableauVotes(idProposition, idUtilisateur, valeurVote) {
if(g_votes[idProposition] == undefined) {
g_votes[idProposition] = new Array();
}
g_votes[idProposition][idUtilisateur] = valeurVote;
}
 
function calculerVotes(id_proposition, ouiOuNon) {
var nb = 0;
for (var votant in g_votes[id_proposition]) {
if(g_votes[id_proposition][votant] == ouiOuNon) {
nb++;
}
}
return nb;
}
 
function voteEstIdentique(id_proposition, id_utilisateur, ouiOuNon) {
return (g_votes[id_proposition] != undefined &&
g_votes[id_proposition][id_utilisateur] != undefined &&
g_votes[id_proposition][id_utilisateur] == ouiOuNon);
}
/tags/v1.1-helium/widget/modules/vote/squelettes/css/vote.css
New file
0,0 → 1,53
@charset "UTF-8";
/*+-----------------------------------------------------------------------------------------------------------------+*/
/* Widget */
.intitule_determination {
float:left;
}
 
.votes_determination {
float:right;
}
 
.auteur_determination {
font-style:italic;
}
 
.image_secondaire {
height: 40px;
cursor:pointer;
}
 
.nb_votes {
position: relative;
top: -12px;
}
 
.image_active {
border: solid 1px black;
}
 
.bouton_selectionne > * {
background-color: #BBBBBB;
cursor: default;
}
 
.bouton_selectionne {
cursor: default;
}
 
.lien_connexion {
float: right;
}
 
.info_observation {
font-size: 14px;
font-weight: bold;
padding-bottom: 5px;
padding-left: 10px;
padding-top: 5px;
}
 
.images {
text-align: center;
}
/tags/v1.1-helium/widget/modules/vote/squelettes/vote.tpl.html
New file
0,0 → 1,113
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Votez !</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<meta http-equiv="Content-style-type" content="text/css" />
<meta http-equiv="Content-script-type" content="text/javascript" />
<meta http-equiv="Content-language" content="fr" />
<meta name="revisit-after" content="15 days" />
<meta name="robots" content="index,follow" />
<meta name="author" content="Delphine Cauquil, Aurélien Peronnet" />
<meta name="keywords" content="Tela Botanica, photographie, DEL" />
<meta name="description" content="Widget de vote sur les dernières images proposées dans DEL" />
 
<!-- Spécial mobile -->
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<!-- Favicones -->
<link rel="icon" type="image/png" href="http://www.tela-botanica.org/sites/commun/generique/images/favicones/tela_botanica.png" />
<link rel="shortcut icon" type="image/x-icon" href="http://www.tela-botanica.org/sites/commun/generique/images/favicones/tela_botanica.ico" />
<!-- Feuilles de styles -->
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" />
<link rel="stylesheet" type="text/css" href="<?=$url_css?>vote.css" media="screen" />
<!-- Javascript : bibliothèques -->
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script type="text/Javascript">
 
</script>
<script src="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>
<!-- attention le script suivant a besoin des variables globales initialisées ci dessous, donc, ne rien utiliser
avant le document.ready() -->
<script src="<?=$url_js?>vote.js"></script>
</head>
<body>
<!-- WIDGET:DEL:VOTE - DEBUT -->
<div data-role="page">
<!-- Variables globales à réinjecter à chaque changement de page
(hors jquery mobile ne recharge pas le contenu du header -->
<script type="text/Javascript">
//<![CDATA[
var g_urlServiceVotes = "<?= $donnees['url_service_votes']; ?>";
var g_urlServiceUtilisateurs = "<?= $donnees['url_service_utilisateurs']; ?>";
var g_idObservation = "<?= $donnees['id_observation']; ?>";
<?= $donnees['votes_js']; ?>;
//]]>
</script>
<!-- /navbar -->
<div data-role="header" data-position="fixed">
<div data-role="navbar" >
<ul>
<?php if($donnees['urls_navigation']['url_precedent'] != null) { ?>
<li><a id="url_precedent" href="<?= $donnees['urls_navigation']['url_precedent']; ?>" data-transition="reverse slide">Précédent</a></li>
<?php } ?>
<?php if($donnees['urls_navigation']['url_suivant'] != null) { ?>
<li><a id="url_suivant" href="<?= $donnees['urls_navigation']['url_suivant']; ?>" data-transition="slide">Suivant</a></li>
<?php } ?>
</ul>
</div>
</div>
<!-- /navbar -->
<div class="del-vote-contenu">
<div class="images">
<div style="height:305px">
<img class="image_principale" src="<?= str_replace('XL', 'CRS', $donnees['url']); ?>" alt="image" />
</div>
<div class="conteneur_image_secondaire">
<?php $premiere_image = true; ?>
<?php foreach($donnees['images'] as $image) : ?>
<img class="image_secondaire <?php if($premiere_image) { echo 'image_active';} ?>" src="<?= str_replace('XL', 'CRX2S', $image['binaire.href']); ?>" alt="image" />
<?php $premiere_image = false; ?>
<?php endforeach ?>
</div>
</div>
<div class="info_observation">
<?= $donnees['titre']; ?>
</div>
<ul class="ui-listview" data-role="listview">
<?php foreach($donnees['liste_votes_determination'] as $vote_determination) : ?>
<li class="ui-li ui-li-static ui-body-c">
<div class="intitule_determination">
<div><?= $vote_determination['nom_sel']; ?></div>
<div class="auteur_determination">Proposé par : <?= $vote_determination['auteur.prenom']; ?> <?= $vote_determination['auteur.nom']; ?></div>
</div>
<div id="vote_determination_<?= $vote_determination['id_commentaire']; ?>" class="votes_determination">
<a href="#" class="bouton_vote bouton_vote_oui" data-role="button" data-mini="true" data-inline="true"> oui</a>
<span class="nb_votes nb_votes_oui">
<?= $vote_determination['votes']['oui']; ?>
</span>
<a href="#" class="bouton_vote bouton_vote_non" data-role="button" data-mini="true" data-inline="true"> non</a>
<span class="nb_votes nb_votes_non">
<?= $vote_determination['votes']['non']; ?>
</span>
</div>
<hr style="visibility:hidden;clear:both" />
</li>
<?php endforeach ?>
</ul>
</div>
<div data-role="footer" data-theme="b">
<div data-role="navbar" >
<ul>
<li><a href="">Aide</a></li>
<li><a href="">Se connecter</a></li>
</ul>
</div>
</div>
</div>
<!-- WIDGET:DEL:VOTE - FIN -->
</body>
</html>
/tags/v1.1-helium/widget/modules/vote/squelettes/vote_ajax.tpl.html
New file
0,0 → 1,54
<!-- WIDGET:DEL:VOTE - DEBUT -->
<div id="contenu" data-role="page">
<!-- /navbar -->
<div data-role="header" data-position="fixed">
<div data-role="navbar" >
<ul>
<?php if($donnees['urls_navigation']['url_precedent'] != null) { ?>
<li><a href="<?= $donnees['urls_navigation']['url_precedent']; ?>" class="ui-btn-active">Précédent</a></li>
<?php } ?>
<?php if($donnees['urls_navigation']['url_suivant'] != null) { ?>
<li><a href="<?= $donnees['urls_navigation']['url_suivant']; ?>">Suivant</a></li>
<?php } ?>
</ul>
</div>
</div>
<!-- /navbar -->
<div class="del-vote-contenu">
<img id="image_principale" src="<?= str_replace('XL', 'CRS', $donnees['url']); ?>" alt="image" />
<div class="conteneur_image_secondaire">
<?php $premiere_image = true; ?>
<?php foreach($donnees['images'] as $image) : ?>
<img class="image_secondaire <?php if($premiere_image) { echo 'image_active';} ?>" src="<?= str_replace('XL', 'CRX2S', $image['binaire.href']); ?>" alt="image" />
<?php $premiere_image = false; ?>
<?php endforeach ?>
</div>
<div class="info_observation">
<?= $donnees['titre']; ?>
</div>
<ul class="ui-listview" data-role="listview">
<?php foreach($donnees['liste_votes_determination'] as $vote_determination) : ?>
<li class="ui-li ui-li-static ui-body-c">
<div class="intitule_determination">
<div><?= $vote_determination['nom_sel']; ?></div>
<div class="auteur_determination">Proposé par : <?= $vote_determination['auteur.prenom']; ?> <?= $vote_determination['auteur.nom']; ?></div>
</div>
<div id="vote_determination_<?= $vote_determination['id_commentaire']; ?>" class="votes_determination">
<a href="#" class="bouton_vote bouton_vote_oui" data-role="button" data-mini="true" data-inline="true"> oui</a>
<span class="nb_votes nb_votes_oui">
<?= $vote_determination['votes']['oui']; ?>
</span>
<a href="#" class="bouton_vote bouton_vote_non" data-role="button" data-mini="true" data-inline="true"> non</a>
<span class="nb_votes nb_votes_non">
<?= $vote_determination['votes']['non']; ?>
</span>
</div>
<hr style="visibility:hidden;clear:both" />
</li>
<?php endforeach ?>
</ul>
</div>
<div data-role="footer" data-theme="b" data-position="fixed">
</div>
</div>
<!-- WIDGET:DEL:VOTE - FIN -->
/tags/v1.1-helium/widget/modules/vote/squelettes/aide.tpl.html
New file
0,0 → 1,60
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Votez !</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<meta http-equiv="Content-style-type" content="text/css" />
<meta http-equiv="Content-script-type" content="text/javascript" />
<meta http-equiv="Content-language" content="fr" />
<meta name="revisit-after" content="15 days" />
<meta name="robots" content="index,follow" />
<meta name="author" content="Delphine Cauquil, Aurélien Peronnet" />
<meta name="keywords" content="Tela Botanica, photographie, DEL" />
<meta name="description" content="Widget de vote sur les dernières images proposées dans DEL" />
 
<!-- Spécial mobile -->
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<!-- Favicones -->
<link rel="icon" type="image/png" href="http://www.tela-botanica.org/sites/commun/generique/images/favicones/tela_botanica.png" />
<link rel="shortcut icon" type="image/x-icon" href="http://www.tela-botanica.org/sites/commun/generique/images/favicones/tela_botanica.ico" />
<!-- Feuilles de styles -->
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" />
<link rel="stylesheet" type="text/css" href="<?=$url_css?>vote.css" media="screen" />
<!-- Javascript : bibliothèques -->
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script type="text/Javascript">
//<![CDATA[
$(document).bind("mobileinit", function(){
$.extend( $.mobile , {
ajaxEnabled: false
});
});
//]]>
</script>
<script src="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>
<script src="<?=$url_js?>vote.js"></script>
</head>
<body>
<!-- WIDGET:DEL:VOTE - DEBUT -->
<div data-role="page">
<div class="aide-contenu">
</div>
<div data-role="footer" data-theme="b" data-position="fixed">
<div data-role="navbar" >
<ul>
<li><a href="">Aide</a></li>
<li><a href="">Se connecter</a></li>
</ul>
</div>
</div>
</div>
<!-- WIDGET:DEL:VOTE - FIN -->
</body>
</html>
/tags/v1.1-helium/widget/modules/vote/Vote.php
New file
0,0 → 1,208
<?php
// declare(encoding='UTF-8');
/**
* Service affichant les dernières photo publiques du CEL ouvrable sous forme de diaporama.
* Encodage en entrée : utf8
* Encodage en sortie : utf8
*
* Cas d'utilisation et documentation :
* @link http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=AideCELWidgetPhoto
*
* Paramètres :
* ===> extra = booléen (1 ou 0) [par défaut : 1]
* Affiche / Cache la vignette en taille plus importante au bas du widget.
* ===> vignette = [0-9]+,[0-9]+ [par défaut : 4,3]
* Indique le nombre de vignette par ligne et le nombre de ligne.
*
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
* @copyright Copyright (c) 2010, Tela Botanica (accueil@tela-botanica.org)
*/
class Vote extends WidgetCommun {
const DS = DIRECTORY_SEPARATOR;
const SERVICE_DEFAUT = 'photo';
private $ce_img_url_tpl = null;
private $del_url_service_tpl = null;
private $id_observation_suivant = null;
private $id_observation_precedent = null;
private $id_observation = null;
/**
* Méthode appelée par défaut pour charger ce widget.
*/
public function executer() {
$this->del_url_service_tpl = $this->config['vote']['baseURLServicesDelTpl'];
$this->ce_img_url_tpl = $this->config['vote']['celImgUrlTpl'];
$this->collecterParametres();
$ids_observations = $this->obtenirIdsObservation();
$donnees = $this->obtenirDonnees($this->id_observation);
 
$widget['donnees']['id_observation'] = $this->id_observation;
$widget['donnees']['titre'] = $this->construireTitreImage($donnees);
$widget['donnees']['url'] = $this->obtenirUrlImage($donnees['images']);
$widget['donnees']['images'] = $donnees['images'];
$widget['donnees']['liste_votes_determination'] = $this->formaterDeterminations($donnees);
$widget['donnees']['url_css'] = sprintf($this->config['chemins']['baseURLAbsoluDyn'], 'modules/vote/squelettes/css/');
$widget['donnees']['url_js'] = sprintf($this->config['chemins']['baseURLAbsoluDyn'], 'modules/vote/squelettes/scripts/');
$widget['donnees']['votes_js'] = $this->convertirTableauVotesEnJs($donnees['commentaires']);
$widget['donnees']['url_service_votes'] = $this->del_url_service_tpl.'observations/'.$this->id_observation;
$widget['donnees']['url_service_utilisateurs'] = $this->del_url_service_tpl.'utilisateurs/';
$widget['donnees']['urls_navigation'] = $this->construireUrlsSuivantesEtPrecedentes($ids_observations);
if (isset($this->parametres['mode']) && $this->parametres['mode'] == 'ajax') {
$squelette = dirname(__FILE__).self::DS.'squelettes'.self::DS.'vote_ajax.tpl.html';
} else {
$squelette = dirname(__FILE__).self::DS.'squelettes'.self::DS.'vote.tpl.html';
}
$contenu = $this->traiterSquelettePhp($squelette, $widget['donnees']);
$this->envoyer($contenu);
}
private function collecterParametres() {
$this->id_observation = (isset($_GET['id_observation'])) ? $_GET['id_observation'] : null;
unset($_GET['id_observation']);
$this->parametres = $_GET;
}
private function convertirParametresEnChaineRequeteService() {
$requete = '';
$mapping = $this->config['mapping_masque'];
if(!empty($this->parametres)) {
foreach ($this->parametres as $parametre=>$valeur) {
if (isset($mapping[$parametre])) {
$requete .= '&'.$mapping[$parametre].'='.urlencode($valeur);
}
}
}
return $requete;
}
private function convertirParametresEnChaineRequete() {
$requete = str_replace('masque_','masque.',http_build_query($this->parametres));
if(!empty($this->parametres)) {
$requete = '&'.$requete;
}
return $requete;
}
private function obtenirIdsObservation() {
$ids = json_decode(file_get_contents($this->del_url_service_tpl.'observations?retour.format=widget'.$this->convertirParametresEnChaineRequeteService()), true);
if($this->id_observation == null) {
$this->id_observation = $ids['resultats'][0];
}
return $ids['resultats'];
}
private function obtenirUrlBaseWidget() {
return $this->config['chemins']['baseURL'].'vote';
}
private function construireUrlsSuivantesEtPrecedentes($tableau_id_observation) {
$indices_id_obs = array_flip($tableau_id_observation);
$indice_obs_courante = $indices_id_obs[$this->id_observation];
$url_base = $this->obtenirUrlBaseWidget();
$indice_predecent = isset($tableau_id_observation[$indice_obs_courante - 1]) ? $tableau_id_observation[$indice_obs_courante - 1] : '';
$indice_suivant = isset($tableau_id_observation[$indice_obs_courante + 1]) ? $tableau_id_observation[$indice_obs_courante + 1] : '';
$url_suivant = isset($tableau_id_observation[$indice_obs_courante + 1]) ? $url_base.'?id_observation='.$tableau_id_observation[$indice_obs_courante + 1].$this->convertirParametresEnChaineRequete() : null;
$url_precedent = isset($tableau_id_observation[$indice_obs_courante - 1]) ? $url_base.'?id_observation='.$tableau_id_observation[$indice_obs_courante - 1].$this->convertirParametresEnChaineRequete() : null;
 
return array('url_suivant' => $url_suivant,
'url_precedent' => $url_precedent
);
}
private function obtenirDonnees($id_observation) {
$donnees = json_decode(file_get_contents($this->del_url_service_tpl.'observations/'.$id_observation), true);
return $donnees;
}
private function construireTitreImage($donnees) {
return 'Pris par '.$donnees['auteur.prenom'].' '.$donnees['auteur.nom'].' à '.$donnees['zone_geo'].' le '.$this->formaterDate($donnees['date_observation'],'%d/%m/%Y');
}
private function obtenirUrlImage($images) {
return $images[0]['binaire.href'];
}
private function formaterDeterminations($observation) {
$liste_determinations = $observation['commentaires'];
$liste_determinations_formatees = array();
$creerPropositionAPartirObservation = true;
foreach ($liste_determinations as $determination) {
$determination_formatee = $determination;
if($determination['nom_sel'] != null && $determination['nom_sel'] != '') {
$determination_formatee['votes'] = $this->formaterVotes($determination['votes']);
$liste_determinations_formatees[] = $determination_formatee;
}
if($determination['nom_sel'] == $observation['determination.ns'] &&
$determination['auteur.id'] == $observation['auteur.id']) {
$creerPropositionAPartirObservation = false;
}
}
if($creerPropositionAPartirObservation) {
$liste_determinations_formatees[] = $this->creerDeterminationAPartirObservation($observation);
}
return $liste_determinations_formatees;
}
private function creerDeterminationAPartirObservation($observation) {
$proposition = array("id_commentaire" => "0",
"observation" => $observation['id_observation'],
"proposition" => "0",
"id_parent" => "0",
"auteur.id" => $observation['auteur.id'],
"texte" => null,
"auteur.nom" => $observation['auteur.nom'],
"auteur.prenom" => $observation['auteur.prenom'],
"auteur.courriel" => $observation['observateur'],
"date" => $observation['date_observation'],
"nom_sel" => $observation['determination.ns'],
"votes" => array('oui' => 0, 'non' => 0)
);
return $proposition;
}
private function formaterVotes($liste_votes) {
$liste_votes_formates = array('oui' => 0, 'non' => 0);
foreach($liste_votes as $vote) {
if($vote['vote'] == 1) {
$liste_votes_formates['oui']++;
} else {
$liste_votes_formates['non']++;
}
}
return $liste_votes_formates;
}
private function convertirTableauVotesEnJs($liste_commentaires) {
$tableau_js = "var g_votes = new Array();";
foreach($liste_commentaires as $commentaire) {
$tableau_js .= 'g_votes["'.$commentaire['id_commentaire'].'"] = new Array();';
if(isset($commentaire['votes'])) {
foreach($commentaire['votes'] as $vote) {
$tableau_js .= 'g_votes["'.$commentaire['id_commentaire'].'"]["'.$vote['auteur.id'].'"] = '.$vote['vote'].';';
}
}
}
return $tableau_js;
}
}
?>
/tags/v1.1-helium/widget/modules/vote/config.defaut.ini
New file
0,0 → 1,5
[vote]
; URL des services web du CEL sous forme de template à utiliser avec sprintf
baseURLServicesDelTpl = "http://localhost/del/services/0.1/"
; Squelette d'Url permettant d'afficher une image du CEL (remplace %s par l'id de l'image sans underscore)
celImgUrlTpl = "http://api.tela-botanica.org/img:%s.jpg"
/tags/v1.1-helium/widget/modules/vote/bibliotheque/Cache.php
New file
0,0 → 1,128
<?php
class Cache {
private $actif = null;
private $dossier_stockage = null;
private $duree_de_vie = null;
public function __construct($dossier_stockage = null, $duree_de_vie = null, $activation = true) {
$this->actif = ($activation) ? true : false;
if ($this->actif) {
$this->dossier_stockage = $dossier_stockage;
if (is_null($dossier_stockage)) {
$this->dossier_stockage = self::getDossierTmp();
}
$this->duree_de_vie = $duree_de_vie;
if (is_null($duree_de_vie)) {
$this->duree_de_vie = 3600*24;
}
}
}
public function charger($id) {
$contenu = false;
if ($this->actif) {
$chemin_fichier_cache = $this->dossier_stockage.DIRECTORY_SEPARATOR.$id.'.txt';
if (file_exists($chemin_fichier_cache ) && (time() - @filemtime($chemin_fichier_cache) < $this->duree_de_vie)) {
$contenu = file_get_contents($chemin_fichier_cache);
}
}
return $contenu;
}
public function sauver($id, $contenu) {
if ($this->actif) {
$chemin_fichier_cache = $this->dossier_stockage.DIRECTORY_SEPARATOR.$id.'.txt';
if (!file_exists($chemin_fichier_cache) || (time() - @filemtime($chemin_fichier_cache) > $this->duree_de_vie)) {
$fh = fopen($chemin_fichier_cache,'w+');
if ($fh) {
fputs($fh, $contenu);
fclose($fh);
}
}
}
}
/**
* Détermine le dossier système temporaire et détecte si nous y avons accès en lecture et écriture.
*
* Inspiré de Zend_File_Transfer_Adapter_Abstract & Zend_Cache
*
* @return string|false le chemine vers le dossier temporaire ou false en cas d'échec.
*/
private static function getDossierTmp() {
$dossier_tmp = false;
foreach (array($_ENV, $_SERVER) as $environnement) {
foreach (array('TMPDIR', 'TEMP', 'TMP', 'windir', 'SystemRoot') as $cle) {
if (isset($environnement[$cle])) {
if (($cle == 'windir') or ($cle == 'SystemRoot')) {
$dossier = realpath($environnement[$cle] . '\\temp');
} else {
$dossier = realpath($environnement[$cle]);
}
if (self::etreAccessibleEnLectureEtEcriture($dossier)) {
$dossier_tmp = $dossier;
break 2;
}
}
}
}
if ( ! $dossier_tmp) {
$dossier_televersement_tmp = ini_get('upload_tmp_dir');
if ($dossier_televersement_tmp) {
$dossier = realpath($dossier_televersement_tmp);
if (self::etreAccessibleEnLectureEtEcriture($dossier)) {
$dossier_tmp = $dossier;
}
}
}
if ( ! $dossier_tmp) {
if (function_exists('sys_get_temp_dir')) {
$dossier = sys_get_temp_dir();
if (self::etreAccessibleEnLectureEtEcriture($dossier)) {
$dossier_tmp = $dossier;
}
}
}
if ( ! $dossier_tmp) {
// Tentative de création d'un fichier temporaire
$fichier_tmp = tempnam(md5(uniqid(rand(), TRUE)), '');
if ($fichier_tmp) {
$dossier = realpath(dirname($fichier_tmp));
unlink($fichier_tmp);
if (self::etreAccessibleEnLectureEtEcriture($dossier)) {
$dossier_tmp = $dossier;
}
}
}
if ( ! $dossier_tmp && self::etreAccessibleEnLectureEtEcriture('/tmp')) {
$dossier_tmp = '/tmp';
}
if ( ! $dossier_tmp && self::etreAccessibleEnLectureEtEcriture('\\temp')) {
$dossier_tmp = '\\temp';
}
return $dossier_tmp;
}
/**
* Vérifie si le fichier ou dossier est accessible en lecture et écriture.
*
* @param $ressource chemin vers le dossier ou fichier à tester
* @return boolean true si la ressource est accessible en lecture et écriture.
*/
protected static function etreAccessibleEnLectureEtEcriture($ressource){
$accessible = false;
if (is_readable($ressource) && is_writable($ressource)) {
$accessible = true;
}
return $accessible;
}
}
?>
/tags/v1.1-helium/widget/modules/vote
New file
Property changes:
Added: svn:ignore
+config.ini
/tags/v1.1-helium/widget/Widget.php
New file
0,0 → 1,162
<?php
// In : utf8 url_encoded (get et post)
// Out : utf8
/**
* La classe Widget analyser l'url et chage le widget correspondant.
* Format d'url :
* /widget/nom_du_widget?parametres1=ma_valeur1&parametre2=ma_valeur2
* Les widget sont dans des dossiers en minuscule correspondant au nom de la classe du widget.
* Exemple : /widget/carto avec la classe Carto.php dans le dossier carto.
*
*
* @author jpm
*
*/
class Widget {
 
/** Les paramètres de configuration extrait du fichier .ini */
private static $config;
 
/** Le nom du widget demandé. */
private $widget = null;
/** Les chemins où l'autoload doit chercher des classes. */
private static $autoload_chemins = array();
/** Les paramètres de l'url $_GET nettoyés. */
private $parametres = null;
 
/**
* Constructeur.
* Parse le fichier de configuraion "widget.ini" et parse l'url à la recherche du widget demandé.
* @param str iniFile Configuration file to use
*/
public function __construct($fichier_ini = 'widget.ini.php') {
// Chargement de la configuration
self::$config = parse_ini_file($fichier_ini, TRUE);
// Paramêtres de config dynamiques
self::$config['chemins']['baseURLAbsoluDyn'] = 'http://'.$_SERVER['SERVER_NAME'].self::$config['chemins']['baseURL'].'%s';
// Gestion de la mémoire maximum allouée aux services
ini_set('memory_limit', self::$config['parametres']['limiteMemoire']);
// Réglages de PHP
setlocale(LC_ALL, self::$config['parametres']['locale']);
date_default_timezone_set(self::$config['parametres']['fuseauHoraire']);
// Gestion des erreurs
error_reporting(self::$config['parametres']['erreurNiveau']);
if (isset($_SERVER['REQUEST_URI']) && isset($_SERVER['QUERY_STRING'])) {
$url_morceaux = $this->parserUrl();
if (isset($url_morceaux[0])) {
$this->widget = $url_morceaux[0];
self::$config['chemins']['widgetCourantDossier'] = self::$config['chemins']['widgetsDossier'].strtolower($this->widget).DIRECTORY_SEPARATOR;
$this->chargerWidgetConfig();
}
// Chargement des chemins pour l'autoload
$this->chargerCheminAutoload();
// Enregistrement de la méthode gérant l'autoload des classes
spl_autoload_register(array('Widget', 'chargerClasse'));
// Nettoyage du $_GET (sécurité)
$this->collecterParametres();
} else {
$e = 'Les widget nécessite les variables serveurs suivantes pour fonctionner : REQUEST_URI et QUERY_STRING.';
trigger_error($e, E_USER_ERROR);
}
}
private function parserUrl() {
if (strlen($_SERVER['QUERY_STRING']) == 0) {
$len = strlen($_SERVER['REQUEST_URI']);
} else {
$len = -(strlen($_SERVER['QUERY_STRING']) + 1);
}
$url = substr($_SERVER['REQUEST_URI'], strlen(self::$config['chemins']['baseURL']), $len);
$url_morceaux = explode('/', $url);
return $url_morceaux;
}
private function collecterParametres() {
if (isset($_GET) && $_GET != '') {
$this->nettoyerGet();
$this->parametres = $_GET;
}
}
private function nettoyerGet() {
foreach ($_GET as $cle => $valeur) {
$verifier = array('NULL', "\n", "\r", "\\", "'", '"', "\x00", "\x1a", ';');
$_GET[$cle] = strip_tags(str_replace($verifier, '', $valeur));
}
}
private function chargerCheminAutoload() {
$chemins_communs = explode(';', self::$config['chemins']['autoload']);
$chemins_communs = array_map('trim', $chemins_communs);
array_unshift($chemins_communs, '');
$chemins_widget = array();
if (isset(self::$config[$this->widget]['autoload'])) {
$chemins_widget = explode(';', self::$config[$this->widget]['autoload']);
foreach ($chemins_widget as $cle => $chemin) {
$chemins_widget[$cle] = self::$config['chemins']['widgetCourantDossier'].trim($chemin);
}
}
self::$autoload_chemins = array_merge($chemins_communs, $chemins_widget);
}
/**
* La méthode chargerClasse() charge dynamiquement les classes trouvées dans le code.
* Cette fonction est appelée par php5 quand il trouve une instanciation de classe dans le code.
*
*@param string le nom de la classe appelée.
*@return void le fichier contenant la classe doit être inclu par la fonction.
*/
public static function chargerClasse($classe) {
if (class_exists($classe)) {
return null;
}
foreach (self::$autoload_chemins as $chemin) {
$chemin = $chemin.$classe.'.php';
if (file_exists($chemin)) {
require_once $chemin;
}
}
}
/**
* Execute le widget.
*/
function executer() {
if (!is_null($this->widget)) {
$classe_widget = ucfirst($this->widget);
$fichier_widget = self::$config['chemins']['widgetCourantDossier'].$classe_widget.'.php';
if (file_exists($fichier_widget)) {
include_once $fichier_widget;
if (class_exists($classe_widget)) {
$widget = new $classe_widget(self::$config, $this->parametres);
$widget->executer();
}
}
} else {
echo "pas de module précisé";
}
}
/**
* Charge le fichier de config spécifique du wiget et fusionne la config avec celle partagés par l'ensemble des widgets.
*/
private function chargerWidgetConfig() {
$widget_config_ini_fichier = self::$config['chemins']['widgetCourantDossier'].'config.ini';
if (file_exists($widget_config_ini_fichier)) {
$widget_config = parse_ini_file($widget_config_ini_fichier, TRUE);
self::$config = array_merge(self::$config, $widget_config);
}
}
}
?>
/tags/v1.1-helium/widget
New file
Property changes:
Added: svn:ignore
+widget.ini.php
/tags/v1.1-helium/TODO
New file
0,0 → 1,4
- l'indirection (utils/UtilitairesAutoCompletionService.java et nomstaxons/ListeTaxons.php) devrait être
supprimée pour tapper directement dans eflore/services (nécessite un retour JSON plus exploitable (tableau non-associatif))
- ajouter un cache par onglet
- implémenter les tests en attente
/tags/v1.1-helium/doc/bdd/sql/protocoles.sql
New file
0,0 → 1,9
--
-- Contenu de la table `del_image_protocole`
--
 
INSERT INTO `del_image_protocole` (`id_protocole`, `intitule`, `descriptif`, `tag`, `mots_cles`) VALUES
(3, 'Capitalisation d''images', 'photographier en extérieur les organes (feuille, fruit, tronc, etc.) de plantes et transmettre les photos via le Carnet en ligne.', 'Plantnet', 'port,fleur,fruit,feuille,plantscan_new,ecorce,rameau,planche'),
(1, 'Caractères d''identification', 'Caractères d''identification', 'caractere', ''),
(4, 'Défi images', 'Défi images ', 'DefiPhoto', 'defiphoto'),
(5, 'Enquête Gentiane-Azuré', 'Participez à la localisation des Gentianes Croisette, témoins et actrices du cycle de vie du papillon Azuré de la Croisette\r\n', 'GentianeAzure', '');
/tags/v1.1-helium/doc/bdd/sql/del.sql
New file
0,0 → 1,239
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
 
 
-- -----------------------------------------------------
-- Table `del_utilisateur_infos`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `del_utilisateur_infos` ;
 
CREATE TABLE IF NOT EXISTS `del_utilisateur_infos` (
`id_utilisateur` INT(11) NOT NULL ,
`admin` TINYINT(1) NULL ,
`preferences` LONGTEXT NULL ,
`date_premiere_utilisation` DATETIME NULL ,
PRIMARY KEY (`id_utilisateur`) )
ENGINE = MyISAM;
 
 
-- -----------------------------------------------------
-- Table `del_utilisateur`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `del_utilisateur` ;
 
CREATE TABLE IF NOT EXISTS `del_utilisateur` (
`id_utilisateur` INT NOT NULL AUTO_INCREMENT COMMENT 'Type varchar pour éviter problème de jointure.' ,
`prenom` VARCHAR(255) NOT NULL ,
`nom` VARCHAR(255) NOT NULL ,
`courriel` VARCHAR(255) NOT NULL ,
`mot_de_passe` VARCHAR(45) NULL DEFAULT NULL ,
PRIMARY KEY (`id_utilisateur`) )
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
 
 
-- -----------------------------------------------------
-- Table `del_image`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `del_image` ;
 
CREATE TABLE IF NOT EXISTS `del_image` (
`id_image` BIGINT NOT NULL AUTO_INCREMENT ,
`ce_utilisateur` INT NOT NULL ,
`hauteur` INT NULL ,
`largeur` INT NULL ,
`date_prise_de_vue` DATETIME NULL ,
`mots_cles_texte` LONGTEXT NULL DEFAULT NULL ,
`commentaire` LONGTEXT NULL DEFAULT NULL ,
`nom_original` VARCHAR(255) NOT NULL ,
`date_creation` DATETIME NOT NULL ,
`date_modification` DATETIME NOT NULL ,
`publiable_eflore` TINYINT(1) NOT NULL DEFAULT '1' ,
PRIMARY KEY (`id_image`) )
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
 
 
-- -----------------------------------------------------
-- Table `del_observation`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `del_observation` ;
 
CREATE TABLE IF NOT EXISTS `del_observation` (
`id_observation` BIGINT NOT NULL AUTO_INCREMENT ,
`ce_utilisateur` INT NOT NULL ,
`nom_sel` VARCHAR(255) NULL DEFAULT NULL COMMENT 'Nom scientifique sélectionné par l\'utilisateur.' ,
`nom_sel_nn` DECIMAL(9,0) NULL DEFAULT NULL COMMENT 'Identifiant du nom sélectionné.' ,
`nom_ret` VARCHAR(255) NULL DEFAULT NULL COMMENT 'Nom scientifique retenu correspondant au nom sélectionné.' ,
`nom_ret_nn` DECIMAL(9,0) NULL DEFAULT NULL COMMENT 'Identifiant du nom retenu.' ,
`nt` DECIMAL(9,0) NULL DEFAULT NULL COMMENT 'Numéro taxonomique du taxon correspondant au nom sélectionné.' ,
`famille` VARCHAR(255) NULL DEFAULT NULL COMMENT 'Nom de la famille du nom sélectionné.' ,
`nom_referentiel` VARCHAR(255) NULL DEFAULT NULL ,
`ce_zone_geo` VARCHAR(50) NULL DEFAULT NULL ,
`zone_geo` VARCHAR(255) NULL DEFAULT NULL ,
`lieudit` VARCHAR(255) NULL DEFAULT NULL ,
`station` VARCHAR(255) NULL DEFAULT NULL ,
`milieu` VARCHAR(255) NULL DEFAULT NULL ,
`date_observation` DATETIME NULL ,
`mots_cles_texte` LONGTEXT NULL DEFAULT NULL ,
`commentaire` TEXT NULL DEFAULT NULL ,
`date_creation` DATETIME NOT NULL ,
`date_modification` DATETIME NOT NULL ,
`date_transmission` DATETIME NOT NULL COMMENT 'Date à laquelle l\'observation a été rendu publique.' ,
PRIMARY KEY (`id_observation`) )
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci
COMMENT = 'Observations publiques.';
 
 
-- -----------------------------------------------------
-- Table `del_image_protocole`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `del_image_protocole` ;
 
CREATE TABLE IF NOT EXISTS `del_image_protocole` (
`id_protocole` INT NOT NULL AUTO_INCREMENT ,
`intitule` VARCHAR(255) NOT NULL ,
`descriptif` TEXT NULL ,
`tag` VARCHAR(255) NULL ,
`mots_cles` VARCHAR(600) NOT NULL COMMENT 'Mots clés associés au protocole, ceux ci déterminent les mots clés présentés \"à cocher\" dans l\'interface, lorsque le protocole est selectionné' ,
PRIMARY KEY (`id_protocole`) )
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
 
 
-- -----------------------------------------------------
-- Table `del_image_vote`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `del_image_vote` ;
 
CREATE TABLE IF NOT EXISTS `del_image_vote` (
`id_vote` BIGINT NOT NULL AUTO_INCREMENT ,
`ce_image` BIGINT NOT NULL ,
`ce_protocole` INT NOT NULL ,
`ce_utilisateur` VARCHAR(32) NOT NULL COMMENT 'Identifiant de session ou id utilisateur.' ,
`valeur` TINYINT(1) NOT NULL ,
`date` DATETIME NOT NULL ,
PRIMARY KEY (`id_vote`) ,
UNIQUE INDEX `protocole_image_utilisateur` (`ce_image` ASC, `ce_protocole` ASC, `ce_utilisateur` ASC) )
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
 
 
-- -----------------------------------------------------
-- Table `del_image_tag`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `del_image_tag` ;
 
CREATE TABLE IF NOT EXISTS `del_image_tag` (
`id_tag` BIGINT NOT NULL AUTO_INCREMENT ,
`ce_image` BIGINT NOT NULL ,
`ce_utilisateur` VARCHAR(32) NOT NULL ,
`tag` VARCHAR(255) NOT NULL DEFAULT 'Mot clé saisi par l\'utilisateur.' ,
`tag_normalise` VARCHAR(255) NOT NULL DEFAULT 'Mot clé normalisé (sans espace ni accent).' ,
`date` DATETIME NOT NULL COMMENT 'Date de création du tag.' ,
`actif` INT(1) NULL ,
`date_modification` DATETIME NULL ,
PRIMARY KEY (`id_tag`) ,
INDEX `tag` (`tag` ASC) ,
INDEX `tag_normalise` (`tag_normalise` ASC) )
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
 
 
-- -----------------------------------------------------
-- Table `del_commentaire`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `del_commentaire` ;
 
CREATE TABLE IF NOT EXISTS `del_commentaire` (
`id_commentaire` BIGINT NOT NULL AUTO_INCREMENT ,
`ce_observation` BIGINT NOT NULL ,
`ce_proposition` INT NULL DEFAULT 0 ,
`ce_commentaire_parent` BIGINT NULL DEFAULT 0 ,
`texte` TEXT NULL DEFAULT NULL ,
`ce_utilisateur` INT NULL DEFAULT '0' ,
`utilisateur_prenom` VARCHAR(255) NOT NULL ,
`utilisateur_nom` VARCHAR(255) NOT NULL ,
`utilisateur_courriel` VARCHAR(255) NOT NULL ,
`nom_sel` VARCHAR(255) NULL DEFAULT NULL ,
`nom_sel_nn` DECIMAL(9,0) NULL DEFAULT NULL ,
`nom_ret` VARCHAR(255) NULL DEFAULT NULL ,
`nom_ret_nn` DECIMAL(9,0) NULL DEFAULT NULL ,
`nt` DECIMAL(9,0) NULL DEFAULT NULL ,
`famille` VARCHAR(255) NULL DEFAULT NULL ,
`nom_referentiel` VARCHAR(255) NULL DEFAULT NULL ,
`date` DATETIME NOT NULL COMMENT 'Date de création du commentaire.' ,
`proposition_initiale` INT(1) NOT NULL DEFAULT 0 COMMENT 'La proposition initiale est le nom_sel d\'origine copié ici dès lors que des commentaires adviennent.' ,
`proposition_retenue` INT(1) NOT NULL DEFAULT 0 COMMENT 'La proposition \"validée\" une fois que l\'auteur à validé et que le nom_sel de cel_obs a été modifié à partir du nom_sel de del_commentaire.' ,
PRIMARY KEY (`id_commentaire`) )
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
 
 
-- -----------------------------------------------------
-- Table `del_commentaire_vote`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `del_commentaire_vote` ;
 
CREATE TABLE IF NOT EXISTS `del_commentaire_vote` (
`id_vote` BIGINT NOT NULL AUTO_INCREMENT ,
`ce_proposition` BIGINT NOT NULL ,
`ce_utilisateur` VARCHAR(32) NOT NULL DEFAULT '0' COMMENT 'Identifiant de session ou id de l\'utilisateur.' ,
`valeur` TINYINT(1) NOT NULL ,
`date` DATETIME NOT NULL ,
PRIMARY KEY (`id_vote`) )
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci
COMMENT = 'Vote uniquement sur le commentaire de type \'proposition\'.';
 
 
-- -----------------------------------------------------
-- Table `del_obs_image`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `del_obs_image` ;
 
CREATE TABLE IF NOT EXISTS `del_obs_image` (
`id_image` BIGINT NOT NULL ,
`id_observation` BIGINT NOT NULL ,
`date_liaison` DATETIME NOT NULL ,
PRIMARY KEY (`id_image`, `id_observation`) )
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
 
 
-- -----------------------------------------------------
-- Table `del_image_stats`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `del_image_stats` ;
 
CREATE TABLE IF NOT EXISTS `del_image_stats` (
`ce_image` BIGINT(20) NOT NULL COMMENT 'id_image (tb_cel.cel_images)' ,
`ce_protocole` TINYINT NOT NULL DEFAULT 0 COMMENT 'un id de protocole' ,
`moyenne` FLOAT NOT NULL DEFAULT 0 COMMENT 'moyenne des votes pour une image et un protocole donné' ,
`nb_votes` SMALLINT NOT NULL DEFAULT 0 COMMENT 'nombre de votes pour une image et un protocole donné' ,
`nb_tags` TINYINT NOT NULL DEFAULT 0 COMMENT 'nombre de tags pictoflora associés à une image' ,
PRIMARY KEY (`ce_image`, `ce_protocole`) ,
INDEX `ce_image` (`ce_image` ASC) ,
INDEX `ce_protocole` (`ce_protocole` ASC, `moyenne` DESC) ,
INDEX `nb_tags` (`nb_tags` DESC) ,
INDEX `nb_votes` (`nb_votes` DESC) )
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8
COMMENT = 'table de stockage des statistiques utilisées pour les tri de /* comment truncated */ /* PictoFlora*/';
 
 
 
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
/tags/v1.1-helium/doc/bdd/sql/tela/tb_del_cel_vues.sql
New file
0,0 → 1,99
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
 
 
-- -----------------------------------------------------
-- Placeholder table for view `del_utilisateurs`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `del_utilisateurs` (`id_utilisateur` INT, `prenom` INT, `nom` INT, `courriel` INT, `mot_de_passe` INT);
 
-- -----------------------------------------------------
-- Placeholder table for view `del_observations`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `del_observations` (`id_observation` INT, `ce_utilisateur` INT, `prenom_utilisateur` INT, `nom_utilisateur` INT, `courriel_utilisateur` INT, `nom_sel` INT, `nom_sel_nn` INT, `nom_ret` INT, `nom_ret_nn` INT, `nt` INT, `famille` INT, `ce_zone_geo` INT, `zone_geo` INT, `lieudit` INT, `station` INT, `milieu` INT, `nom_referentiel` INT, `date_observation` INT, `mots_cles_texte` INT, `commentaire` INT, `date_creation` INT, `date_modification` INT, `date_transmission` INT);
 
-- -----------------------------------------------------
-- Placeholder table for view `del_images`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `del_images` (`id_image` INT, `ce_utilisateur` INT, `prenom_utilisateur` INT, `nom_utilisateur` INT, `courriel_utilisateur` INT, `hauteur` INT, `largeur` INT, `date_prise_de_vue` INT, `mots_cles_texte` INT, `commentaire` INT, `nom_original` INT, `date_modification` INT, `date_creation` INT, `publiable_eflore` INT, `nom_referentiel` INT);
 
-- -----------------------------------------------------
-- Placeholder table for view `del_obs_images`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `del_obs_images` (`id_image` INT, `id_observation` INT, `date_liaison` INT);
 
-- -----------------------------------------------------
-- Placeholder table for view `v_del_image`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `v_del_image` (`id_image` INT, `i_ordre` INT, `i_ce_utilisateur` INT, `i_prenom_utilisateur` INT, `i_nom_utilisateur` INT, `i_courriel_utilisateur` INT, `i_mots_cles_texte` INT, `hauteur` INT, `largeur` INT, `date_prise_de_vue` INT, `i_commentaire` INT, `nom_original` INT, `publiable_eflore` INT);
 
-- -----------------------------------------------------
-- View `del_utilisateurs`
-- -----------------------------------------------------
DROP VIEW IF EXISTS `del_utilisateurs` ;
DROP TABLE IF EXISTS `del_utilisateurs`;
CREATE OR REPLACE VIEW del_utilisateur AS
SELECT
U_ID AS id_utilisateur,
CONVERT(U_SURNAME USING UTF8) AS prenom,
CONVERT(U_NAME USING UTF8) AS nom,
CONVERT(U_MAIL USING UTF8) AS courriel,
CONVERT(U_PASSWD USING UTF8) AS mot_de_passe
FROM tela_prod_v4.annuaire_tela;
 
-- -----------------------------------------------------
-- View `del_observations`
-- -----------------------------------------------------
DROP VIEW IF EXISTS `del_observations` ;
DROP TABLE IF EXISTS `del_observations`;
CREATE OR REPLACE VIEW del_observation AS
SELECT id_observation, if((char_length(o.ce_utilisateur) <> 32),cast(o.ce_utilisateur as unsigned),0) AS ce_utilisateur, prenom_utilisateur, nom_utilisateur, courriel_utilisateur, nom_sel, nom_sel_nn, nom_ret, nom_ret_nn, nt, famille,
ce_zone_geo, zone_geo, lieudit, station, milieu, nom_referentiel,
date_observation, mots_cles_texte, commentaire,
date_creation, date_modification, date_transmission, certitude
FROM tb_cel.cel_obs AS o
WHERE transmission = '1' ;
 
-- -----------------------------------------------------
-- View `del_images`
-- -----------------------------------------------------
DROP VIEW IF EXISTS `del_images` ;
DROP TABLE IF EXISTS `del_images`;
CREATE OR REPLACE VIEW del_image AS
SELECT i.id_image, if((char_length(i.ce_utilisateur) <> 32),cast(i.ce_utilisateur as unsigned),0) AS ce_utilisateur, i.prenom_utilisateur, i.nom_utilisateur, i.courriel_utilisateur, i.hauteur, i.largeur, i.date_prise_de_vue, i.mots_cles_texte,
i.commentaire, i.nom_original, i.date_modification, i.date_creation, i.publiable_eflore, o.nom_referentiel
FROM tb_cel.cel_images AS i
INNER JOIN tb_cel.cel_obs_images AS oi ON (i.id_image = oi.id_image)
INNER JOIN tb_cel.cel_obs AS o ON (oi.id_observation = o.id_observation)
WHERE o.transmission = '1' ;
 
-- -----------------------------------------------------
-- View `del_obs_images`
-- -----------------------------------------------------
DROP VIEW IF EXISTS `del_obs_images` ;
DROP TABLE IF EXISTS `del_obs_images`;
CREATE OR REPLACE VIEW del_obs_image AS
SELECT oi.id_image, oi.id_observation, oi.date_liaison
FROM tb_cel.cel_obs_images AS oi
INNER JOIN tb_cel.cel_obs AS o ON (oi.id_observation = o.id_observation)
WHERE o.transmission = '1' ;
 
-- -----------------------------------------------------
-- View `v_del_image`
-- -----------------------------------------------------
DROP VIEW IF EXISTS `v_del_image` ;
DROP TABLE IF EXISTS `v_del_image`;
CREATE OR REPLACE VIEW v_del_image AS
SELECT o.*, i.id_image, i.ordre AS i_ordre,
i.ce_utilisateur AS i_ce_utilisateur, i.prenom_utilisateur AS i_prenom_utilisateur, i.nom_utilisateur AS i_nom_utilisateur, i.courriel_utilisateur AS i_courriel_utilisateur,
i.mots_cles_texte AS i_mots_cles_texte, hauteur, largeur, date_prise_de_vue, i.commentaire AS i_commentaire, nom_original, publiable_eflore
FROM tb_cel.cel_obs AS o
INNER JOIN tb_cel.cel_obs_images oi ON oi.id_observation = o.id_observation
INNER JOIN tb_cel.cel_images i ON i.id_image = oi.id_image
WHERE o.transmission = '1';
 
 
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
/tags/v1.1-helium/doc/bdd/schema_bdd_del.mwb
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/doc/bdd/schema_bdd_del.mwb
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/doc/bdd/schema_bdd_del.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/doc/bdd/schema_bdd_del.pdf
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/doc/readme.txt
New file
0,0 → 1,95
Configuration du poste de developpement pas à pas
 
##################################################
############# INSTALLATION ECLIPSE ###############
##################################################
Installer Eclipse Helios (3.6)
Installer le plugin GWT 2.4 pour eclipse sur http://dl.google.com/eclipse/plugin/3.6
Telecharger GWT 2.4 sur le poste local à partir de http://google-web-toolkit.googlecode.com/files/gwt-2.4.0.zip et installer dans un repertoire que nous appellerons GWT_HOME dans ce document
 
##########################################################
################### RECUPERATION DU PROJET ###############
##########################################################
Recuperer le projet avec un client svn sur http://svn.tela-botanica.net/svn/eflore/applications/del
Normalement la propriété svn:ignore devrait exister sur :
- le fichier .classpath à la racine du projet
- le reperoire war/WEB-INF
 
###############################################################
#################### CONFIGURATION D'ECLIPSE ##################
###############################################################
Régler l'encodage à UTF-8
Dans eclipse File>Import>General>Existing Project Into Workspace puis choisir l'emplacement du répertoire del
Clicker sur "OK"
 
Click droit sur le projet del => Properties
Aller ds Google>Web Toolkit et cocher "Use Google Web Toolkit" avec le SDK 2.4
Click droit sur le projet del => Properties
Clicker sur "OK"
 
Aller ds Java Build Path => Onglet "Source"
Dans "source folders in build path" choisir "del/src" et accepter lorqu'il propose d'effacer les autres fichiers sources
Dans default output folder entrer "del/war/WEB-INF/classes/"
Clicker sur "OK"
 
Click droit sur le projet del => Properties
Aller ds Java Build Path => Onglet "Librairies"
Clicker sur "Add library"
Choisir "JRE System Library" puis bouton "Next" et cocher Workspace default JRE(jre6)
Choisir "JUnit 4"
Cliquez sur "Add jars" et ajouter successivement :
- "del> lib > cobogw-1.3.1.jar"
- "del> lib > mockito-all-1.8.5.jar"
 
Clicker sur "OK"
 
Puis Project>Clean et les erreurs doivent disparaitre.
 
######################################################################
################ CONFIGURATION DES SOURCES ###########################
######################################################################
Dans src>org.tela_botanica.del.client.i18n :
- clic droit sur Vocabulary.properties et choisir "properties'. Puis dans Ressources mettre l'encodage à UTF-8
- clic droit sur Messages.properties et choisir 'properties'. Puis dans Ressources mettre l'encodage à UTF-8
 
######################################################################
################ CONFIGURATION DE JREST ##############################
######################################################################
Dans jrest, copiez le fichier jrest.ini.defaut.php et renomez le : jrest.ini.php
En fonction, de l'emplacement du dossier jrest sur votre serveur web modifié les paramètres :
- baseURL
- baseURLAbsolu
- delUrlAbsolu
 
######################################################################
################ CONFIGURATION DE DEL ##############################
######################################################################
Dans war > config, copier le fichier config.defaut.js et renomez le config.js.
En fonction, de l'emplacement du dossier jrest et del sur votre serveur web, modifier les paramètres :
- serviceBaseUrl
- delUrl
######################################################################
################ CONFIGURATION DU SCRIPT ANT DE DEPLOIEMENT ##########
######################################################################
Creer un fichier local.properties à la racine du projet et reseignez les valeurs suivantes:
server-url=xxxxxxxxxxxx
server-login=xxxxxxxxxxxxxx
server-password=xxxxxxxxxxxx
server-dir=xxxxxxxxxxxxxx
gwt-path=xxxxxxxxxxxxxxxx
Mettre ce fichier en svn:ignore (attention tt commit rendra les codes du serveur accessibles sur internet!)
 
######################################################################
################# CONFIGURATION DE ANT POUR ECLIPSE ##################
######################################################################
Télécharger le dernier binaire (jar) de commons.net sur http://commons.apache.org/net/download_net.cgi
Dans Eclipse Window>Preferences>Ant>Runtime>Ant Home Entries puis cliquer sur "Add jar" et ajoutez le jat que vous venez de selectionner et cliquez sur "OK"
Puis Window>Show view>Ant et sur la dorite de votre IDE un onglet Ant apparait
Drag'n'droppez le fichier build.xml situe a la racine du projet vers cet onglet
Sous del deux taches apparaissent, a executer en faisant un clic droit sur la tache puis "run as">"ant build"
La tache "build and deploy test" compile le projet et le déploie sur le serveur de test
 
Bon développement!
 
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/tags/v1.1-helium/lib/commons-net-3.0.1.jar
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/lib/commons-net-3.0.1.jar
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/lib/cobogw-1.3.1.jar
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/lib/cobogw-1.3.1.jar
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/lib/mockito-all-1.8.5.jar
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/lib/mockito-all-1.8.5.jar
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/lib/gwt-servlet.jar
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/lib/gwt-servlet.jar
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/Changelog
New file
0,0 → 1,28
Changements 2014-01-06 [création de la branche "v1.1-helium"]:
* Migration vers Agathis
* Optimisation des requêtes Pictoflora
* Mise à jour des votes en direct
* Correction de bugs
* Le masque "adeterminer" considère aussi les observations dont la "certitude" est "douteux"
* Lors de la création d'une proposition factice, c'est la date de transmission qui est utilisée plutôt que la date de relevé
* Mise à jour du modèle : la vue "del_observation" contient maintenant le champ "certitude"
 
Changements <next>:
- config:
- ajout: "referentiel" à {masques_possibles} à config_observations.ini, config_images.ini, config_nomstaxons.ini et config_mapping_commentaires.ini
- ajout: {nom_referentiel} = "determination.referentiel" à config_observations.ini et config_images.ini
- ajout: {referentiel} = "nom_referentiel" à config_observations.ini et config_images.ini
- ajout: {mots_cles} = "protocole.mots_cles" à config_mapping_votes.ini
- ajout: {admins} dans config.ini
- change: {url_images} pour config_observations.ini et config_images.ini
- change: url_service référence désormais {url_service_base} dans config_votes.ini et config_images.ini
- change: {nb_commentaires_discussion} = 10 (adaptation à la -prod)
- ajout: {url_service_completion_base}
- suppr: {url_service} de config.ini (adaptation à la -prod)
- suppr: {tris_possibles} de config_observations.ini
- Les sections [mappings*] sont obsolètes dans config_images.ini et config_observations.ini
- {masques_possibles}, {formats_possibles} et {tris_possibles} sont obsolètes dans config_images.ini et config_observations.ini
- optimisation d'identiplante à travers ListeObservations2.php
- optimisation de pictoflora à travers ListeImages2.php
- suppression d'un niveau d'indirection pour le service d'autocompletion des noms de taxons
Changements 20130801:
/tags/v1.1-helium/scripts/modules/commentaires/AlerteMailCommentaires.php
New file
0,0 → 1,209
<?php
// declare(encoding='UTF-8');
/**
* Le script récupère tous les commentaires et déterminations fait ce jour et envoie un mail
* aux auteurs des observations récapitulant celle-ci
*
* @category php 5.2
* @package del
* @subpackage scripts
* @author Aurélien PERONNET <aurelien@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
*/
 
class AlerteMailCommentaires {
 
private $parametres;
private $conteneur;
private $observations_concernees = array();
private $id_observation_commentees = array();
private $correspondance_id_obs_auteurs = array();
public function __construct($parametres, $conteneur) {
$this->parametres = $parametres;
$this->conteneur = $conteneur;
}
public function executer() {
try {
$observations = $this->chargerObservationsCommentees();
if(!empty($observations)) {
$this->formaterObservations($observations);
$commentaires = $this->chargerCommentairesAjourdhui();
$this->formaterCommentaires($commentaires);
$this->parcourirListeCommentairesEtEnvoyerMessage($this->observations_concernees);
}
} catch (Exception $e) {
$this->traiterErreur($e->getMessage());
}
}
 
protected function chargerCommentairesAjourdhui() {
//TODO: optimiser la requête si beaucoup de mails sont envoyés
$requete = "SELECT * ".
"FROM del_commentaire dc ".
"WHERE dc.ce_observation != '0' ".
"AND dc.id_commentaire NOT IN ".
"( ".
" SELECT dc.id_commentaire ".
" FROM del_commentaire dc, del_observation dob".
" WHERE dc.nom_sel = dob.nom_sel ".
" AND dc.ce_utilisateur = dob.ce_utilisateur ".
" AND dc.ce_observation = dob.id_observation ".
") ".
"AND dc.ce_utilisateur NOT IN ".
"( ".
" SELECT id_utilisateur ".
" FROM del_utilisateur_infos ".
" WHERE preferences LIKE ".$this->conteneur->getBdd()->proteger('%"mail_notification_mes_obs":"0"%')." ".
") ".
"AND TO_DAYS(NOW()) - TO_DAYS(dc.date) <= 1 ".
"ORDER BY dc.ce_observation";
$commentaires = $this->conteneur->getBdd()->recupererTous($requete);
return $commentaires;
}
protected function chargerObservationsCommentees() {
//TODO: optimiser la requête si beaucoup de mails sont envoyés
$requete = "SELECT * FROM del_observation do ".
"WHERE do.id_observation IN ".
"( ".
"SELECT dc.ce_observation ".
"FROM del_commentaire dc ".
"WHERE dc.ce_observation != '0' ".
"AND dc.id_commentaire NOT IN ".
"( ".
" SELECT dc.id_commentaire ".
" FROM del_commentaire dc, del_observation dob".
" WHERE dc.nom_sel = dob.nom_sel ".
" AND dc.ce_utilisateur = dob.ce_utilisateur ".
" AND dc.ce_observation = dob.id_observation ".
") ".
"AND dc.ce_utilisateur NOT IN ".
"( ".
" SELECT id_utilisateur ".
" FROM del_utilisateur_infos ".
" WHERE preferences LIKE ".$this->conteneur->getBdd()->proteger('%"mail_notification_mes_obs":"0"%')." ".
") ".
"AND TO_DAYS(NOW()) - TO_DAYS(dc.date) <= 1 ".
") ".
"ORDER BY do.ce_utilisateur, do.id_observation ";
$observations = $this->conteneur->getBdd()->recupererTous($requete);
return $observations;
}
protected function convertirCodeZoneGeoVersDepartement($code_zone_geo) {
$code_departement = '';
if($this->estUnCodeInseeDepartement($code_zone_geo)) {
$code_departement = substr(ltrim($code_zone_geo,'INSEE-C:'),0,2);
}
return $code_departement;
}
protected function estUnCodeInseeDepartement($code_a_tester) {
return preg_match('/^INSEE-C:[0-9]{5}/',$code_a_tester);
}
protected function formaterObservations($liste_obs) {
foreach ($liste_obs as $obs) {
$id_obs = $obs['id_observation'];
$auteur_obs = $obs['ce_utilisateur'];
$obs['date'] = $this->formaterDateObs($obs['date_observation']);
$obs['lieu'] = $this->formaterLieuObservation($obs);
$obs['lien'] = $this->obtenirLienFicheObs($obs['id_observation']);
$obs['commentaires'] = array();
$this->correspondance_id_obs_auteurs[$id_obs] = $auteur_obs;
$this->observations_concernees[$auteur_obs][$id_obs] = $obs;
}
}
protected function formaterLieuObservation($obs) {
$lieux = array();
if(!empty($obs['zone_geo'])) {
$zone_geo = $obs['zone_geo'];
$zone_geo.= (!empty($obs['ce_zone_geo']) ? ' ('.$this->convertirCodeZoneGeoVersDepartement($obs['ce_zone_geo']).')' : '');
$lieux[] = $zone_geo;
}
if(!empty($obs['lieudit'])) {
$lieux[] = $obs['lieudit'];
}
if(!empty($obs['station'])) {
$lieux[] = $obs['station'];
}
return implode(" > ", $lieux);
}
protected function formaterCommentaires($liste_commentaires) {
$liste_commentaires_formatee = array();
foreach ($liste_commentaires as $commentaire) {
$id_obs = $commentaire['ce_observation'];
if(isset($this->correspondance_id_obs_auteurs[$commentaire['ce_observation']])) {
$auteur_obs = $this->correspondance_id_obs_auteurs[$commentaire['ce_observation']];
$commentaire['auteur'] = $this->formaterAuteur($commentaire);
$this->observations_concernees[$auteur_obs][$id_obs]['commentaires'][] = $commentaire;
}
}
}
protected function parcourirListeCommentairesEtEnvoyerMessage($liste_obs_a_auteur) {
foreach ($liste_obs_a_auteur as $auteur => $liste_obs) {
$message = $this->formaterMessagePourAuteur($liste_obs,$auteur);
$this->envoyerMessage($message, $auteur);
}
}
private function formaterMessagePourAuteur($liste_obs, $auteur) {
$donnees = array();
// copie de la première obs pour en obtenir le nom et prénom de l'auteur
// (en deux fois pour éviter un warning en mode strict)
$valeurs = array_values($liste_obs);
$premiere_obs = array_shift($valeurs);
$donnees['liste_observations'] = $liste_obs;
$donnees['auteur'] = $auteur;
$donnees['auteur_formate'] = ucfirst($premiere_obs['prenom_utilisateur']).' '.ucfirst($premiere_obs['nom_utilisateur']);
$this->squelette_dossier = dirname(__FILE__).DIRECTORY_SEPARATOR.'squelettes'.DIRECTORY_SEPARATOR;
return $this->conteneur->traiterSquelettePhp($this->squelette_dossier.'commentaires.tpl.html', $donnees);
}
protected function formaterDateObs($date) {
$time = strtotime($date);
return date('d/m/Y', $time);
}
private function formaterAuteur($commentaire) {
return $commentaire['utilisateur_prenom'].' '.$commentaire['utilisateur_nom'];
}
private function obtenirLienFicheObs($id_obs) {
return $this->conteneur->formaterUrl(Config::get('url_fiche_observation'), array('id' => $id_obs));
}
protected function envoyerMessage($message, $auteur) {
$url_requete = $this->conteneur->formaterUrl(Config::get('url_service_messagerie'), array('id' => $auteur));
$post = array(
'sujet' => Config::get('titre_message_recapitulatif'),
'message' => $message,
'utilisateur_courriel' => Config::get('adresse_expediteur_recapitulatif'),
'format' => 'html'
);
 
$ch = curl_init();
$options = array(CURLOPT_URL => $url_requete,
CURLOPT_HEADER => false,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $post,
CURLOPT_RETURNTRANSFER => true
);
curl_setopt_array($ch, $options);
$envoi = curl_exec($ch);
curl_close($ch);
}
}
?>
/tags/v1.1-helium/scripts/modules/commentaires/Commentaires.php
New file
0,0 → 1,41
<?php
//declare(encoding='UTF-8');
/**
* Exemple de lancement du script : :
* /opt/lampp/bin/php cli.php coste -a chargerTous
*
* @category php 5.2
* @package eFlore/Scripts
* @author Aurélien PERONNET <aurelien@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
*/
class Commentaires extends DelScript {
 
public function executer() {
try {
$this->initialiserProjet('commentaires');
 
// Lancement de l'action demandée
$cmd = $this->getParametre('a');
switch ($cmd) {
case 'alerteMail' :
$script = $this->chargerClasse('AlerteMailCommentaires');
$script->executer();
break;
default :
throw new Exception("Erreur : la commande '$cmd' n'existe pas!");
}
} catch (Exception $e) {
$this->traiterErreur($e->getMessage());
}
}
private function chargerClasse($classe) {
require_once $classe.'.php';
return new $classe($this->parametres, $this);
}
}
?>
/tags/v1.1-helium/scripts/modules/commentaires/squelettes/commentaires.tpl.html
New file
0,0 → 1,120
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
<!--
body {
font-family: Arial,Helvetica,Verdana,sans-serif;
font-size: 14px;
}
 
h1 > a {
color:#fd8c13;
}
 
.emphase {
color: #777777;
}
h3 {
font-size:14px;
color:#454341 !important;
margin:0px;
}
 
h3 > a {
color:#454341;
}
 
h1 a, h3 a, h4 a {
color: inherit;
border-bottom: dotted 1px;
}
h3 a {
border-color:#CCCCCC;
}
a {
cursor: pointer;
color:#598000;
text-decoration:none;
border-bottom:1px dotted #95ae5d;
}
a:hover {
color:#FD8C13;
border-bottom:1px dotted #95ae5d;
}
.lire-suite {
padding-left:10px;
background:url(http://www.tela-botanica.org/sites/commun/generique/images/graphisme/petit_carre.png) no-repeat 0px 4px;
}
 
#titre {
background: none repeat scroll 0 0 #9AC343;
opacity: 0.9;
position: relative;
text-align: center;
width: 100%;
}
 
#titre h1 {
background: url("http://www.tela-botanica.org/eflore-test/del/img/identiplante_mini.png") no-repeat scroll 150px 7px transparent;
color: #777777;
font-size: 2em;
font-weight: bold;
margin: 0 0 0;
padding: 18px 60px;
text-align: center;
width: 100%;
}
 
.description_message {
color: #333333;
font-size: 1.1em;
font-style: italic;
padding-top: 10px;
}
-->
</style>
</head>
<body>
<div>
<h1><span class="emphase">IdentiPlante</span> : un telabotaniste vous a aidé </h1>
</div>
<div class="description_message">
Bonjour <?= $auteur_formate ?>,<br />
<br />
</div>
<?php foreach($liste_observations as $observation) : ?>
<span class="emphase">-&gt;</span> Un Telabotaniste vient de proposer une nouvelle détermination ou de faire un commentaire concernant votre observation de
<?php $nom_ret = (trim($observation['nom_ret']) != '') ? $observation['nom_ret'] : 'Espèce indéterminée'; ?>
<h3><a href="<?= $observation['lien']; ?>">Observation <?= $observation['id_observation'] ?> - <em><?= $nom_ret; ?></em></a>
du <?= $observation['date']; ?> à <?= $observation['lieu']; ?></h3>
<?php foreach($observation['commentaires'] as $commentaire) : ?>
<?php if($commentaire['nom_sel'] == '') { ?>
<div class="commentaire">
- <?= $commentaire['auteur'] ?> a écrit <em>"<?= $commentaire['texte'] ?>"</em>
</div>
<?php } else { ?>
<div class="proposition">
- <?= $commentaire['auteur'] ?> a proposé <em><?= $commentaire['nom_sel'] ?></em><br />
<?php if($commentaire['texte'] != '') { ?>
et a écrit : <em>"<?= $commentaire['texte'] ?>"</em>
<?php } ?>
</div>
<?php } ?>
<?php endforeach ; ?>
<br />
<?php endforeach ; ?>
 
Bonne continuation sur nos outils botaniques !<br />
L'&eacute;quipe de Tela Botanica<br />
<div>---------</div>
<br/>
<small>Ce message vous est envoy&eacute; par l'interm&eacute;diaire de l'application IdentiPlante du r&eacute;seau Tela Botanica.
<a href="http://www.tela-botanica.org/eflore">http://www.tela-botanica.org/appli:identiplante </a></small><br />
<small>Si vous ne souhaitez plus recevoir ce mail d&eacute;cochez
la case dans vos pr&eacute;f&eacute;rences sur l'interface d'IdentiPlante.</small>
</body>
</html>
/tags/v1.1-helium/scripts/modules/maj/201310-propret.sql
New file
0,0 → 1,103
DELIMITER |
 
-- initialisation (structure)
DROP PROCEDURE IF EXISTS update_struct;
CREATE PROCEDURE update_struct()
BEGIN
-- ajout de la colonne "proposition_retenue"
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S21' SELECT "colonne proposition_retenue déjà existante"; /* = Duplicate column name */
ALTER TABLE `BASEDEL`.`del_commentaire` ADD `proposition_retenue` INT(1) NOT NULL DEFAULT 0 COMMENT "La proposition \"validée\" une fois que l'auteur à validé et que le nom_sel de cel_obs a été modifié à partir du nom_sel de del_commentaire."; -- '
END;
|
 
-- petite functon bonus
DROP PROCEDURE IF EXISTS getCommentaires;
CREATE PROCEDURE getCommentaires(IN _s1 INT(20))
BEGIN
SELECT id_commentaire, ce_observation, ce_proposition, texte, nom_sel, nom_sel_nn, proposition_retenue FROM `BASEDEL`.`del_commentaire` WHERE ce_observation = _s1;
END;
|
 
-- procédure créant des tables temporaires permettant de faciliter le processus de MAJ
DROP PROCEDURE IF EXISTS rebuild_retenues;
CREATE PROCEDURE rebuild_retenues()
BEGIN
DROP TEMPORARY TABLE IF EXISTS _temp_having_retenue, _temp_multi_prop, _temp_mono_prop;
 
-- les observations déjà retenues (pour pouvoir être exclues des processus postérieurs)
CREATE TEMPORARY TABLE _temp_having_retenue ENGINE=MEMORY AS ( \
SELECT ce_observation FROM `BASEDEL`.`del_commentaire` co WHERE proposition_retenue = 1);
 
-- observations ayant plusieurs propositions (= commentaire dont nom_sel IS NOT NULL)
CREATE TEMPORARY TABLE IF NOT EXISTS _temp_multi_prop ENGINE=MEMORY AS ( \
SELECT ce_observation FROM `BASEDEL`.`del_commentaire` co \
WHERE nom_sel IS NOT NULL \
AND proposition_retenue = 0 /* == ce_observation NOT IN (SELECT ce_proposition FROM _temp_having_retenue) */ \
GROUP BY ce_observation HAVING COUNT(id_commentaire) > 1); -- 1053
 
-- observations ayant une seule proposition (= commentaire dont nom_sel IS NOT NULL)
CREATE TEMPORARY TABLE IF NOT EXISTS _temp_mono_prop ENGINE=MEMORY AS ( \
SELECT ce_observation FROM `BASEDEL`.`del_commentaire` \
WHERE nom_sel IS NOT NULL \
AND proposition_retenue = 0 /* == ce_observation NOT IN (SELECT ce_proposition FROM _temp_having_retenue) */ \
GROUP BY ce_observation HAVING COUNT(id_commentaire) = 1);
 
END;
|
 
DELIMITER ;
 
 
CALL update_struct();
-- table temporaire de tous les comptages (somme des votes pour chaque proposition de del_commentaire):
CREATE TEMPORARY TABLE IF NOT EXISTS _temp_stats ENGINE=MEMORY AS ( SELECT ce_proposition, SUM(valeur) AS val FROM `BASEDEL`.`del_commentaire_vote` GROUP BY ce_proposition); -- 5912
-- propositions ayant eu au moins 1 vote positif non-anonyme
CREATE TEMPORARY TABLE IF NOT EXISTS _temp_authvotepos ENGINE=MEMORY AS (SELECT DISTINCT ce_proposition FROM `BASEDEL`.`del_commentaire_vote` WHERE valeur = 1 AND LENGTH(ce_utilisateur) != 32 ORDER BY ce_proposition); -- 3794
CALL rebuild_retenues(); -- initialisation
 
-- core
-- SELECT ce_observation, id_commentaire FROM `BASEDEL`.`del_commentaire` co INNER JOIN _temp_multi_prop mp USING (ce_observation) INNER JOIN `BASECEL`.`cel_obs` ce ON mp.ce_observation = id_observation AND (co.nom_sel = ce.nom_sel AND co.nom_sel_nn = ce.nom_sel_nn) WHERE co.nom_sel_nn != 0 AND co.proposition_retenue = 0; -- 470, dont 464 ce_observation unique
-- SELECT ce_observation, id_commentaire FROM `BASEDEL`.`del_commentaire` co INNER JOIN _temp_multi_prop mp USING (ce_observation) INNER JOIN `BASECEL`.`cel_obs` ce ON mp.ce_observation = id_observation AND (co.nom_sel = ce.nom_sel OR co.nom_sel_nn = ce.nom_sel_nn) WHERE co.nom_sel_nn != 0 AND co.proposition_retenue = 0; -- 520, dont 493 ce_observation unique
 
-- Étant donné les doublons nous pouvons commencer ou finir par filtrer sur les stats de vote
-- Comme il est plus simple de finir par ça, commençons correctement par les nom_sel comme ci-dessus avec ceux sans ambiguité:
-- C'est à dire observations dotées de multiples proposition dont une et une seule match exactement le nom-sel du carnet en ligne
CREATE TEMPORARY TABLE IF NOT EXISTS _temp_updatable1 ENGINE=MEMORY AS ( \
SELECT /* ce_observation, */ id_commentaire FROM `BASEDEL`.`del_commentaire` co \
INNER JOIN _temp_multi_prop mp USING (ce_observation) /* faisant partie des observations ayant plusieurs propositions */ \
INNER JOIN `BASECEL`.`cel_obs` ce ON mp.ce_observation = id_observation AND (co.nom_sel = ce.nom_sel AND co.nom_sel_nn = ce.nom_sel_nn) \
WHERE co.nom_sel_nn != 0 \
GROUP BY co.ce_observation HAVING COUNT(co.id_commentaire) = 1 /* observations n'ayant pas d'ambiguité sur le commentaire correspondant au nom du carnet en ligne */ ); -- 335
 
UPDATE `BASEDEL`.`del_commentaire` co SET co.proposition_retenue = 1 WHERE co.id_commentaire IN (SELECT id_commentaire FROM _temp_updatable1);
SELECT ROW_COUNT() AS "nb MAJ par match sur nom_sel sans ambiguité";
CALL rebuild_retenues();
 
 
-- Pour les observations ayant plusieurs nom-sel communs au carnet en ligne, il s'agit de ne sélectionner que celle
-- ayant le plus de vote (idéalement les propositions doublonnes ne devraient pas exister)
CREATE TEMPORARY TABLE IF NOT EXISTS _temp_updatable2 ENGINE=MEMORY AS ( \
SELECT co.ce_observation, id_commentaire, i1.val FROM `BASEDEL`.`del_commentaire` co \
INNER JOIN _temp_multi_prop mp USING (ce_observation) /* uniquement les multi-propositions, inclue le check sur _temp_having_retenue */ \
INNER JOIN (SELECT ce_proposition, val FROM _temp_stats) AS i1 ON i1.ce_proposition = co.id_commentaire /* et ayant des votes */ \
INNER JOIN `BASECEL`.`cel_obs` ce ON co.ce_observation = ce.id_observation AND (co.nom_sel = ce.nom_sel AND co.nom_sel_nn = ce.nom_sel_nn) /* et un nom_sel acceptable */ \
WHERE co.nom_sel_nn != 0 \
GROUP BY ce_observation HAVING i1.val = MAX(i1.val) /* parmis les doublonnes, prendre la proposition ayant le plus de SUM(votes) */ \
ORDER BY ce_observation ); -- 249 (sans le processus précédent, moins autrement s'il l'on exclue les observation déjà "validée")
 
UPDATE `BASEDEL`.`del_commentaire` co SET co.proposition_retenue = 1 WHERE co.id_commentaire IN (SELECT id_commentaire FROM _temp_updatable2);
SELECT ROW_COUNT() AS "nb MAJ par nombre de vote";
CALL rebuild_retenues();
 
-- Enfin, les observation n'ayant qu'une seule proposition sont passées comme retenues si
-- elles ont été notée positivement au moins une fois par un utilisateur authentifié
CREATE TEMPORARY TABLE IF NOT EXISTS _temp_updatable3 ENGINE=MEMORY AS ( \
SELECT co.id_commentaire FROM `BASEDEL`.`del_commentaire` co \
INNER JOIN _temp_mono_prop AS i1 USING (ce_observation) /* l'inverse de _temp_multi_prop, inclue le check sur _temp_having_retenue */ \
INNER JOIN _temp_authvotepos ta ON co.id_commentaire = ta.ce_proposition /* et uniquement si faisant partie des commentaires doté d'un vote positif non-anonyme */ \
INNER JOIN `BASECEL`.`cel_obs` ce ON co.ce_observation = ce.id_observation AND (co.nom_sel = ce.nom_sel AND co.nom_sel_nn = ce.nom_sel_nn) \
WHERE co.nom_sel_nn != 0); -- 2216 sans test sur cel_obs, 2193 avec
 
UPDATE `BASEDEL`.`del_commentaire` co SET co.proposition_retenue = 1 WHERE co.id_commentaire IN (SELECT id_commentaire FROM _temp_updatable3);
SELECT ROW_COUNT() AS "nb MAJ ayant 1 seule proposition mais un vote non-anonyme positif";
CALL rebuild_retenues();
/tags/v1.1-helium/scripts/modules/maj/Makefile
New file
0,0 → 1,36
celdb = tb_cel_test
deldb = tb_del_test
 
# helper
do_subst = sed -e "1i--\n-- fichier d'origine: \"${1}\"\n" \
-e 's/`BASECEL`/`$(celdb)`/g' \
-e 's/`BASEDEL`/`$(deldb)`/g' \
$(1)
 
# default target
help:
@echo "make o_maj1 [celdb=<$(celdb)>] [deldb=<$(deldb)>]"
 
clean:
rm -f *.comp.sql
 
# maj1 contient: 201309-index-views.sql
o_maj1: fichiers_generes = $(addsuffix .comp.sql,$(filter-out clean,$?))
o_maj1: clean o_201309-index-views
cat $(fichiers_generes) > maj1.comp.sql
 
 
# maj1 contient: 201310-propret.sql
o_maj2: fichiers_generes = $(addsuffix .comp.sql,$(filter-out clean,$?))
o_maj2: clean o_201310-propret
cat $(fichiers_generes) > maj2.comp.sql
 
 
# SHOW INDEX FROM cel_obs WHERE Key_name = 'transmission';
# SHOW INDEX FROM cel_obs WHERE Key_name = 'date_transmission';
o_201309-index-views:
$(call do_subst,201309-index-views.sql) > $@.comp.sql
 
# SHOW COLUMNS FROM del_commentaire LIKE 'proposition_retenu';
o_201310-propret:
$(call do_subst,201310-propret.sql) > $@.comp.sql
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/tags/v1.1-helium/scripts/modules/maj/README-Index-maj1.txt
New file
0,0 → 1,106
1) accélérer le SELECT + ORDER BY sur del_observation
 
C'est un aspect important de la requête car il représente près de 33% du temps.
En local, près de 50ms sur 1.5s.
Solution:
 
CREATE INDEX `date_transmission` ON `cel_obs` (`date_transmission` DESC) COMMENT "nécessaire à l'ORDER BY utilisé dans la liste d'observation de DEL";
 
Malheureusement l'INDEX ne semble pas utilisable par la view (http://bugs.mysql.com/bug.php?id=43341 ?):
EXPLAIN SELECT SQL_CALC_FOUND_ROWS id_observation FROM del_observation ORDER BY date_transmission desc LIMIT 0, 12;
# Using filesort (0.46s)
 
Allons donc invoquer directement la table, cependant, encore une fois l'INDEX n'est pas utilisé
EXPLAIN SELECT SQL_CALC_FOUND_ROWS id_observation FROM tb_cel.cel_obs ORDER BY date_transmission desc LIMIT 0, 12;
# Using filesort (0.46s)
 
Nous pouvons forcer l'index:
EXPLAIN SELECT SQL_CALC_FOUND_ROWS id_observation FROM tb_cel.cel_obs FORCE INDEX FOR ORDER BY (`date_transmission`) ORDER BY date_transmission desc LIMIT 0, 12;
# key=date_transmission (0.0s)
parfait !
 
 
Cependant, à peine ajoutons-nous le WHERE transmission = 1 que nous remontons à 0.60 seconde, et MySQL nous déconseille même l'utilisation de l'INDEX
qui, en effet, ralenti la requête (2.38s):
EXPLAIN SELECT SQL_CALC_FOUND_ROWS id_observation FROM tb_cel.cel_obs FORCE INDEX FOR ORDER BY (`date_transmission`) WHERE transmission = 1 ORDER BY date_transmission desc LIMIT 0, 12;
# Using where; Using filesort (0.60s)
# Using where; (key=date_transmission) (2.38s) [avec FORCE INDEX]
Dans tous les cas ci-dessus, "rows" indique "291265", et le type "ref", sauf en "FORCE INDEX", mais comme nous l'avons vu, cela sous-optimal.
 
Le processing de transmission = 1 est très (très) couteux et c'est lui qui s'avère bloquant.
 
 
Tentons l'ajout d'un INDEX sur transmission ,tout TINYINT soit-il:
CREATE INDEX `transmission` ON `tb_cel`.`cel_obs` (`transmission`) COMMENT "nécessaire à CEL/DEL qui officie avec transmission = 1"
ANALYZE TABLE tb_cel.cel_obs;
EXPLAIN SELECT id_observation FROM tb_cel.cel_obs WHERE transmission = 1 ORDER BY date_transmission desc LIMIT 0, 12;
# key = date_transmission, rows = 17, type = index (0.0s)
parfait...
et idem pour:
EXPLAIN SELECT * FROM del_observation ORDER BY date_transmission desc LIMIT 0, 12;
La vue prend donc bien en compte nos 2 INDEX.
 
MAIS... ...
EXPLAIN SELECT SQL_CALC_FOUND_ROWS id_observation FROM tb_cel.cel_obs WHERE transmission = 1 ORDER BY date_transmission desc LIMIT 0, 12;
# Using where; Using filesort, key = date_transmission, rows = 291265, type = index (0.80s)
... à peine retrouvons-nous SQL_CALC_FOUND_ROWS() que les perf' sont à nouveau déplorable puis MySQL itère sur les 300k lignes à transmission=1
 
Cependant:
EXPLAIN SELECT count(1) FROM del_observation;
# key = transmission, 291265 = 17, type = ref, MAIS... "Using index" (0.10s)
 
 
 
Ainsi pour une requête initiale:
SELECT SQL_CALC_FOUND_ROWS dob.id_observation, nom_sel, famille, ce_zone_geo, zone_geo, lieudit, station, milieu, date_observation, dob.mots_cles_texte, date_transmission, dob.ce_utilisateur, prenom, nom, courriel, dob.prenom_utilisateur, dob.nom_utilisateur, dob.courriel_utilisateur, dob.commentaire as dob_commentaire, dob.nt, dob.nom_sel_nn FROM del_observation AS dob LEFT JOIN del_utilisateur AS du ON dob.ce_utilisateur = du.id_utilisateur ORDER BY date_transmission desc LIMIT 0, 12
de 1.52s, la suppression SQL_CALC_FOUND_ROWS() nous amène à 0.00s + 0.10s de count() additionnel.
 
Sans INDEX sur transmission, la requête est de même rapidité, mais le count(1), trois fois plus long (0.30s)
Sans INDEX sur date_transmission, la requête est 4 fois plus longue (0.40s) et le count(1) identique (0.35s)
Bref, les 2 INDEX sont intéressant même si l'idéal est de rendre optionnel l'affichage du total des résultats
 
 
 
 
2) accélérer le GROUP en requête complexe:
SELECT SQL_CALC_FOUND_ROWS dob.id_observation, nom_sel, famille, ce_zone_geo, zone_geo, lieudit, station, milieu, date_observation, dob.mots_cles_texte, date_transmission, di.id_image, dob.ce_utilisateur, prenom, nom, courriel, dob.prenom_utilisateur, dob.nom_utilisateur, dob.courriel_utilisateur, nom_original, dob.commentaire AS dob_commentaire, dob.nt, dob.nom_sel_nn FROM del_observation AS dob LEFT JOIN del_utilisateur AS du ON du.id_utilisateur = dob.ce_utilisateur LEFT JOIN del_obs_image AS doi ON doi.id_observation = dob.id_observation LEFT JOIN del_image AS di ON di.id_image = doi.id_image WHERE 1 GROUP BY doi.id_observation ORDER BY date_transmission desc LIMIT 0, 12
 
 
EXPLAIN SELECT dob.id_observation, di.id_image FROM cel_obs AS dob, cel_obs_images AS doi, cel_images AS di WHERE (transmission = 1 AND doi.id_observation = dob.id_observation AND di.id_image = doi.id_image) GROUP BY dob.id_observation ORDER BY date_transmission desc LIMIT 0, 12;
+------+-------------+-------+--------+---------------------------+---------+---------+---------------------------+-------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+--------+---------------------------+---------+---------+---------------------------+-------+----------------------------------------------+
| 1 | SIMPLE | doi | index | PRIMARY,observation,image | PRIMARY | 16 | NULL | 10314 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | di | eq_ref | PRIMARY,id_image | PRIMARY | 8 | tb_cel.doi.id_image | 1 | Using index |
| 1 | SIMPLE | dob | eq_ref | PRIMARY,transmission | PRIMARY | 8 | tb_cel.doi.id_observation | 1 | Using where |
+------+-------------+-------+--------+---------------------------+---------+---------+---------------------------+-------+----------------------------------------------+
# 0.04s
 
EXPLAIN SELECT dob.id_observation, di.id_image FROM del_observation AS dob, del_obs_image AS doi, del_image AS di WHERE (doi.id_observation = dob.id_observation AND di.id_image = doi.id_image) GROUP BY dob.id_observation ORDER BY date_transmission desc LIMIT 0, 12;
+------+-------------+-------+--------+---------------------------+---------+---------+--------------------------+-------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+--------+---------------------------+---------+---------+--------------------------+-------+----------------------------------------------+
| 1 | SIMPLE | oi | index | PRIMARY,observation,image | PRIMARY | 16 | NULL | 10314 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | oi | ref | PRIMARY,observation,image | image | 8 | tb_cel.oi.id_image | 1 | |
| 1 | SIMPLE | i | eq_ref | PRIMARY,id_image | PRIMARY | 8 | tb_cel.oi.id_image | 1 | Using index |
| 1 | SIMPLE | o | eq_ref | PRIMARY,transmission | PRIMARY | 8 | tb_cel.oi.id_observation | 1 | Using where |
| 1 | SIMPLE | o | eq_ref | PRIMARY,transmission | PRIMARY | 8 | tb_cel.oi.id_observation | 1 | Using where |
| 1 | SIMPLE | o | eq_ref | PRIMARY,transmission | PRIMARY | 8 | tb_cel.oi.id_observation | 1 | Using where |
+------+-------------+-------+--------+---------------------------+---------+---------+--------------------------+-------+----------------------------------------------+
# 1.67s
 
 
En fait, del_image se définit comme suit:
select `i`.`id_image` AS `id_image`,if((char_length(`i`.`ce_utilisateur`) <> 32),cast(`i`.`ce_utilisateur` as unsigned),0) AS `ce_utilisateur`,`i`.`prenom_utilisateur` AS `prenom_utilisateur`,`i`.`nom_utilisateur` AS `nom_utilisateur`,`i`.`courriel_utilisateur` AS `courriel_utilisateur`,`i`.`hauteur` AS `hauteur`,`i`.`largeur` AS `largeur`,`i`.`date_prise_de_vue` AS `date_prise_de_vue`,`i`.`mots_cles_texte` AS `mots_cles_texte`,`i`.`commentaire` AS `commentaire`,`i`.`nom_original` AS `nom_original`,`i`.`date_modification` AS `date_modification`,`i`.`date_creation` AS `date_creation`,`i`.`publiable_eflore` AS `publiable_eflore` from ((`tb_cel`.`cel_images` `i` join `tb_cel`.`cel_obs_images` `oi` on((`i`.`id_image` = `oi`.`id_image`))) join `tb_cel`.`cel_obs` `o` on((`oi`.`id_observation` = `o`.`id_observation`))) where (`o`.`transmission` = '1')
 
soit déjà une double-jointure.
 
EXPLAIN SELECT id_observation, id_image FROM del_image AS di GROUP BY id_observation ORDER BY date_transmission desc LIMIT 0, 12;
+------+-------------+-------+--------+---------------------------+---------+---------+--------------------------+-------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+--------+---------------------------+---------+---------+--------------------------+-------+----------------------------------------------+
| 1 | SIMPLE | oi | index | PRIMARY,observation,image | PRIMARY | 16 | NULL | 10314 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | i | eq_ref | PRIMARY,id_image | PRIMARY | 8 | tb_cel.oi.id_image | 1 | Using index |
| 1 | SIMPLE | o | eq_ref | PRIMARY,transmission | PRIMARY | 8 | tb_cel.oi.id_observation | 1 | Using where |
+------+-------------+-------+--------+---------------------------+---------+---------+--------------------------+-------+----------------------------------------------+
# 0.04s
/tags/v1.1-helium/scripts/modules/maj/201309-index-views.sql
New file
0,0 → 1,74
-- r1368/r1418: ajout de nom_referentiel à del_observations (attention, appelée "del_images" dans mysql-workbench)
DROP VIEW IF EXISTS `BASEDEL`.`del_image` ;
DROP TABLE IF EXISTS `BASEDEL`.`del_image`;
CREATE OR REPLACE VIEW `BASEDEL`.`del_image` AS
SELECT i.id_image, if((char_length(i.ce_utilisateur) <> 32),cast(i.ce_utilisateur as unsigned),0) AS ce_utilisateur, i.prenom_utilisateur, i.nom_utilisateur, i.courriel_utilisateur, i.hauteur, i.largeur, i.date_prise_de_vue, i.mots_cles_texte,
i.commentaire, i.nom_original, i.date_modification, i.date_creation, i.publiable_eflore, o.nom_referentiel
FROM `BASECEL`.`cel_images` AS i
INNER JOIN `BASECEL`.`cel_obs_images` AS oi ON (i.id_image = oi.id_image)
INNER JOIN `BASECEL`.`cel_obs` AS o ON (oi.id_observation = o.id_observation)
WHERE o.transmission = '1' ;
 
 
-- r1368/r1418: ajout de nom_referentiel à del_observations
DROP VIEW IF EXISTS `BASEDEL`.`del_observations` ;
DROP TABLE IF EXISTS `BASEDEL`.`del_observations`;
CREATE OR REPLACE VIEW `BASEDEL`.`del_observation` AS
SELECT id_observation, if((char_length(o.ce_utilisateur) <> 32),cast(o.ce_utilisateur as unsigned),0) AS ce_utilisateur, prenom_utilisateur, nom_utilisateur, courriel_utilisateur, nom_sel, nom_sel_nn, nom_ret, nom_ret_nn, nt, famille,
ce_zone_geo, zone_geo, lieudit, station, milieu, nom_referentiel,
date_observation, mots_cles_texte, commentaire,
date_creation, date_modification, date_transmission
FROM `BASECEL`.`cel_obs` AS o
WHERE transmission = '1' ;
 
-- r1376: ajout de la vue v_del_image (version modifiée de del_image
DROP VIEW IF EXISTS `BASEDEL`.`v_del_image` ;
DROP TABLE IF EXISTS `BASEDEL`.`v_del_image`;
CREATE OR REPLACE VIEW `BASEDEL`.`v_del_image` AS
SELECT o.*, i.id_image, i.ordre AS i_ordre,
i.ce_utilisateur AS i_ce_utilisateur, i.prenom_utilisateur AS i_prenom_utilisateur, i.nom_utilisateur AS i_nom_utilisateur, i.courriel_utilisateur AS i_courriel_utilisateur,
i.mots_cles_texte AS i_mots_cles_texte, hauteur, largeur, date_prise_de_vue, i.commentaire AS i_commentaire, nom_original, publiable_eflore
FROM `BASECEL`.cel_obs AS o
INNER JOIN `BASECEL`.cel_obs_images oi ON oi.id_observation = o.id_observation
INNER JOIN `BASECEL`.cel_images i ON i.id_image = oi.id_image
WHERE o.transmission = '1';
 
-- r1853 de CEL: ajout des INDEX (note: pas de commentaires sur les INDEX < MySQL 5.5)
CREATE INDEX `date_transmission` ON `BASECEL`.`cel_obs` (`date_transmission` DESC) /* COMMENT "nécessaire à l'ORDER BY utilisé dans la liste d'observation de DEL" */ ;
CREATE INDEX `transmission` ON `BASECEL`.`cel_obs` (`transmission`) /* COMMENT "nécessaire à CEL/DEL qui officie avec transmission = 1" */ ;
 
 
-- cleanup
DROP INDEX `tag_normalise_2` ON `BASEDEL`.`del_image_tag` ;
DROP INDEX `ce_image_2` ON `BASEDEL`.`del_image_tag` ;
 
 
 
DROP TABLE IF EXISTS `BASEDEL`.`del_image_stat`;
CREATE TABLE IF NOT EXISTS `BASEDEL`.`del_image_stat` (
`ce_image` BIGINT(20) NOT NULL COMMENT 'id_image (tb_cel.cel_images)',
`ce_protocole` TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'un id de protocole',
`moyenne` FLOAT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'moyenne des votes pour une image et un protocole donné',
`nb_votes` SMALLINT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'nombre de votes pour une image et un protocole donné',
`nb_tags` TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'nombre de tags pictoflora pour une image donnée',
PRIMARY KEY (`ce_image`, `ce_protocole`),
KEY `ce_image` (`ce_image`),
KEY `ce_protocole` (`ce_protocole`, `moyenne` DESC),
KEY `nb_votes` (`nb_votes` DESC),
KEY `nb_tags` (`nb_tags` DESC)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'table de stockage des statistiques utilisées pour les tri de PictoFlora';
 
 
INSERT INTO `BASEDEL`.`del_image_stat` (
SELECT id_image, divo.ce_protocole, divo.moyenne, divo.nb_votes, dit.ctags
FROM `BASECEL`.`cel_images` ci
LEFT JOIN
( SELECT ce_image, ce_protocole, AVG(valeur) AS moyenne, COUNT(valeur) AS nb_votes
FROM del_image_vote GROUP BY ce_image, ce_protocole ) AS divo
ON ci.id_image = divo.ce_image
LEFT JOIN
( SELECT ce_image, COUNT(id_tag) as ctags FROM del_image_tag
GROUP BY ce_image ) AS dit
ON ci.id_image = dit.ce_image );
 
ALTER TABLE `BASEDEL`.`del_image_protocole` ADD `mots_cles` VARCHAR(600) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
/tags/v1.1-helium/scripts/modules/maj
New file
Property changes:
Added: svn:ignore
+o_*.comp.sql
/tags/v1.1-helium/scripts/modules/adeterminer/squelettes/aDeterminer.tpl.html
New file
0,0 → 1,93
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
<!--
body {
font-family: Arial,Helvetica,Verdana,sans-serif;
font-size: 14px;
}
 
h1 > a {
color:#fd8c13;
}
h3 {
font-size:14px;
color:#454341 !important;
margin:0px;
}
 
h3 > a {
color:#454341;
}
 
h1 a, h3 a, h4 a {
color: inherit;
border-bottom: dotted 1px;
}
h3 a {
border-color:#CCCCCC;
}
a {
cursor: pointer;
color:#598000;
text-decoration:none;
border-bottom:1px dotted #95ae5d;
}
a:hover {
color:#FD8C13;
border-bottom:1px dotted #95ae5d;
}
.lire-suite {
padding-left:10px;
background:url(http://www.tela-botanica.org/sites/commun/generique/images/graphisme/petit_carre.png) no-repeat 0px 4px;
}
 
#titre {
background: none repeat scroll 0 0 #9AC343;
opacity: 0.9;
position: relative;
text-align: center;
width: 100%;
}
 
#titre h1 {
background: url("http://www.tela-botanica.org/eflore-test/del/img/identiplante_mini.png") no-repeat scroll 150px 7px transparent;
color: #777777;
font-size: 2em;
font-weight: bold;
margin: 0 0 0;
padding: 18px 60px;
text-align: center;
width: 100%;
}
 
.description_message {
color: #333333;
font-size: 1.1em;
font-style: italic;
padding-top: 10px;
}
-->
</style>
</head>
<body>
<div id="titre">
<h1>IdentiPlante - Récapitulatif des observations à déterminer </h1>
</div>
<div class="description_message">
Ce message récapitule l'ensemble des observations dont l'auteur a demandé confirmation ou détermination via
l'outil <a href="http://www.tela-botanica.org/appli:del" >Identiplante</a>
<br /><br />
</div>
<?php foreach($liste_observations as $observation) : ?>
<?php $nom_ret = (trim($observation['nom_propose']) != '') ? $observation['nom_propose'] : 'Espèce indéterminée'; ?>
<h3><a href="<?= $observation['lien']; ?>">Observation <?= $observation['id_observation'] ?> - <em><?= $nom_ret; ?></em> </a>
observée le <?= $observation['date']; ?> à <?= $observation['zone_geo']; ?></h3>
<br />
<?php endforeach ; ?>
</body>
</html>
/tags/v1.1-helium/scripts/modules/adeterminer/Adeterminer.php
New file
0,0 → 1,41
<?php
//declare(encoding='UTF-8');
/**
* Exemple de lancement du script : :
* /opt/lampp/bin/php cli.php coste -a chargerTous
*
* @category php 5.2
* @package eFlore/Scripts
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
*/
class Adeterminer extends DelScript {
 
public function executer() {
try {
$this->initialiserProjet('adeterminer');
 
// Lancement de l'action demandée
$cmd = $this->getParametre('a');
switch ($cmd) {
case 'alerteMail' :
$script = $this->chargerClasse('AlerteMailADeterminer');
$script->executer();
break;
default :
throw new Exception("Erreur : la commande '$cmd' n'existe pas!");
}
} catch (Exception $e) {
$this->traiterErreur($e->getMessage());
}
}
private function chargerClasse($classe) {
require_once $classe.'.php';
return new $classe($this->parametres, $this);
}
}
?>
/tags/v1.1-helium/scripts/modules/adeterminer/AlerteMailADeterminer.php
New file
0,0 → 1,199
<?php
// declare(encoding='UTF-8');
/**
* Le script récupère tous les commentaires et déterminations fait ce jour et envoie un mail
* aux auteurs des observations récapitulant celle-ci
*
* @category php 5.2
* @package del
* @subpackage scripts
* @author Aurélien PERONNET <aurelien@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
*/
 
class AlerteMailADeterminer {
 
private $parametres;
private $conteneur;
private $observations_concernees = array();
private $id_observation_commentees = array();
private $correspondance_id_obs_auteurs = array();
public function __construct($parametres, $conteneur) {
$this->parametres = $parametres;
$this->conteneur = $conteneur;
}
public function executer() {
try {
$observations = $this->chargerObsADeterminer();
if(!empty($observations)) {
$this->formaterObservations($observations);
$this->formaterListeObservationsEtEnvoyerMessage($this->observations_concernees);
}
} catch (Exception $e) {
$this->traiterErreur($e->getMessage());
}
}
 
protected function chargerObsADeterminer() {
//TODO: optimiser la requête si beaucoup de mails sont envoyés
$requete = "SELECT * ".
"FROM del_obs_image doi ".
"INNER JOIN del_observation do ".
"ON doi.id_observation = do.id_observation ".
"LEFT JOIN del_utilisateur du ".
"ON do.ce_utilisateur = du.id_utilisateur AND do.ce_utilisateur != 0 ".
'WHERE (do.mots_cles_texte LIKE "%aDeterminer%" OR nom_sel IS NULL OR nom_ret IS NULL) AND '.
'(do.date_transmission > DATE_SUB(CURDATE(), INTERVAL 1 DAY) OR '.
'do.date_creation > DATE_SUB(CURDATE(), INTERVAL 1 DAY) OR '.
'do.date_modification > DATE_SUB(CURDATE(), INTERVAL 1 DAY)) '.
"ORDER BY do.id_observation";
$obs = $this->conteneur->getBdd()->recupererTous($requete);
return $obs;
}
protected function formaterObservations($liste_obs) {
foreach ($liste_obs as $obs) {
$id_obs = $obs['id_observation'];
$auteur_obs = $this->formaterAuteur($obs);
$obs['date'] = ($obs['date_observation'] != '0000-00-00 00:00:00') ? $this->formaterDateObs($obs['date_observation']) : '(date inconnue)';
$obs['lien'] = $this->obtenirLienFicheObs($obs['id_observation']);
$obs['nom_propose'] = $this->formaterNomSci($obs);
$this->observations_concernees[$id_obs] = $obs;
}
}
protected function formaterListeObservationsEtEnvoyerMessage($liste_obs) {
$message = $this->formaterMessagePourListeObs($liste_obs);
$this->envoyerMessageListeDetermination($message);
$utilisateurs = $this->obtenirDestinatairesMailsRecapitulatif();
foreach ($utilisateurs as $utilisateur) {
$this->envoyerMessage($message, $utilisateur['id_utilisateur']);
}
}
private function formaterMessagePourListeObs($liste_obs) {
$donnees = array();
$donnees['liste_observations'] = $liste_obs;
$this->squelette_dossier = dirname(__FILE__).DIRECTORY_SEPARATOR.'squelettes'.DIRECTORY_SEPARATOR;
return $this->conteneur->traiterSquelettePhp($this->squelette_dossier.'aDeterminer.tpl.html', $donnees);
}
protected function formaterDateObs($date) {
$time = strtotime($date);
return date('d/m/Y', $time);
}
private function formaterAuteur($obs) {
return $obs['prenom'].' '.$obs['nom'];
}
private function formaterNomSci($obs) {
$nom = '';
if($obs['nom_ret'] != '') {
$nom = $obs['nom_ret'];
} else if($obs['nom_sel'] != '') {
$nom = $obs['nom_sel'];
}
return $nom;
}
private function obtenirLienFicheObs($id_obs) {
return $this->conteneur->formaterUrl(Config::get('url_fiche_observation'), array('id' => $id_obs));
}
private function obtenirDestinatairesMailsRecapitulatif() {
$requete = "SELECT id_utilisateur ".
" FROM del_utilisateur_infos ".
" WHERE preferences LIKE ".$this->conteneur->getBdd()->proteger('%"mail_notification_toutes_obs":"1"%');
$utilisateurs = $this->conteneur->getBdd()->recupererTous($requete);
return $utilisateurs;
}
/**
* Appelle le web service message de l'annuaire afin d'envoyer un mail à l'utilisateur dont l'identifiant est donné
* en paramètre
* Enter description here ...
* @param string $message
* @param int $id_destinataire
*/
protected function envoyerMessage($message, $id_destinataire) {
$url_requete = $this->conteneur->formaterUrl(Config::get('url_service_messagerie'), array('id' => $id_destinataire));
$post = array(
'sujet' => 'Récapitulatif des dernières observations à déterminer',
'message' => $message,
'utilisateur_courriel' => Config::get('adresse_expediteur_recapitulatif'),
'format' => 'html'
);
$ch = curl_init();
$options = array(CURLOPT_URL => $url_requete,
CURLOPT_HEADER => false,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $post,
CURLOPT_RETURNTRANSFER => true
);
curl_setopt_array($ch, $options);
$envoi = curl_exec($ch);
curl_close($ch);
}
/** La liste détermination n'étant pas un membre de tela botanica,
* on lui envoie un message directement
* @param string $message contenu du mail
* @return boolean true ou false suivant le succès ou non de l'envoi
*/
public function envoyerMessageListeDetermination($message) {
$sujet = 'Récapitulatif des dernières observations à déterminer';
$message_antislashe = $message;
$message_texte = strip_tags($message);
$message_html = $message_antislashe;
$limite = "_----------=_parties_".md5(uniqid (rand()));
$entetes = '';
// Définition d'un mail en texte simple et html
$entetes .= "X-Sender: <http://www.tela-botanica.org>\n";
$entetes .= "X-Mailer: PHP\n";
$entetes .= "X-auth-smtp-user: ".Config::get('adresse_expediteur_recapitulatif')." \n";
$entetes .= "X-abuse-contact: ".Config::get('adresse_expediteur_recapitulatif')." \n";
$entetes .= "Date: ".date("D, j M Y G:i:s O")."\n";
$entetes .= 'From: '.Config::get('adresse_expediteur_recapitulatif')."\n";
// multipart/alternative signifie même contenu de la forme la plus simple à la plus complexe
$entetes .= "Content-Type: multipart/alternative; boundary=\"".$limite."\";\n\n";
$contenu = "";
// message en texte simple
$contenu .= "--".$limite."\n";
$contenu .= "Content-Type: text/plain; charset=\"".Config::get('encodage_appli')."\";\n";
$contenu .= "Content-Transfer-Encoding: 7bit;\n\n";
$contenu .= $message_texte."\n";
// le message en html est préféré s'il est lisible
$contenu .= "--".$limite."\n";
$contenu .= "Content-Type: text/html;";
$contenu .= "charset=\"".Config::get('encodage_appli')."\";\n";
$contenu .= "Content-Transfer-Encoding: 7bit;\n\n";
$contenu .= $message_antislashe."\n";
$contenu .= "--".$limite."--\n";
if (!mail(Config::get('adresse_destinataire_recapitulatif_determination'), Config::get('titre_message_recapitulatif_obs'), $contenu, $entetes)) {
return false;
}
return true;
}
}
?>
/tags/v1.1-helium/scripts/configurations/config.defaut.ini
New file
0,0 → 1,70
; Encodage : UTF-8
 
; +------------------------------------------------------------------------------------------------------+
; URLs
; Le séparateur utilisé par le framework lorsqu'il génère des URL pour séparer les arguments.
; Pour remettre les valeurs par défaut, utitliser : "php:ini_get('arg_separator.output')"
url_arg_separateur_sortie = "&"
 
; +------------------------------------------------------------------------------------------------------+
; Info sur l'application
info.nom = Scripts d'identiplante
; Abréviation de l'application
info.abr = del-services
; Version du Framework nécessaire au fonctionnement de cette application
info.framework.version = 0.3
;Encodage de l'application
encodage_appli = "UTF-8"
 
; +------------------------------------------------------------------------------------------------------+
; Débogage
; Indique si oui ou non on veut afficher le débogage.
debogage = true
; Indique sous quelle forme les méssages de débogage doivent s'afficher :
; - "php:Debug::MODE_ECHO" : le message est affiché en utilisant echo
; - "php:Debug::MODE_NOTICE" : le message est affiché en utilisant une erreur de type notice
; - "php:Debug::MODE_ENTETE_HTTP" : les messages sont envoyés dans un entête HTTP "X_REST_DEBOGAGE".
; - "Autre valeur" : les messages sont formatés puis retournés par la méthode de débogage utilisée.
debogage_mode = "php:Debug::MODE_ECHO"
; Indique si oui ou non on veut lancer le chronométrage
chronometrage = false
 
 
; +------------------------------------------------------------------------------------------------------+
; Paramètrage de la base de données.
; Abstraction de la base de données.
bdd_abstraction = pdo
; Protocole de la base de données.
bdd_protocole = mysql
; Nom du serveur de bases de données.
bdd_serveur = localhost
; Nom de l'utilisateur de la base de données.
bdd_utilisateur = ""
; Mot de passe de l'utilisateur de la base de données.
bdd_mot_de_passe = ""
; Nom de la base de données principale.
bdd_nom = "del"
; Encodage de la base de données principale au format base de données (ex. pour l'utf-8 ne pas mettre le tiret!).
bdd_encodage = "utf8"
 
; +------------------------------------------------------------------------------------------------------+
; Standard utilisé pour les codes de langue
langue_source = "ISO-639-1";
; Standard utilisé pour les codes de zones géographiques
zone_geo_source = "ISO-3166-1";
 
; +------------------------------------------------------------------------------------------------------+
; Url de la fiche de l'observation
url_fiche_observation = "http://www.tela-botanica.org/eflore-test/del/del.html#page_validation~{id}";
 
; +------------------------------------------------------------------------------------------------------+
; Url du service de messagerie de l'annuaire
url_service_messagerie = "http://www.tela-botanica.org/client/annuaire_nouveau/actuelle/jrest/Utilisateur/{id}/message";
; Titre du message de récapitulatif d'identiplante
titre_message_recapitulatif = "Récapitulatif identiplante";
; Adresse de l'expéditeur des messages récapitulatifs
adresse_expediteur_recapitulatif = "identiplante-determination@tela-botanica.org"
; Adresse destinataire des messages récapitulatifs de détermination
adresse_destinataire_recapitulatif_determination = "test@tela-botanica.org"
; titre du message de récapitulatif des obs à déterminer
titre_message_recapitulatif_obs = "Récapitulatif des dernieres observations à déterminer"
/tags/v1.1-helium/scripts/configurations
New file
Property changes:
Added: svn:ignore
+config.ini
/tags/v1.1-helium/scripts/framework.defaut.php
New file
0,0 → 1,6
<?php
// Inclusion du Framework
// Renomer ce fichier en "framework.php"
// Indiquer ci-dessous le chemin absolu vers le fichier autoload.inc.php de la bonne version du Framework
require_once '/home/www/commun/framework/0.3/Framework.php';
?>
/tags/v1.1-helium/scripts/bibliotheque/DelScript.php
New file
0,0 → 1,117
<?php
/**
* Classe mère des scripts del
*
* @category php 5.2
* @package del
* @subpackage scripts
* @author Aurélien PERONNET <aurelien@tela-botanica.org>
* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
* @version $Id$
*/
abstract class DelScript extends Script {
 
private $Bdd = null;
private $projetNom = null;
 
public function getProjetNom() {
return $this->projetNom;
}
 
protected function initialiserProjet($projetNom) {
$this->projetNom = $projetNom;
}
//+------------------------------------------------------------------------------------------------------+
// Méthodes d'url
/**
* Formate une url à partir d'un template contenant des paramètres à remplacer sous la forme {monParametre}.
* Le tableau associatif de paramètres doit contenir en clé le paramêtre (monParametre) sans les accolades,
* la valeur correspondante sera la valeur de remplacement.
* Par défaut, les parametres suivant sont pris en compte par cette méthode :
* - {projet} : le code du référentiel courrant ou définit dans le constructeur de l'objet métier.
*
* @param String $tpl le squelette d'url à formater.
* @param Array $parametres le tableau de parametres (sans accolades pour les clés).*/
public function formaterUrl($tpl, Array $parametres) {
foreach($parametres as $key=> $value) {
$tpl = str_replace('{'.$key.'}',rawurlencode($value),$tpl);
}
return $tpl;
}
 
//+------------------------------------------------------------------------------------------------------+
// Méthodes d'accès aux objets du Framework
/**
* Méthode de connection à la base de données sur demande.
* Tous les scripts n'ont pas besoin de s'y connecter.
*/
public function getBdd() {
if (! isset($this->Bdd)) {
$this->Bdd = new Bdd();
}
return $this->Bdd;
}
//+----------------------------------------------------------------------------------------------------------------+
// GESTION DES SQUELETTES PHP
 
/**
* Méthode prenant en paramètre un chemin de fichier squelette et un tableau associatif de données,
* en extrait les variables, charge le squelette et retourne le résultat des deux combinés.
*
* @param String $fichier le chemin du fichier du squelette
* @param Array $donnees un tableau associatif contenant les variables a injecter dans le squelette.
*
* @return boolean false si le squelette n'existe pas, sinon la chaine résultat.
*/
public function traiterSquelettePhp($fichier, Array $donnees = array()) {
$sortie = false;
if (file_exists($fichier)) {
// Extraction des variables du tableau de données
extract($donnees);
// Démarage de la bufferisation de sortie
ob_start();
// Si les tags courts sont activés
if ((bool) @ini_get('short_open_tag') === true) {
// Simple inclusion du squelette
include $fichier;
} else {
// Sinon, remplacement des tags courts par la syntaxe classique avec echo
$html_et_code_php = self::traiterTagsCourts($fichier);
// Pour évaluer du php mélangé dans du html il est nécessaire de fermer la balise php ouverte par eval
$html_et_code_php = '?>'.$html_et_code_php;
// Interprétation du html et du php dans le buffer
echo eval($html_et_code_php);
}
// Récupèration du contenu du buffer
$sortie = ob_get_contents();
// Suppression du buffer
@ob_end_clean();
} else {
$msg = "Le fichier du squelette '$fichier' n'existe pas.";
trigger_error($msg, E_USER_WARNING);
}
// Retourne le contenu
return $sortie;
}
 
/**
* Fonction chargeant le contenu du squelette et remplaçant les tags court php (<?= ...) par un tag long avec echo.
*
* @param String $chemin_squelette le chemin du fichier du squelette
*
* @return string le contenu du fichier du squelette php avec les tags courts remplacés.
*/
private function traiterTagsCourts($chemin_squelette) {
$contenu = file_get_contents($chemin_squelette);
// Remplacement de tags courts par un tag long avec echo
$contenu = str_replace('<?=', '<?php echo ', $contenu);
// Ajout systématique d'un point virgule avant la fermeture php
$contenu = preg_replace("/;*\s*\?>/", "; ?>", $contenu);
return $contenu;
}
}
?>
/tags/v1.1-helium/scripts/cli.php
New file
0,0 → 1,37
<?php
// Encodage : UTF-8
// +-------------------------------------------------------------------------------------------------------------------+
/**
* Initialise le chargement et l'exécution des scripts
*
* Lancer ce fichier en ligne de commande avec :
* <code>/opt/lampp/bin/php cli.php mon_script -a test</code>
*
//Auteur original :
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Delphine CAUQUIL <delphine@tela-botanica.org>
* @copyright Tela-Botanica 1999-2008
* @licence GPL v3 & CeCILL v2
* @version $Id$
*/
// +-------------------------------------------------------------------------------------------------------------------+
 
// Le fichier Framework.php du Framework de Tela Botanica doit être appelée avant tout autre chose dans l'application.
// Sinon, rien ne sera chargé.
// Chemin du fichier chargeant le framework requis
$framework = dirname(__FILE__).DIRECTORY_SEPARATOR.'framework.php';
if (!file_exists($framework)) {
$e = "Veuillez paramétrer l'emplacement et la version du Framework dans le fichier $framework";
trigger_error($e, E_USER_ERROR);
} else {
// Inclusion du Framework
require_once $framework;
 
// Ajout d'information concernant cette application
Framework::setCheminAppli(__FILE__);// Obligatoire
Framework::setInfoAppli(Config::get('info'));
 
// Initialisation et lancement du script appelé en ligne de commande
Cli::executer();
}
?>
/tags/v1.1-helium/scripts
New file
Property changes:
Added: svn:ignore
+framework.php
/tags/v1.1-helium/src/org/tela_botanica/del/uitest/ComparaisonEfloreVueTest.java
New file
0,0 → 1,42
package org.tela_botanica.del.uitest;
 
import org.tela_botanica.del.client.modeles.Image;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.vues.comparaisoneflore.ComparaisonEfloreVue;
 
import com.google.gwt.junit.client.GWTTestCase;
 
public class ComparaisonEfloreVueTest extends GWTTestCase {
 
// To run this test configure your junit launcher (Eclipse>Run>Run configurations
// classpath>Advanced>Select Folders and choose src/)
 
@Override
public String getModuleName() {
return "org.tela_botanica.del.Del";
}
 
public void testLoginView() {
 
Observation observation = new Observation();
String auteur = "benjamin";
observation.setAuteur(auteur);
observation.setNomRetenu("marronier");
observation.setNumNomenclatural("num nomenclatural ");
observation.setDateReleve("28/09/2011");
observation.setFamille("famille ");
observation.setLocalite("localite ");
 
Image image = new Image();
image.setIdImage("id image 1");
image.setUrlFormat("http://www.tela-botanica.org/appli:cel-img:00001%s%.jpg");
image.setUrl("http://www.tela-botanica.org/appli:cel-img:00001CRS.jpg");
image.setMiniature("http://www.tela-botanica.org/appli:cel-img:00001XS.jpg");
image.setObservation(observation);
 
ComparaisonEfloreVue vue = new ComparaisonEfloreVue();
vue.chargerImagePrincipale(image);
assertTrue(vue.getNomAuteur().getText().contains("benjamin"));
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/cache/CacheClient.java
New file
0,0 → 1,428
package org.tela_botanica.del.client.cache;
 
import java.util.Arrays;
import java.util.List;
 
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.gestionhistorique.ConstantesNavigation;
import org.tela_botanica.del.client.modeles.Image;
import org.tela_botanica.del.client.modeles.InformationsRecherche;
import org.tela_botanica.del.client.modeles.ModeTri;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.modeles.Protocole;
import org.tela_botanica.del.client.modeles.Utilisateur;
import org.tela_botanica.del.client.utils.URLUtils;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Window.Location;
 
public class CacheClient {
 
private List<Protocole> listeProtocoles;
private String home = ConstantesNavigation.PAGE_RECHERCHE_OBSERVATIONS;
private Observation observationCourante;
private Image imageCourante;
private String taxonPourRechercheEflore;
private String idProtocoleEnAttente = null;
private Protocole protocoleCourant;
private String referentielCourant;
private int numPageRechercheImage = 0;
private int nbTotalImagesRecherchees = 0;
private boolean referentielNonModifiable = false;
 
private int pasPagination = 12;
private int pageCouranteRechercheImage = 1;
private int pageCouranteRechercheObservations = 1;
private InformationsRecherche informationsRechercheImage;
private InformationsRecherche informationsRechercheObservation;
private Utilisateur utilisateur;
private String pageCourante = home;
private String statut;
private String[] statutsPossibles = {ConstantesNavigation.PARAM_TYPE_TOUS,
ConstantesNavigation.PARAM_TYPE_A_DETERMINER,
ConstantesNavigation.PARAM_TYPE_EN_DISCUSSION,
ConstantesNavigation.PARAM_TYPE_VALIDEES};
public void supprimerFiltreStatut() {
this.statut = null;
}
public void setFiltreStatut(String statut) {
this.statut = statut;
}
public String getFiltreStatut() {
return this.statut;
}
public String getPageCourante() {
return pageCourante;
}
 
public void setPageCourante(String pageCourante) {
this.pageCourante = pageCourante;
}
 
private static CacheClient instance;
 
private CacheClient() {
instance = this;
}
 
public void initialiserAvecParametres() {
if(Location.getPath().contains("identiplante")) {
if(Location.getHash().contains(ConstantesNavigation.PAGE_VALIDATION)) {
setPageCourante(ConstantesNavigation.PAGE_VALIDATION+"~"+URLUtils.getURLSpecialParameterValue());
} else {
setPageCourante(ConstantesNavigation.PAGE_RECHERCHE_OBSERVATIONS);
}
} else if(Location.getPath().contains("pictoflora")) {
if(Location.getHash().contains(ConstantesNavigation.PAGE_VALIDATION_PICTOFLORA)) {
setPageCourante(ConstantesNavigation.PAGE_VALIDATION+URLUtils.getURLSpecialParameterValue());
} else {
setPageCourante(ConstantesNavigation.PAGE_RECHERCHE_IMAGES);
}
}
String rechercheLibre = Location.getParameter("masque");
String famille = Location.getParameter("masque.famille");
String taxon = Location.getParameter("masque.ns");
String genre = Location.getParameter("masque.genre");
String commune = Location.getParameter("masque.commune");
String dept = Location.getParameter("masque.departement");
String auteur = Location.getParameter("masque.auteur");
String date = Location.getParameter("masque.date");
String tag = Location.getParameter("masque.tag");
String tagCel = Location.getParameter("masque.tag_cel");
String tagDel = Location.getParameter("masque.tag_pictoflora");
String referentiel = Location.getParameter("masque.referentiel");
String protocole = Location.getParameter("protocole");
String statutParam = Location.getParameter("masque.type");
String page = Location.getParameter("page");
Integer pageInt = null;
try {
pageInt = Integer.parseInt(page);
} catch (Exception e) {
pageInt = null;
}
String pas = Location.getParameter("pas");
Integer pasInt = null;
if(pas != null) {
try {
pasInt = Integer.parseInt(pas);
} catch (Exception e) {
pasInt = null;
}
}
InformationsRecherche rechercheParArguments = new InformationsRecherche();
rechercheParArguments.setRechercheLibre(rechercheLibre);
rechercheParArguments.setFamille(famille);
rechercheParArguments.setTaxon(taxon);
rechercheParArguments.setGenre(genre);
rechercheParArguments.setCommune(commune);
rechercheParArguments.setDepartement(dept);
rechercheParArguments.setAuteur(auteur);
rechercheParArguments.setDate(date);
rechercheParArguments.setTag(tag);
if(protocole != null && !protocole.equals("")) {
CacheClient.getInstance().setIdProtocoleEnAttente(protocole);
rechercheParArguments.setIdProtocoleSelectionne(protocole);
} else if(URLUtils.getURLSpecialParameterValue() != null) {
CacheClient.getInstance().setIdProtocoleEnAttente(URLUtils.getURLSpecialParameterValue());
rechercheParArguments.setIdProtocoleSelectionne(URLUtils.getURLSpecialParameterValue());
}
if(pasInt != null) setPasPagination(pasInt);
if(pageCourante.equals(ConstantesNavigation.PAGE_RECHERCHE_IMAGES)) {
rechercheParArguments.setMotClefCel(tagCel);
rechercheParArguments.setMotClefDel(tagDel);
if(pageInt != null) setPageCouranteRechercheImages(pageInt);
} else {
if(pageInt != null) setPageCouranteRechercheObservations(pageInt);
}
String tri = Location.getParameter("tri");
String ordre = Location.getParameter("ordre");
if(tri != null) {
ModeTri modeTri = ModeTri.TRI_ASCENDANT;
if(ordre != null && ordre.equals("asc")) {
modeTri = ModeTri.TRI_ASCENDANT;
}
if(ordre != null && ordre.equals("desc")) {
modeTri = ModeTri.TRI_DESCENDANT;
}
if(tri.equals("votes")) {
rechercheParArguments.setTriParNbVotes(modeTri);
}
if(tri.equals("tags")) {
rechercheParArguments.setTriParNbTags(modeTri);
}
if(tri.equals("date_observation")) {
rechercheParArguments.setTriParDate(modeTri);
}
}
rechercheParArguments.setMotClef(tag);
// si le référentiel est passé dans l'url alors il ne doit pas être modifiable
if(referentiel != null && !referentiel.equals("")) {
setReferentielCourant(referentiel);
rechercheParArguments.setReferentiel(referentiel);
referentielNonModifiable = true;
}
if(Location.getParameterMap().size() == 0) {
// par défaut l'application s'ouvre sur l'onglet à déterminer
statut = ConstantesNavigation.PARAM_TYPE_DEFAUT;
} else {
if(Arrays.asList(statutsPossibles).contains(statutParam)) {
statut = statutParam;
} else {
statut = ConstantesNavigation.PARAM_TYPE_DEFAUT;
}
}
informationsRechercheImage = rechercheParArguments;
informationsRechercheObservation = rechercheParArguments;
mettreAjourUrlCourante();
}
public void setIdProtocoleEnAttente(String idProtocole) {
idProtocoleEnAttente = idProtocole;
}
public String getIdProtocoleEnAttente() {
return idProtocoleEnAttente;
}
 
public Utilisateur getUtilisateur() {
if (this.utilisateur == null) {
this.utilisateur = new Utilisateur(null, null);
}
return this.utilisateur;
}
public void setUtilisateur(Utilisateur utilisateur) {
this.utilisateur = utilisateur;
}
public void setHome(String home) {
this.home = home;
setPageCourante(home);
}
public String getHome() {
return home;
}
public Observation getObservationCourante() {
return observationCourante;
}
 
public void setObservationCourante(Observation observationCourante) {
this.observationCourante = observationCourante;
}
 
public static CacheClient getInstance() {
if (instance == null) {
instance = new CacheClient();
}
return instance;
}
 
public String getTaxonPourRechercheEflore() {
return taxonPourRechercheEflore;
}
 
public void setTaxonPourRechercheEflore(String taxonPourRechercheEflore) {
this.taxonPourRechercheEflore = taxonPourRechercheEflore;
}
 
public int getNumPageRechercheImage() {
return numPageRechercheImage;
}
 
// Pour la recherche :
public int getPasPagination() {
return pasPagination;
}
 
public void setPasPagination(int pasPagination) {
this.pasPagination = pasPagination;
}
 
public void setPageCouranteRechercheImages(int pageCouranteRecherche) {
this.pageCouranteRechercheImage = pageCouranteRecherche;
}
 
public int getPageCouranteRechercheImage() {
return this.pageCouranteRechercheImage;
}
 
public void setNbTotalImagesRecherchees(int nbTotalImagesRecherchees) {
this.nbTotalImagesRecherchees = nbTotalImagesRecherchees;
}
 
public int getNbTotalImagesRecherchees() {
return this.nbTotalImagesRecherchees;
}
 
public Image getImageCourante() {
return imageCourante;
}
 
public void setImageCourante(Image imageCourante) {
this.imageCourante = imageCourante;
}
public void setListeProtocoles(List<Protocole> listeProtocole) {
this.listeProtocoles = listeProtocole;
}
public List<Protocole> getListeProtocoles() {
return this.listeProtocoles;
}
 
public Protocole getProtocoleCourant() {
return protocoleCourant;
}
 
public void setProtocoleCourant(Protocole protocoleCourant) {
this.protocoleCourant = protocoleCourant;
}
 
public InformationsRecherche getInformationsRechercheImage() {
if(informationsRechercheImage == null) {
informationsRechercheImage = new InformationsRecherche();
}
return informationsRechercheImage;
}
 
public InformationsRecherche getInformationsRechercheObservation() {
if(informationsRechercheObservation == null) {
informationsRechercheObservation = new InformationsRecherche();
}
return informationsRechercheObservation;
}
 
public void setInformationsRechercheImage(InformationsRecherche informationsRechercheImage) {
this.informationsRechercheImage = informationsRechercheImage;
}
 
public void setInformationsRechercheObservation(InformationsRecherche informationsRechercheObservation) {
this.informationsRechercheObservation = informationsRechercheObservation;
}
 
public int getPageCouranteRechercheObservations() {
return pageCouranteRechercheObservations;
}
 
public void setPageCouranteRechercheObservations(int pageCouranteRechercheObservations) {
this.pageCouranteRechercheObservations = pageCouranteRechercheObservations;
}
public void setReferentielCourant(String referentielCourant) {
this.referentielCourant = referentielCourant;
}
public String getReferentielCourant() {
return referentielCourant;
}
public void setReferentielNonModifiable(boolean referentielNonModifiable) {
this.referentielNonModifiable = referentielNonModifiable;
}
public boolean getReferentielNonModifiable() {
return referentielNonModifiable;
}
public String genererUrlCourante() {
String url = Window.Location.getHref();
String arguments = "";
String argumentsRecherche = "";
if (getPageCourante().equals(ConstantesNavigation.PAGE_RECHERCHE_IMAGES)) {
InformationsRecherche infoRecherche;
infoRecherche = getInformationsRechercheImage();
if (CacheClient.getInstance().getProtocoleCourant() != null) {
infoRecherche.setIdProtocoleSelectionne(""+CacheClient.getInstance().getProtocoleCourant().getId());
}
argumentsRecherche = infoRecherche.versChaineRequete();
if(!GWT.isScript()) {
argumentsRecherche += "&gwt.codesvr="+Location.getParameter("gwt.codesvr")+"";
}
argumentsRecherche += (argumentsRecherche.isEmpty()) ? "" : "&";
argumentsRecherche += "page="+getPageCouranteRechercheImage()+"&pas="+getPasPagination();
argumentsRecherche = (argumentsRecherche.isEmpty()) ? argumentsRecherche : "?" + argumentsRecherche;
arguments = argumentsRecherche;
url = new Config().getUrl("pictoflora") + arguments;
url += "#"+ConstantesNavigation.PAGE_RECHERCHE_IMAGES;
} else if (getPageCourante().equals(ConstantesNavigation.PAGE_RECHERCHE_OBSERVATIONS) || getPageCourante().equals("")) {
InformationsRecherche infoRecherche;
infoRecherche = getInformationsRechercheObservation();
argumentsRecherche = "masque.type="+statut;
argumentsRecherche += "&page="+getPageCouranteRechercheObservations()+"&pas="+getPasPagination();
argumentsRecherche += "&"+infoRecherche.versChaineRequete();
if(!GWT.isScript()) {
argumentsRecherche += "&gwt.codesvr="+Location.getParameter("gwt.codesvr")+"";
}
arguments = "?"+argumentsRecherche;
url = new Config().getUrl("identiplante") + arguments;
url += "#"+ConstantesNavigation.PAGE_RECHERCHE_OBSERVATIONS;
} else if (getPageCourante().contains(ConstantesNavigation.PAGE_VALIDATION) || getPageCourante().contains(ConstantesNavigation.PAGE_VALIDATION_PICTOFLORA)) {
url = new Config().getUrl("del");
if(getPageCourante().contains(ConstantesNavigation.PAGE_VALIDATION)) {
url = new Config().getUrl("identiplante");
} else {
url = new Config().getUrl("pictoflora");
}
if(!GWT.isScript()) {
url += "?gwt.codesvr="+Location.getParameter("gwt.codesvr");
}
url += "#"+getPageCourante();
}
// remplacements batards pour corriger l'url
// TODO: factoriser toute la fonction
url = url.replaceAll("&#", "#");
url = url.replaceAll("&&", "&");
url = url.replaceAll("\\?&", "?");
return url;
}
public void mettreAjourUrlCourante() {
mettreAJourUrlCouranteSansRecharger(genererUrlCourante());
}
private static native void mettreAJourUrlCouranteSansRecharger(String nouvelleUrl) /*-{
// javascript double negative trick
// pour plus d'info http://stackoverflow.com/questions/4686583/can-someone-explain-this-double-negative-trick
if(!!($wnd.history && $wnd.history.pushState)) {
$wnd.history.pushState(nouvelleUrl, "", nouvelleUrl);
}
}-*/;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/VoteProtocoleService.java
New file
0,0 → 1,21
package org.tela_botanica.del.client.services.rest;
 
import java.util.List;
 
import org.tela_botanica.del.client.modeles.VoteProtocole;
import org.tela_botanica.del.client.services.rest.async.AjoutVoteProtocoleCallback;
import org.tela_botanica.del.client.services.rest.async.VoteProtocoleCallback;
 
public interface VoteProtocoleService {
public List<VoteProtocole> getVote(String idImage);
 
public List<VoteProtocole> getVotePourImageEtProtocole(String idImage, String protocolName);
 
void ajouterVote(String idImage, VoteProtocole voteProtocole, AjoutVoteProtocoleCallback callback);
 
public void modifierVote(String idImage, VoteProtocole voteProtocole, VoteProtocoleCallback vpc);
public void supprimerVote(String idImage, VoteProtocole voteProtocole, VoteProtocoleCallback vpc);
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/ProtocoleService.java
New file
0,0 → 1,11
package org.tela_botanica.del.client.services.rest;
 
import org.tela_botanica.del.client.services.rest.async.ProtocolesCallback;
 
public interface ProtocoleService {
 
public void getProtocole(String nomProtocole);
 
public void getProtocoles(ProtocolesCallback pc);
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/MotsClesServiceConcret.java
New file
0,0 → 1,77
package org.tela_botanica.del.client.services.rest;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.services.rest.async.AjoutMotsClesImageCallback;
import org.tela_botanica.del.client.services.rest.async.ListeMotsClesImageCallBack;
import org.tela_botanica.del.client.services.rest.async.PHPCallback.ModeRequete;
import org.tela_botanica.del.client.services.rest.async.SuppressionMotCleImageCallback;
 
import org.tela_botanica.del.client.services.RequestBuilderWithCredentials;
import com.google.gwt.http.client.URL;
 
public class MotsClesServiceConcret implements MotsClesService {
 
private String baseUrl;
public MotsClesServiceConcret() {
Config config = new Config();
this.baseUrl = config.getServiceBaseUrl();
}
public MotsClesServiceConcret(Config config) {
this.baseUrl = config.getServiceBaseUrl();
}
@Override
public void getMotsClesImage(String idImage,
ListeMotsClesImageCallBack callback) {
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.GET, baseUrl + "mots-cles" + assemblerChaineRequete(idImage));
callback.setMode(ModeRequete.LECTURE);
try {
rb.sendRequest(null, callback);
} catch (Exception e) {
// TODO: handle exception
}
}
private String assemblerChaineRequete(String idImage) {
String chaineRequete = "?masque.image="+idImage;
return chaineRequete;
}
 
@Override
public void ajouterMotCleImage(String idImage, String motCle,
AjoutMotsClesImageCallback callback) {
String urlService = baseUrl+"mots-cles/";
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.PUT, urlService);
callback.setMode(ModeRequete.AJOUT);
String chainePost = assemblerChaineRequeteAjout(idImage, motCle);
try {
rb.sendRequest(chainePost, callback);
} catch (Exception e) {
//TODO: quoi faire si la requete est mal formée coté client avant d'être envoyée ?
}
 
}
 
private String assemblerChaineRequeteAjout(String idImage, String motCle) {
return "image="+URL.encodeQueryString(idImage)+
"&mot_cle="+URL.encodeQueryString(motCle)+
"&"+URL.encodeQueryString("auteur.id")+"="+URL.encodeQueryString(CacheClient.getInstance().getUtilisateur().getId());
}
 
@Override
public void supprimerMotCleImage(String idMotCle, SuppressionMotCleImageCallback callback) {
String urlService = baseUrl+"mots-cles/"+idMotCle;
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.DELETE, urlService);
callback.setMode(ModeRequete.SUPPRESSION);
try {
rb.sendRequest(null, callback);
} catch (Exception e) {
//TODO: quoi faire si la requete est mal formée coté client avant d'être envoyée ?
}
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/PropositionDeterminationService.java
New file
0,0 → 1,13
package org.tela_botanica.del.client.services.rest;
 
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.services.rest.async.PropositionDeterminationCallBack;
import org.tela_botanica.del.client.services.rest.async.SuppressionPropositionDeterminationCallback;
import org.tela_botanica.del.client.services.rest.async.ValidationPropositionCallback;
 
public interface PropositionDeterminationService {
 
public void ajouterProposition(PropositionDetermination proposition, PropositionDeterminationCallBack callback);
public void supprimerProposition(PropositionDetermination proposition, SuppressionPropositionDeterminationCallback callback);
public void validerProposition(PropositionDetermination proposition, ValidationPropositionCallback validationPropositionCallback);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/ObservationServiceConcret.java
New file
0,0 → 1,56
package org.tela_botanica.del.client.services.rest;
 
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.modeles.InformationsRecherche;
import org.tela_botanica.del.client.services.rest.async.ObservationsCallback;
import org.tela_botanica.del.client.services.rest.async.PHPCallback.ModeRequete;
 
import org.tela_botanica.del.client.services.RequestBuilderWithCredentials;
 
public class ObservationServiceConcret implements ObservationService {
 
private String baseUrl;
 
public ObservationServiceConcret() {
Config config = new Config();
this.baseUrl = config.getServiceBaseUrl();
}
public ObservationServiceConcret(Config config) {
this.baseUrl = config.getServiceBaseUrl();
}
@Override
public void getObservations(InformationsRecherche infos, int debut, int fin, String statut, ObservationsCallback callback) {
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.GET, baseUrl + "observations" + assemblerChaineRequete(infos, debut, fin, statut));
callback.setMode(ModeRequete.LECTURE);
try {
rb.sendRequest(null, callback);
} catch (Exception e) {
// TODO: handle exception
}
}
 
private String assemblerChaineRequete(InformationsRecherche infos, int debut, int fin, String statut) {
 
String chaineRequete = "?navigation.depart=" + debut + "&navigation.limite=" + (fin - debut);
if (statut != null && !statut.equals("tous")) {
chaineRequete += "&masque.type=" + statut;
}
chaineRequete+= infos.versChaineRequete();
 
return chaineRequete;
}
 
@Override
public void getObservation(String idObservation,
ObservationsCallback callback) {
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.GET, baseUrl + "observations/"+idObservation);
callback.setMode(ModeRequete.LECTURE);
try {
rb.sendRequest(null, callback);
} catch (Exception e) {
// TODO: handle exception
}
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/UtilisateurService.java
New file
0,0 → 1,11
package org.tela_botanica.del.client.services.rest;
 
import org.tela_botanica.del.client.services.rest.async.UtilisateurCallback;
 
public interface UtilisateurService {
public void connecterUtilisateur(String login, String motDePasse, UtilisateurCallback callback);
public void deconnecterUtilisateur(UtilisateurCallback callback);
public void obtenirUtilisateur(UtilisateurCallback callback);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/ObservationsCallback.java
New file
0,0 → 1,21
package org.tela_botanica.del.client.services.rest.async;
 
import org.tela_botanica.del.client.modeles.ObservationServiceResultat;
import org.tela_botanica.del.client.utils.UtilitairesServiceResultat;
 
import com.google.gwt.json.client.JSONParser;
 
/**
* Objet passé en paramètre d'un service de recuperation d'observations
*
* @author LIENS
*
*/
public abstract class ObservationsCallback extends PHPCallback<ObservationServiceResultat> {
 
@Override
public ObservationServiceResultat parserJSON(String retourService) {
return UtilitairesServiceResultat.parserObservationServiceResultat(JSONParser.parseStrict(retourService));
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/SuppressionCommentaireCallback.java
New file
0,0 → 1,9
package org.tela_botanica.del.client.services.rest.async;
 
public abstract class SuppressionCommentaireCallback extends PHPCallback<String> {
 
@Override
public String parserJSON(String retourService) {
return null;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/ImagesParTaxonCallback.java
New file
0,0 → 1,24
package org.tela_botanica.del.client.services.rest.async;
 
import org.tela_botanica.del.client.modeles.ImageServiceResultat;
import org.tela_botanica.del.client.utils.UtilitairesServiceResultat;
 
import com.google.gwt.json.client.JSONParser;
 
/**
*
* Objet passé en paramètre d'un service d'ajout de recuperation des images pour
* un taxon
*
* @author LIENS
*
*/
public abstract class ImagesParTaxonCallback extends PHPCallback<ImageServiceResultat> {
 
@Override
public ImageServiceResultat parserJSON(String retourService) {
ImageServiceResultat resultat = UtilitairesServiceResultat.parserImageServiceResultat(JSONParser.parseStrict(retourService));
return resultat;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/SuppressionPropositionDeterminationCallback.java
New file
0,0 → 1,9
package org.tela_botanica.del.client.services.rest.async;
 
public abstract class SuppressionPropositionDeterminationCallback extends PHPCallback<String> {
 
@Override
public String parserJSON(String retourService) {
return null;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/ListeVotesDeterminationCallback.java
New file
0,0 → 1,22
package org.tela_botanica.del.client.services.rest.async;
 
import java.util.HashMap;
 
import org.tela_botanica.del.client.modeles.VoteDetermination;
import org.tela_botanica.del.client.utils.UtilitairesServiceResultat;
 
/**
* Objet passé en paramètre d'un service de recuperation de la liste de votes
* sur une determination
*
* @author LIENS
*
*/
public abstract class ListeVotesDeterminationCallback extends PHPCallback<HashMap<String, VoteDetermination>> {
 
@Override
public HashMap<String, VoteDetermination> parserJSON(String retourService) {
return UtilitairesServiceResultat.parserRetourListeVotesDetermination(retourService);
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/PHPCallback.java
New file
0,0 → 1,87
package org.tela_botanica.del.client.services.rest.async;
 
import org.tela_botanica.del.client.utils.StringUtils;
 
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.Response;
import com.google.gwt.json.client.JSONException;
import com.google.gwt.user.client.Window;
 
/**
* Cette classe correspond au retour asynchrone d'un webservice php qui retourne
* l'objet generique T si l'appel de service est un succcès
*
* @author LIENS
*
* @param <T>
*/
public abstract class PHPCallback<T> implements RequestCallback {
 
public enum ModeRequete {
AJOUT, MODIFICATION, SUPPRESSION, LECTURE
}
 
protected ModeRequete mode;
 
public PHPCallback() {
}
 
public void setMode(ModeRequete mode) {
this.mode = mode;
}
 
@Override
public void onResponseReceived(Request request, Response response) {
int statusCode = response.getStatusCode();
int codeAttendu = 500;
switch (mode) {
case AJOUT:
codeAttendu = 201;
break;
case MODIFICATION:
codeAttendu = 200;
break;
case SUPPRESSION:
codeAttendu = 200;
break;
case LECTURE:
codeAttendu = 200;
break;
default:
codeAttendu = 500;
break;
}
 
if (statusCode == codeAttendu) {
try {
T reponseParsee = parserJSON(response.getText());
surRetour(reponseParsee);
} catch (JSONException e) {
StringUtils.logChaine("Une erreur est survenue, le serveur a répondu : "+response.getText());
}
} else {
surErreur("Erreur " + statusCode + ": " + response.getText());
}
}
 
/**
* Cette methode permet de pareser le JSON retourné par le webservice pour
* le transformer en objet métier
*
* @param retourService
* @return
*/
public abstract T parserJSON(String retourService);
 
@Override
public void onError(Request request, Throwable exception) {
surErreur(exception.getMessage());
}
 
public abstract void surRetour(T objetRetour);
 
public void surErreur(String messageErreur) {
Window.alert(messageErreur);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/ModificationPreferencesCallback.java
New file
0,0 → 1,15
package org.tela_botanica.del.client.services.rest.async;
 
/**
* Objet passé en paramètre d'un service de modification des préférences utilisateur
* @author LIENS
*
*/
public abstract class ModificationPreferencesCallback extends PHPCallback<String>{
 
@Override
public String parserJSON(String retourService) {
return null;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/ListeCommentairesCallback.java
New file
0,0 → 1,22
package org.tela_botanica.del.client.services.rest.async;
 
import java.util.List;
 
import org.tela_botanica.del.client.modeles.Commentaire;
import org.tela_botanica.del.client.utils.UtilitairesServiceResultat;
 
import com.google.gwt.json.client.JSONParser;
 
/**
* Objet passé en paramètre d'un service de recuperation d'une liste de commentaires
* @author LIENS
*
*/
public abstract class ListeCommentairesCallback extends PHPCallback<List<Commentaire>> {
 
@Override
public List<Commentaire> parserJSON(String retourService) {
return UtilitairesServiceResultat.parserCommentaires(JSONParser.parseStrict(retourService).isObject().get("resultats").isObject());
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/ProtocolesCallback.java
New file
0,0 → 1,22
package org.tela_botanica.del.client.services.rest.async;
 
import org.tela_botanica.del.client.modeles.ProtocoleServiceResultat;
import org.tela_botanica.del.client.utils.UtilitairesServiceResultat;
 
import com.google.gwt.json.client.JSONParser;
 
/**
* Objet passé en paramètre d'un service de recuperation de la liste des
* protocoles
*
* @author LIENS
*
*/
public abstract class ProtocolesCallback extends PHPCallback<ProtocoleServiceResultat> {
 
@Override
public ProtocoleServiceResultat parserJSON(String retourService) {
return UtilitairesServiceResultat.parserProtocoleServiceResultat(JSONParser.parseStrict(retourService));
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/ListeMotsClesImageCallBack.java
New file
0,0 → 1,16
package org.tela_botanica.del.client.services.rest.async;
 
import java.util.List;
 
import org.tela_botanica.del.client.modeles.MotCle;
import org.tela_botanica.del.client.utils.UtilitairesServiceResultat;
 
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.user.client.Window;
 
public abstract class ListeMotsClesImageCallBack extends PHPCallback<List<MotCle>> {
@Override
public List<MotCle> parserJSON(String retourService) {
return UtilitairesServiceResultat.parserRetourListeMotsClesImage(JSONParser.parseStrict(retourService).isObject().get("resultats").isObject());
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/AjoutMotsClesImageCallback.java
New file
0,0 → 1,8
package org.tela_botanica.del.client.services.rest.async;
 
public abstract class AjoutMotsClesImageCallback extends PHPCallback<Void> {
@Override
public Void parserJSON(String retourService) {
return null;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/ValidationPropositionCallback.java
New file
0,0 → 1,9
package org.tela_botanica.del.client.services.rest.async;
 
public abstract class ValidationPropositionCallback extends PHPCallback<String> {
 
@Override
public String parserJSON(String retourService) {
return retourService;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/SuppressionMotCleImageCallback.java
New file
0,0 → 1,9
package org.tela_botanica.del.client.services.rest.async;
 
public abstract class SuppressionMotCleImageCallback extends PHPCallback<String> {
 
@Override
public String parserJSON(String retourService) {
return null;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/ListePreferencesCallback.java
New file
0,0 → 1,19
package org.tela_botanica.del.client.services.rest.async;
 
import java.util.HashMap;
 
import org.tela_botanica.del.client.utils.UtilitairesServiceResultat;
 
import com.google.gwt.json.client.JSONParser;
 
/**
* Objet passé en paramètre d'un service de chargement des préférences utilisateur
*
*/
public abstract class ListePreferencesCallback extends PHPCallback<HashMap<String, String>>{
 
@Override
public HashMap<String, String> parserJSON(String retourService) {
return UtilitairesServiceResultat.parserPreferencesUtilisateur(JSONParser.parseStrict(retourService));
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/AjoutVoteDeterminationCallback.java
New file
0,0 → 1,15
package org.tela_botanica.del.client.services.rest.async;
 
/**
* Objet passé en paramètre d'un service d'ajout de vote sur une determination
* @author LIENS
*
*/
public abstract class AjoutVoteDeterminationCallback extends PHPCallback<Void> {
 
@Override
public Void parserJSON(String retourService) {
return null;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/VoteProtocoleCallback.java
New file
0,0 → 1,15
package org.tela_botanica.del.client.services.rest.async;
 
/**
* Objet passé en paramètre d'un service d'ajout de votes
* @author LIENS
*
*/
public abstract class VoteProtocoleCallback extends PHPCallback<Void> {
 
@Override
public Void parserJSON(String retourService) {
return null;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/AjoutCommentaireCallback.java
New file
0,0 → 1,19
package org.tela_botanica.del.client.services.rest.async;
 
import org.tela_botanica.del.client.utils.UtilitairesServiceResultat;
 
import com.google.gwt.json.client.JSONParser;
 
/**
* Objet passé en paramètre d'un service d'ajout de commentaire
* @author LIENS
*
*/
public abstract class AjoutCommentaireCallback extends PHPCallback<String>{
 
@Override
public String parserJSON(String retourService) {
return UtilitairesServiceResultat.parserRetourAjoutCommentaire(JSONParser.parseStrict(retourService).isObject());
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/AjoutVoteProtocoleCallback.java
New file
0,0 → 1,13
package org.tela_botanica.del.client.services.rest.async;
 
import org.tela_botanica.del.client.utils.UtilitairesServiceResultat;
 
import com.google.gwt.json.client.JSONParser;
 
public abstract class AjoutVoteProtocoleCallback extends PHPCallback<String> {
 
@Override
public String parserJSON(String retourService) {
return UtilitairesServiceResultat.parserRetourAjoutVoteProtocole(JSONParser.parseStrict(retourService).isObject());
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/PropositionDeterminationCallBack.java
New file
0,0 → 1,19
package org.tela_botanica.del.client.services.rest.async;
 
import org.tela_botanica.del.client.utils.UtilitairesServiceResultat;
 
import com.google.gwt.json.client.JSONParser;
 
/**
* Objet passé en paramètre d'un service d'ajout de determination
* @author LIENS
*
*/
public abstract class PropositionDeterminationCallBack extends PHPCallback<String> {
 
@Override
public String parserJSON(String retourService) {
return UtilitairesServiceResultat.parserRetourAjoutCommentaire(JSONParser.parseStrict(retourService).isObject());
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/async/UtilisateurCallback.java
New file
0,0 → 1,20
package org.tela_botanica.del.client.services.rest.async;
 
import org.tela_botanica.del.client.modeles.Utilisateur;
import org.tela_botanica.del.client.utils.UtilitairesServiceResultat;
 
import com.google.gwt.json.client.JSONParser;
 
/**
* Objet passé en paramètre d'un service de recuperation d'un utilisateur
* @author LIENS
*
*/
public abstract class UtilisateurCallback extends PHPCallback<Utilisateur> {
 
@Override
public Utilisateur parserJSON(String retourService) {
return UtilitairesServiceResultat.parserUtilisateurJson(JSONParser.parseStrict(retourService));
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/VoteDeterminationServiceConcret.java
New file
0,0 → 1,95
package org.tela_botanica.del.client.services.rest;
 
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.modeles.VoteDetermination;
import org.tela_botanica.del.client.services.rest.async.AjoutVoteDeterminationCallback;
import org.tela_botanica.del.client.services.rest.async.ListeVotesDeterminationCallback;
import org.tela_botanica.del.client.services.rest.async.PHPCallback.ModeRequete;
 
import org.tela_botanica.del.client.services.RequestBuilderWithCredentials;
import com.google.gwt.user.client.Window;
 
public class VoteDeterminationServiceConcret implements VoteDeterminationService {
 
private String baseUrl;
 
public VoteDeterminationServiceConcret() {
Config config = new Config();
this.baseUrl = config.getServiceBaseUrl();
}
public VoteDeterminationServiceConcret(Config config) {
this.baseUrl = config.getServiceBaseUrl();
}
@Override
public void ajouterVote(VoteDetermination voteDetermination, AjoutVoteDeterminationCallback callback) {
String idObservation = voteDetermination.getPropositionDetermination().getObservation().getId();
String idProposition = voteDetermination.getPropositionDetermination().getId();
//cas de la proposition de détermination crée automatiquement à partir de l'obs
if(idProposition == null) {
idProposition = "0";
}
String urlService = baseUrl+"observations/"+idObservation+"/"+idProposition+"/vote/";
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.PUT, urlService);
callback.setMode(ModeRequete.AJOUT);
String chainePost = assemblerChaineRequeteAjoutModif(voteDetermination);
try {
rb.sendRequest(chainePost, callback);
} catch (Exception e) {
//TODO: quoi faire si la requete est mal formée coté client avant d'être envoyée ?
}
}
 
@Override
public void modifierVote(VoteDetermination voteDetermination, AjoutVoteDeterminationCallback callback) {
String idObservation = voteDetermination.getPropositionDetermination().getObservation().getId();
String idProposition = voteDetermination.getPropositionDetermination().getId();
//cas de la proposition de détermination crée automatiquement à partir de l'obs
if(idProposition == null) {
idProposition = "0";
}
String urlService = baseUrl+"observations/"+idObservation+"/"+idProposition+"/vote/";
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.POST, urlService);
callback.setMode(ModeRequete.MODIFICATION);
String chainePost = assemblerChaineRequeteAjoutModif(voteDetermination);
try {
rb.sendRequest(chainePost, callback);
} catch (Exception e) {
//TODO: quoi faire si la requete est mal formée coté client avant d'être envoyée ?
}
}
 
private String assemblerChaineRequeteAjoutModif(VoteDetermination voteDetermination) {
String chaineRequete = "utilisateur="+voteDetermination.getContributeur()+"&"+
"valeur="+voteDetermination.getVote();
return chaineRequete;
}
 
@Override
public void consulterVotesPourPropositionDetermination(PropositionDetermination propositionDetermination, ListeVotesDeterminationCallback callback) {
String idObservation = propositionDetermination.getObservation().getId();
String idProposition = propositionDetermination.getId();
//cas de la proposition de détermination crée automatiquement à partir de l'obs
if(idProposition == null) {
idProposition = "0";
}
String urlService = baseUrl+"observations/"+idObservation+"/"+idProposition+"/vote/";
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.GET, urlService);
callback.setMode(ModeRequete.LECTURE);
try {
rb.sendRequest(null, callback);
} catch (Exception e) {
//TODO: quoi faire si la requete est mal formée coté client avant d'être envoyée ?
}
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/PreferencesServiceConcret.java
New file
0,0 → 1,70
package org.tela_botanica.del.client.services.rest;
 
import java.util.HashMap;
import java.util.Iterator;
 
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.modeles.Utilisateur;
import org.tela_botanica.del.client.services.rest.async.ListePreferencesCallback;
import org.tela_botanica.del.client.services.rest.async.ModificationPreferencesCallback;
import org.tela_botanica.del.client.services.rest.async.PHPCallback.ModeRequete;
 
import org.tela_botanica.del.client.services.RequestBuilderWithCredentials;
import com.google.gwt.user.client.Window;
 
public class PreferencesServiceConcret implements PreferencesService {
private String baseUrl;
 
public PreferencesServiceConcret() {
this(new Config());
}
public PreferencesServiceConcret(Config config) {
this.baseUrl = config.getUrl("serviceUtilisateursBaseUrl");
}
 
@Override
public void modifierPreferences(Utilisateur utilisateur, HashMap<String, String> preferences, ModificationPreferencesCallback callback) {
String idUtilisateur = utilisateur.getId();
String urlService = baseUrl+"utilisateurs/"+idUtilisateur+"/preferences/";
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.POST, urlService);
callback.setMode(ModeRequete.MODIFICATION);
String chainePost = assemblerRequeteModification(preferences);
try {
rb.sendRequest(chainePost, callback);
} catch (Exception e) {
//TODO: quoi faire si la requete est mal formée coté client avant d'être envoyée ?
}
}
private String assemblerRequeteModification(HashMap<String, String> preferences) {
String chaine = "";
Iterator<String> it = preferences.keySet().iterator();
while (it.hasNext()) {
String cle = it.next();
if(!chaine.equals("")) {
chaine += "&";
}
chaine += cle+"="+preferences.get(cle);
}
return chaine;
}
 
@Override
public void chargerPreferences(Utilisateur utilisateur,
ListePreferencesCallback callback) {
String idUtilisateur = utilisateur.getId();
String urlService = baseUrl+"utilisateurs/"+idUtilisateur+"/preferences/";
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.GET, urlService);
callback.setMode(ModeRequete.LECTURE);
try {
rb.sendRequest(null, callback);
} catch (Exception e) {
//TODO: quoi faire si la requete est mal formée coté client avant d'être envoyée ?
}
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/CommentaireServiceConcret.java
New file
0,0 → 1,93
package org.tela_botanica.del.client.services.rest;
 
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.modeles.Commentaire;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.services.rest.async.AjoutCommentaireCallback;
import org.tela_botanica.del.client.services.rest.async.ListeCommentairesCallback;
import org.tela_botanica.del.client.services.rest.async.PHPCallback.ModeRequete;
import org.tela_botanica.del.client.services.rest.async.SuppressionCommentaireCallback;
 
import org.tela_botanica.del.client.services.RequestBuilderWithCredentials;
import com.google.gwt.http.client.URL;
 
public class CommentaireServiceConcret implements CommentaireService {
 
private String baseUrl;
 
public CommentaireServiceConcret() {
Config config = new Config();
this.baseUrl = config.getServiceBaseUrl();
}
public CommentaireServiceConcret(Config config) {
this.baseUrl = config.getServiceBaseUrl();
}
@Override
public void ajouterCommentaire(Commentaire commentaire, AjoutCommentaireCallback callback) {
String urlService = baseUrl+"commentaires/";
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.PUT, urlService);
callback.setMode(ModeRequete.AJOUT);
String chainePost = assemblerChaineRequeteAjoutModif(commentaire);
try {
rb.sendRequest(chainePost, callback);
} catch (Exception e) {
//TODO: quoi faire si la requete est mal formée coté client avant d'être envoyée ?
}
}
private String assemblerChaineRequeteAjoutModif(Commentaire commentaire) {
 
String chaineRequete = "";
if(commentaire.getObservation() != null && commentaire.getObservation().getId() != null) {
chaineRequete += "observation="+URL.encodeQueryString(commentaire.getObservation().getId());
}
if(commentaire.getContributeur().getId() != null) {
chaineRequete += "&auteur.id="+URL.encodeQueryString(commentaire.getContributeur().getId());
}
 
if(commentaire.getParent() != null && commentaire.getParent().getId() != null) {
chaineRequete += "&id_parent="+URL.encodeQueryString(commentaire.getParent().getId());
PropositionDetermination propositionParente = commentaire.getPropositionParenteOuNulle();
if(propositionParente != null) {
chaineRequete += "&proposition="+URL.encodeQueryString(propositionParente.getId());
}
}
chaineRequete += "&texte="+URL.encodeQueryString(commentaire.getCommentaire())+
"&auteur.prenom="+URL.encodeQueryString(commentaire.getContributeur().getPrenom())+
"&auteur.nom="+URL.encodeQueryString(commentaire.getContributeur().getNom())+
"&auteur.courriel="+URL.encodeQueryString(commentaire.getContributeur().getAdresseEmail());
return chaineRequete;
}
 
public void chargerCommentaires(PropositionDetermination propositionDetermination, ListeCommentairesCallback commentaireCallback) {
String urlService = baseUrl+"commentaires/?masque.proposition="+propositionDetermination.getId();
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.GET, urlService);
commentaireCallback.setMode(ModeRequete.LECTURE);
try {
rb.sendRequest(null, commentaireCallback);
} catch (Exception e) {
//TODO: quoi faire si la requete est mal formée coté client avant d'être envoyée ?
}
}
 
@Override
public void supprimerCommentaire(Commentaire commentaire,
SuppressionCommentaireCallback callback) {
String urlService = baseUrl+"commentaires/"+commentaire.getId();
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.DELETE, urlService);
callback.setMode(ModeRequete.SUPPRESSION);
try {
rb.sendRequest(null, callback);
} catch (Exception e) {
//TODO: quoi faire si la requete est mal formée coté client avant d'être envoyée ?
}
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/ImageService.java
New file
0,0 → 1,14
package org.tela_botanica.del.client.services.rest;
 
import org.tela_botanica.del.client.modeles.InformationsRecherche;
import org.tela_botanica.del.client.services.rest.async.ImagesParTaxonCallback;
 
public interface ImageService {
 
public void getImagesEfloreParTaxon(String nomTaxon, ImagesParTaxonCallback callback);
 
public void getImagesParTaxon(InformationsRecherche informationsRecherche, int debut, int fin, ImagesParTaxonCallback callback);
 
public void getImagesParObservation(String observationId, ImagesParTaxonCallback callback);
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/VoteProtocoleServiceConcret.java
New file
0,0 → 1,81
package org.tela_botanica.del.client.services.rest;
 
import java.util.List;
 
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.modeles.VoteProtocole;
import org.tela_botanica.del.client.services.rest.async.AjoutVoteProtocoleCallback;
import org.tela_botanica.del.client.services.rest.async.PHPCallback.ModeRequete;
import org.tela_botanica.del.client.services.rest.async.VoteProtocoleCallback;
 
import org.tela_botanica.del.client.services.RequestBuilderWithCredentials;
 
public class VoteProtocoleServiceConcret implements VoteProtocoleService {
 
private String baseUrl;
 
public VoteProtocoleServiceConcret() {
Config config = new Config();
this.baseUrl = config.getServiceBaseUrl();
}
public VoteProtocoleServiceConcret(Config config) {
this.baseUrl = config.getServiceBaseUrl();
}
@Override
public List<VoteProtocole> getVote(String idImage) {
// TODO Auto-generated method stub
return null;
}
 
@Override
public List<VoteProtocole> getVotePourImageEtProtocole(String idImage,
String protocolName) {
// TODO Auto-generated method stub
return null;
}
 
@Override
public void ajouterVote(String idImage, VoteProtocole voteProtocole, AjoutVoteProtocoleCallback callback) {
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.PUT, baseUrl+"images/"+idImage+"/votes/");
callback.setMode(ModeRequete.AJOUT);
String chainePost = assemblerChaineRequeteAjoutModif(voteProtocole);
try {
rb.sendRequest(chainePost, callback);
} catch (Exception e) {
//TODO: quoi faire si la requete est mal formée coté client avant d'être envoyée ?
}
}
 
private String assemblerChaineRequeteAjoutModif(VoteProtocole voteProtocole) {
String chaineRequete = "utilisateur="+voteProtocole.getContributeur()+"&"+
"protocole="+voteProtocole.getIdProtocole()+"&"+
"valeur="+voteProtocole.getVote();
return chaineRequete;
}
@Override
public void modifierVote(String idImage, VoteProtocole voteProtocole, VoteProtocoleCallback callback) {
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.POST, baseUrl+"images/"+idImage+"/votes/");
callback.setMode(ModeRequete.MODIFICATION);
String chainePost = assemblerChaineRequeteAjoutModif(voteProtocole);
try {
rb.sendRequest(chainePost, callback);
} catch (Exception e) {
//TODO: quoi faire si la requete est mal formée coté client avant d'être envoyée ?
}
}
 
@Override
public void supprimerVote(String idImage, VoteProtocole voteProtocole,
VoteProtocoleCallback callback) {
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.DELETE, baseUrl+"images/"+idImage+"/votes/"+voteProtocole.getId());
callback.setMode(ModeRequete.SUPPRESSION);
try {
rb.sendRequest(null, callback);
} catch (Exception e) {
//TODO: quoi faire si la requete est mal formée coté client avant d'être envoyée ?
}
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/ProtocoleServiceConcret.java
New file
0,0 → 1,38
package org.tela_botanica.del.client.services.rest;
 
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.services.rest.async.PHPCallback.ModeRequete;
import org.tela_botanica.del.client.services.rest.async.ProtocolesCallback;
import org.tela_botanica.del.client.services.RequestBuilderWithCredentials;
 
public class ProtocoleServiceConcret implements ProtocoleService {
 
private String baseUrl;
public ProtocoleServiceConcret() {
Config config = new Config();
this.baseUrl = config.getServiceBaseUrl();
}
public ProtocoleServiceConcret(Config config) {
this.baseUrl = config.getServiceBaseUrl();
}
@Override
public void getProtocole(String nomProtocole) {
//TODO: voir si l'on aura besoin de ne retourner qu'un seul protocole
}
 
@Override
public void getProtocoles(ProtocolesCallback callback) {
//TODO: inventer un système de cache car sinon c'est chargé à fois qu'on accède à la partie
// recherche image
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.GET, baseUrl + "protocoles");
callback.setMode(ModeRequete.LECTURE);
try {
rb.sendRequest(null, callback);
} catch (Exception e) {
// TODO: handle exception
}
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/PropositionDeterminationServiceConcret.java
New file
0,0 → 1,111
package org.tela_botanica.del.client.services.rest;
 
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.modeles.Commentaire;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.services.rest.async.PHPCallback.ModeRequete;
import org.tela_botanica.del.client.services.rest.async.PropositionDeterminationCallBack;
import org.tela_botanica.del.client.services.rest.async.SuppressionCommentaireCallback;
import org.tela_botanica.del.client.services.rest.async.SuppressionPropositionDeterminationCallback;
import org.tela_botanica.del.client.services.rest.async.ValidationPropositionCallback;
 
import org.tela_botanica.del.client.services.RequestBuilderWithCredentials;
import com.google.gwt.http.client.URL;
 
public class PropositionDeterminationServiceConcret implements
PropositionDeterminationService {
private String baseUrl;
 
public PropositionDeterminationServiceConcret() {
Config config = new Config();
this.baseUrl = config.getServiceBaseUrl();
}
public PropositionDeterminationServiceConcret(Config config) {
this.baseUrl = config.getServiceBaseUrl();
}
 
@Override
public void ajouterProposition(PropositionDetermination proposition, PropositionDeterminationCallBack callback) {
String urlService = baseUrl+"commentaires/";
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.PUT, urlService);
callback.setMode(ModeRequete.AJOUT);
String chainePost = assemblerChaineRequeteAjoutModif(proposition);
try {
// TODO urlencoder toutes les requetes;
rb.sendRequest(chainePost, callback);
} catch (Exception e) {
//TODO: quoi faire si la requete est mal formée coté client avant d'être envoyée ?
}
}
private String assemblerChaineRequeteAjoutModif(PropositionDetermination proposition) {
 
String chaineRequete = "";
//TODO: tests sur les num nn et nt et la famille quand ils seront implémentés
chaineRequete += "nom_sel="+URL.encodeQueryString(proposition.getEspece())+
"&auteur.prenom="+URL.encodeQueryString(proposition.getContributeur().getPrenom())+
"&auteur.nom="+URL.encodeQueryString(proposition.getContributeur().getNom())+
"&auteur.courriel="+URL.encodeQueryString(proposition.getContributeur().getAdresseEmail());
if(proposition.getNumNomenclatural() != null) {
chaineRequete += "&nom_sel_nn="+URL.encodeQueryString(proposition.getNumNomenclatural());
}
if(proposition.getReferentiel() != null && !proposition.getReferentiel().equals("tous")) {
chaineRequete += "&nom_referentiel="+URL.encodeQueryString(proposition.getReferentiel());
}
if (proposition.getObservation() != null && proposition.getObservation().getId() != null) {
chaineRequete += "&observation="+URL.encodeQueryString(proposition.getObservation().getId());
}
if (proposition.getContributeur().getId() != null) {
chaineRequete += "&auteur.id="+URL.encodeQueryString(proposition.getContributeur().getId());
}
if (proposition.getParent() != null && proposition.getParent().getId() != null) {
chaineRequete += "&id_parent="+URL.encodeQueryString(proposition.getParent().getId());
PropositionDetermination propositionParente = proposition.getPropositionParenteOuNulle();
if(propositionParente != null) {
chaineRequete += "&proposition="+URL.encodeQueryString(propositionParente.getId());
}
}
if (proposition.getCommentaire() != null) {
chaineRequete += "&texte="+URL.encodeQueryString(proposition.getCommentaire());
}
 
return chaineRequete;
}
 
@Override
public void supprimerProposition(PropositionDetermination proposition, SuppressionPropositionDeterminationCallback callback) {
String urlService = baseUrl+"commentaires/"+proposition.getId();
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.DELETE, urlService);
callback.setMode(ModeRequete.SUPPRESSION);
try {
rb.sendRequest(null, callback);
} catch (Exception e) {
//TODO: quoi faire si la requete est mal formée coté client avant d'être envoyée ?
}
}
@Override
public void validerProposition(PropositionDetermination proposition, ValidationPropositionCallback callback) {
String urlService = baseUrl+"determinations/valider-determination/"+proposition.getId();
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.POST, urlService);
callback.setMode(ModeRequete.MODIFICATION);
String chainePost = "auteur.id="+URL.encodeQueryString(proposition.getContributeur().getId());
try {
rb.sendRequest(chainePost, callback);
} catch (Exception e) {
//TODO: quoi faire si la requete est mal formée coté client avant d'être envoyée ?
}
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/UtilisateurServiceConcret.java
New file
0,0 → 1,54
package org.tela_botanica.del.client.services.rest;
 
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.services.rest.async.UtilisateurCallback;
import org.tela_botanica.del.client.services.rest.async.PHPCallback.ModeRequete;
 
import org.tela_botanica.del.client.services.RequestBuilderWithCredentials;
 
public class UtilisateurServiceConcret implements UtilisateurService {
private String baseUrl;
public UtilisateurServiceConcret() {
this(new Config());
}
public UtilisateurServiceConcret(Config config) {
this.baseUrl = config.getUrl("serviceUtilisateursBaseUrl");
}
@Override
public void connecterUtilisateur(String login, String motDePasse, UtilisateurCallback callback) {
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.GET, baseUrl + "utilisateurs/" + login + "/" + motDePasse);
callback.setMode(ModeRequete.LECTURE);
try {
rb.sendRequest(null, callback);
} catch (Exception e) {
// TODO: handle exception
}
}
 
@Override
public void deconnecterUtilisateur(UtilisateurCallback callback) {
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.GET, baseUrl + "utilisateurs/deconnecter");
callback.setMode(ModeRequete.LECTURE);
try {
rb.sendRequest(null, callback);
} catch (Exception e) {
// TODO: handle exception
}
}
 
@Override
public void obtenirUtilisateur(UtilisateurCallback callback) {
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.GET, baseUrl + "utilisateurs/");
callback.setMode(ModeRequete.LECTURE);
try {
rb.sendRequest(null, callback);
} catch (Exception e) {
// TODO: handle exception
}
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/MotsClesService.java
New file
0,0 → 1,15
package org.tela_botanica.del.client.services.rest;
 
import org.tela_botanica.del.client.services.rest.async.AjoutMotsClesImageCallback;
import org.tela_botanica.del.client.services.rest.async.ListeMotsClesImageCallBack;
import org.tela_botanica.del.client.services.rest.async.SuppressionMotCleImageCallback;
 
public interface MotsClesService {
public void getMotsClesImage(String idImage, ListeMotsClesImageCallBack listeMotsClesImageCallBack);
public void ajouterMotCleImage(String idImage, String motCle, AjoutMotsClesImageCallback ajoutMotsClesImageCallBack);
 
public void supprimerMotCleImage(String idMotCle, SuppressionMotCleImageCallback callback);
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/ObservationService.java
New file
0,0 → 1,13
package org.tela_botanica.del.client.services.rest;
 
import org.tela_botanica.del.client.modeles.InformationsRecherche;
import org.tela_botanica.del.client.services.rest.async.ObservationsCallback;
 
public interface ObservationService {
 
public void getObservations(InformationsRecherche informationsRecherche, int debut, int fin, String statut, ObservationsCallback callback);
 
public void getObservation(String idObservation,
ObservationsCallback observationsCallback);
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/VoteDeterminationService.java
New file
0,0 → 1,14
package org.tela_botanica.del.client.services.rest;
 
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.modeles.VoteDetermination;
import org.tela_botanica.del.client.services.rest.async.AjoutVoteDeterminationCallback;
import org.tela_botanica.del.client.services.rest.async.ListeVotesDeterminationCallback;
 
public interface VoteDeterminationService {
 
void ajouterVote(VoteDetermination voteDetermination, AjoutVoteDeterminationCallback callback);
public void modifierVote(VoteDetermination voteDetermination, AjoutVoteDeterminationCallback callback);
void consulterVotesPourPropositionDetermination(PropositionDetermination propositionDetermination, ListeVotesDeterminationCallback callBack);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/ImageServiceConcret.java
New file
0,0 → 1,68
package org.tela_botanica.del.client.services.rest;
 
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.modeles.InformationsRecherche;
import org.tela_botanica.del.client.services.rest.async.ImagesParTaxonCallback;
import org.tela_botanica.del.client.services.rest.async.PHPCallback.ModeRequete;
 
import org.tela_botanica.del.client.services.RequestBuilderWithCredentials;
 
public class ImageServiceConcret implements ImageService {
 
private String baseUrl;
public ImageServiceConcret() {
Config config = new Config();
this.baseUrl = config.getServiceBaseUrl();
}
public ImageServiceConcret(Config config) {
this.baseUrl = config.getServiceBaseUrl();
}
@Override
public void getImagesEfloreParTaxon(String taxon, ImagesParTaxonCallback callback) {
 
// RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.GET,
// serverUrl+"ImagesEflore");
// adresse ajoutee temporairement le temps de faire fonctionner le
// service d'images eflore
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.GET, baseUrl + "images?nom_taxon=" + taxon);
callback.setMode(ModeRequete.LECTURE);
try {
rb.sendRequest(null, callback);
} catch (Exception e) {
// TODO: handle exception
}
}
 
@Override
public void getImagesParTaxon(InformationsRecherche infos, int debut, int fin, ImagesParTaxonCallback callback) {
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.GET, baseUrl + "images" + assemblerChaineRequete(infos, debut, fin));
callback.setMode(ModeRequete.LECTURE);
try {
rb.sendRequest(null, callback);
} catch (Exception e) {
// TODO: handle exception
}
}
 
public void getImagesParObservation(String observationId, ImagesParTaxonCallback callback) {
// TODO implementer avec une methode realiste
RequestBuilderWithCredentials rb = new RequestBuilderWithCredentials(RequestBuilderWithCredentials.GET, baseUrl + "observations/"+observationId);
callback.setMode(ModeRequete.LECTURE);
try {
rb.sendRequest(null, callback);
} catch (Exception e) {
// TODO: handle exception
}
}
 
private String assemblerChaineRequete(InformationsRecherche infos, int debut, int fin) {
 
String chaineRequete = "?navigation.depart=" + debut + "&navigation.limite=" + (fin - debut);
chaineRequete+= infos.versChaineRequete();
 
return chaineRequete;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/PreferencesService.java
New file
0,0 → 1,14
package org.tela_botanica.del.client.services.rest;
 
import java.util.HashMap;
 
import org.tela_botanica.del.client.modeles.Utilisateur;
import org.tela_botanica.del.client.services.rest.async.ListePreferencesCallback;
import org.tela_botanica.del.client.services.rest.async.ModificationPreferencesCallback;
 
public interface PreferencesService {
public void modifierPreferences(Utilisateur utilisateur, HashMap<String, String> preferences, ModificationPreferencesCallback modificationPreferencesCallback);
public void chargerPreferences(Utilisateur utilisateur, ListePreferencesCallback listePreferencesCallbackCallback);
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/rest/CommentaireService.java
New file
0,0 → 1,13
package org.tela_botanica.del.client.services.rest;
 
import org.tela_botanica.del.client.modeles.Commentaire;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.services.rest.async.AjoutCommentaireCallback;
import org.tela_botanica.del.client.services.rest.async.ListeCommentairesCallback;
import org.tela_botanica.del.client.services.rest.async.SuppressionCommentaireCallback;
 
public interface CommentaireService {
public void ajouterCommentaire(Commentaire commentaire, AjoutCommentaireCallback callback);
public void supprimerCommentaire(Commentaire commentaire, SuppressionCommentaireCallback callback);
public void chargerCommentaires(PropositionDetermination propositionDetermination, ListeCommentairesCallback commentaireCallback);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/CalculVoteDeterminationService.java
New file
0,0 → 1,90
package org.tela_botanica.del.client.services;
 
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
 
import org.tela_botanica.del.client.modeles.MoyenneVote;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.modeles.VoteDetermination;
 
 
public class CalculVoteDeterminationService {
public static List<MoyenneVote> calculerVoteDeterminationPlusPopulaire(List<PropositionDetermination> propositions) {
List<MoyenneVote> pairesVotes = new ArrayList<MoyenneVote>();
for (PropositionDetermination proposition : propositions) {
pairesVotes.add(calculerVoteDetermination(proposition));
}
java.util.Collections.sort(pairesVotes);
return pairesVotes;
}
public static int getNombreTotalVotants(PropositionDetermination proposition) {
int nbVotants = 0;
List<PropositionDetermination> votes = proposition.getObservation().getPropositionDeterminations();
Iterator<PropositionDetermination> itVotes = votes.iterator();
while (itVotes.hasNext()) {
PropositionDetermination propositionCourante = itVotes.next();
nbVotants += propositionCourante.getVotesDeterminations().size();
}
return nbVotants;
}
public static MoyenneVote calculerVoteDetermination(PropositionDetermination propositionDetermination) {
int nbVotants = getNombreTotalVotants(propositionDetermination);
return calculerProportionVote(propositionDetermination, nbVotants);
}
public static MoyenneVote calculerMoyenneVoteDetermination(PropositionDetermination propositionDetermination, int nbVotants) {
return calculerProportionVote(propositionDetermination, nbVotants);
}
private static MoyenneVote calculerProportionVote(PropositionDetermination propositionDetermination, int nbVotants) {
Map<String,VoteDetermination> votes = propositionDetermination.getVotesDeterminations();
double scoreVoteIdentifie = 0;
double scoreVoteAnonyme = 0;
double scoreVote = 0;
if(votes.size() > 0) {
Set<String> cles = votes.keySet();
 
for (String cle : cles) {
String idAuteur = cle;
int valeurVote = votes.get(cle).getVote();
if(estUnAuteurIdentifie(idAuteur)) {
// un votant identifiant compte comme deux votants supplémentaires
// il a donc un vote 3 fois supérieur
scoreVoteIdentifie += valeurVote;
//nbVotants += 2;
} else {
scoreVoteAnonyme += valeurVote;
}
}
scoreVote = ((scoreVoteAnonyme + scoreVoteIdentifie)/(nbVotants))*100;
} else {
scoreVote = -1;
}
return new MoyenneVote((new Double(scoreVote)).intValue(), propositionDetermination);
}
private static boolean estUnAuteurIdentifie(String idAuteur) {
boolean estIdentifie = true;
try {
int intIdAuteur = Integer.parseInt(idAuteur);
} catch (NumberFormatException nfe) {
estIdentifie = false;
}
return estIdentifie;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/ReferentielService.java
New file
0,0 → 1,29
package org.tela_botanica.del.client.services;
 
import java.util.LinkedHashMap;
import java.util.Map;
 
import org.tela_botanica.del.client.i18n.I18n;
 
public class ReferentielService {
//TODO: trouver une meilleure manière de gérer les référentiels
// que cette classe statique
private static Map<String, String> referentiels;
public static Map<String, String> getReferentiels() {
// le fonctionnement de l'i18n empeche de mettre les référentiels dans
// des fichiers de config car il est impossigble de charger les termes
// de vocabulaires associés avec la réflexivité
if(referentiels == null) {
// attention l'utilisation de LinkedHashmap est importante pour conserver
// l'ordre des référentiels
referentiels = new LinkedHashMap<String, String>();
referentiels.put("tous", I18n.getVocabulary().referentielTous());
referentiels.put("bdtfx", I18n.getVocabulary().referentielBdtfx());
referentiels.put("bdtxa", I18n.getVocabulary().referentielBdtxa());
}
return referentiels;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/services/RequestBuilderWithCredentials.java
New file
0,0 → 1,11
package org.tela_botanica.del.client.services;
 
import com.google.gwt.http.client.RequestBuilder;
 
public class RequestBuilderWithCredentials extends RequestBuilder {
 
public RequestBuilderWithCredentials(Method httpMethod, String url) {
super(httpMethod, url);
this.setIncludeCredentials(true);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/Del.java
New file
0,0 → 1,62
package org.tela_botanica.del.client;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.gestionhistorique.GestionnaireHistorique;
 
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
import com.google.gwt.event.shared.UmbrellaException;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
 
public class Del implements EntryPoint {
@Override
public void onModuleLoad() {
// A décommenter + compiler en detailed dans le cas d'une erreur
// survernant uniquement sur le serveur
/*GWT.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void onUncaughtException(Throwable e) {
Window.alert("uncaught: " + e.getMessage());
String s = buildStackTrace(e, "RuntimeException:\n");
Window.alert(s);
e.printStackTrace();
}
});*/
 
CacheClient.getInstance().initialiserAvecParametres();
History.addValueChangeHandler(new GestionnaireHistorique());
History.newItem(CacheClient.getInstance().getPageCourante());
History.fireCurrentHistoryState();
}
/*private String buildStackTrace(Throwable t, String log) {
if (t != null) {
log += t.getClass().toString();
log += t.getMessage();
//
StackTraceElement[] stackTrace = t.getStackTrace();
if (stackTrace != null) {
StringBuffer trace = new StringBuffer();
for (int i = 0; i < stackTrace.length; i++) {
trace.append(stackTrace[i].getClassName() + "." + stackTrace[i].getMethodName() + "("
+ stackTrace[i].getFileName() + ":" + stackTrace[i].getLineNumber());
}
log += trace.toString();
}
//
Throwable cause = t.getCause();
if (cause != null && cause != t) {
log += buildStackTrace(cause, "CausedBy:\n");
}
}
return log;
}*/
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/config/APropos.java
New file
0,0 → 1,93
package org.tela_botanica.del.client.config;
 
import com.google.gwt.i18n.client.Dictionary;
 
/**
* Classe chargeant certains paramètres de configuration à partir d'un fichier
* javascript (war/config/apropos.js)
*
* @author Jean-Pascal MILCENT
*
*/
public class APropos {
private String appliNom;
private String appliCode;
private String appliVersionNom;
private String appliVersionCode;
private String developpeurs;
private String traducteurs;
private String testeurs;
private String licence;
private String dateHeureCompilation;
private String revisionGlobale;
private String revisionGlobaleServices;
private String versionJavaCompilation;
public APropos() {
// on utilise le dictionnaire d'internationalisation pour lire les variables du fichier javascript
Dictionary apropos = Dictionary.getDictionary("apropos");
appliNom = apropos.get("appliNom");
appliCode = apropos.get("appliCode");
appliVersionNom = apropos.get("appliVersionNom");
appliVersionCode = apropos.get("appliVersionCode");
developpeurs = apropos.get("developpeurs");
testeurs = apropos.get("testeurs");
traducteurs = apropos.get("traducteurs");
licence = apropos.get("licence");
dateHeureCompilation = apropos.get("dateHeureCompilation");
revisionGlobale = apropos.get("revisionGlobale");
revisionGlobaleServices = apropos.get("revisionGlobaleServices");
versionJavaCompilation = apropos.get("versionJavaCompilation");
}
 
public String getAppliNom() {
return appliNom;
}
public String getAppliCode() {
return appliCode;
}
public String getAppliVersionNom() {
return appliVersionNom;
}
public String getAppliVersionCode() {
return appliVersionCode;
}
public String getDeveloppeurs() {
return developpeurs;
}
public String getTraducteurs() {
return traducteurs;
}
public String getLicence() {
return licence;
}
public String getDateHeureCompilation() {
return dateHeureCompilation;
}
public String getRevisionGlobale() {
return revisionGlobale;
}
public String getRevisionGlobaleServices() {
return revisionGlobaleServices;
}
public String getVersionJavaCompilation() {
return versionJavaCompilation;
}
 
public String getTesteurs() {
return testeurs;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/config/Config.java
New file
0,0 → 1,80
package org.tela_botanica.del.client.config;
 
import java.util.LinkedHashMap;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.Dictionary;
import com.google.gwt.user.client.Window;
 
/**
* Classe chargeant certains paramètres de configuration à partir d'un fichier
* javascript (config.js)
*
* @author Jean-Pascal MILCENT
*
*/
public class Config {
 
/**
* Tableau associatif contenant les identifiants des urls externes
*/
private LinkedHashMap<String, String> urls = new LinkedHashMap<String, String>();
/**
* Tableau associatif contenant d'autres informations
*/
private LinkedHashMap<String, String> infos = new LinkedHashMap<String, String>();
 
/**
* Constructeur sans argument
*/
public Config() {
// on utilise le dictionnaire d'internationalisation pour lire les variables du fichier javascript
Dictionary configuration = Dictionary.getDictionary("configuration");
urls.put("base", configuration.get("serviceBaseUrl"));
urls.put("del", configuration.get("delUrl"));
urls.put("identiplante", configuration.get("identiplanteUrl"));
urls.put("pictoflora", configuration.get("pictofloraUrl"));
urls.put("bogue", configuration.get("bogueUrl"));
urls.put("commentaire", configuration.get("commentaireUrl"));
urls.put("applisaisie", configuration.get("appliSaisieUrl"));
urls.put("annuaire", configuration.get("annuaireUrl"));
urls.put("eflore", configuration.get("efloreUrl"));
urls.put("efloreTaxon", configuration.get("efloreTaxonUrl"));
urls.put("bonnierPda", configuration.get("bonnierPdaUrl"));
urls.put("ouvragesFlore", configuration.get("ouvragesFloreUrl"));
urls.put("clesDetermination", configuration.get("clesDeterminationUrl"));
urls.put("rss", configuration.get("rssUrl"));
urls.put("iconeBaseUrl", configuration.get("iconeTagBaseUrl"));
urls.put("urlProfil", configuration.get("urlProfil"));
urls.put("urlImages", configuration.get("urlImages"));
urls.put("serviceUtilisateursBaseUrl", configuration.get("serviceUtilisateursBaseUrl"));
}
/**
* Accesseur pour l'url de base du serveur jrest
*
* @return une url de la forme http://emplacement_serveur/jrest
*/
public String getServiceBaseUrl() {
return getUrl("base");
}
 
public String getUrl(String code) {
String url = "";
if (urls.containsKey(code)) {
url = urls.get(code);
}
return url;
}
public String getInfo(String code) {
String info = "";
if (infos.containsKey(code)) {
info = infos.get(code);
}
return info;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/gestionhistorique/ConstantesNavigation.java
New file
0,0 → 1,19
package org.tela_botanica.del.client.gestionhistorique;
public class ConstantesNavigation {
 
public static final String HOME = "accueil";
public static final String PAGE_PRINCIPALE = "page_principale";
public static final String PAGE_RECHERCHE_IMAGES = "page_recherche_images";
public static final String PICTOFLORA = "pictoflora";
public static final String PAGE_RECHERCHE_OBSERVATIONS = "page_recherche_observations";
public static final String PAGE_VALIDATION = "page_validation"; //pour identiplante
public static final String PAGE_VALIDATION_PICTOFLORA = "pictoflora_page_validation";
public static final String PAGE_COMPARAISON_EFLORE = "page_comparaison_eflore";
public static final String PARAM_ID_OBSERVATION = "id_observation";
public static final String PARAM_TYPE_TOUS = "tous";
public static final String PARAM_TYPE_A_DETERMINER = "adeterminer";
public static final String PARAM_TYPE_EN_DISCUSSION = "endiscussion";
public static final String PARAM_TYPE_VALIDEES = "validees";
public static final String PARAM_TYPE_DEFAUT = PARAM_TYPE_A_DETERMINER;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/gestionhistorique/GestionnaireHistorique.java
New file
0,0 → 1,138
package org.tela_botanica.del.client.gestionhistorique;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.services.rest.ImageServiceConcret;
import org.tela_botanica.del.client.services.rest.ObservationServiceConcret;
import org.tela_botanica.del.client.services.rest.ProtocoleServiceConcret;
import org.tela_botanica.del.client.vues.comparaisoneflore.ComparaisonEflorePresenteur;
import org.tela_botanica.del.client.vues.comparaisoneflore.ComparaisonEfloreVue;
import org.tela_botanica.del.client.vues.entete.EntetePresenteur;
import org.tela_botanica.del.client.vues.entete.EnteteVue;
import org.tela_botanica.del.client.vues.identiplante.moteur.MoteurIdentiplantePresenteur;
import org.tela_botanica.del.client.vues.identiplante.moteur.MoteurIdentiplanteVue;
import org.tela_botanica.del.client.vues.identiplante.plateformedetermination.IdentiplanteDeterminationPresenteur;
import org.tela_botanica.del.client.vues.identiplante.plateformedetermination.IdentiplanteDeterminationVue;
import org.tela_botanica.del.client.vues.pictoflora.moteur.MoteurPictofloraPresenteur;
import org.tela_botanica.del.client.vues.pictoflora.moteur.MoteurPictofloraVue;
import org.tela_botanica.del.client.vues.pictoflora.plateformedetermination.PictofloraDeterminationPresenteur;
import org.tela_botanica.del.client.vues.pictoflora.plateformedetermination.PictofloraDeterminationVue;
 
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RootPanel;
 
/**
* @author Benjamin
*
*/
public class GestionnaireHistorique implements ValueChangeHandler<String> {
 
/**
* Évènement lorsque l'historique change. L'action par défaut affiche la
* page d'accueil.
* */
public void onValueChange(ValueChangeEvent<String> event) {
 
//1. définition des variables
String eventValue = event.getValue();
Panel contenu = RootPanel.get("contenu");
Panel zoneEntete = RootPanel.get("zoneEntete");
CacheClient cache = CacheClient.getInstance();
cache.setPageCourante(eventValue);
//2. nettoyer le contenu
contenu.clear();
zoneEntete.clear();
//3. Gérer le titre
String titre = "IdentiPlante";
if (eventValue.startsWith(ConstantesNavigation.PAGE_RECHERCHE_IMAGES)) {
titre = "PictoFlora";
}
if (eventValue.startsWith(ConstantesNavigation.HOME)) {
String home = cache.getHome();
if (home.startsWith(ConstantesNavigation.PAGE_RECHERCHE_IMAGES)) {
titre = "PictoFlora";
}
}
if (eventValue.startsWith(ConstantesNavigation.PAGE_VALIDATION_PICTOFLORA)) {
titre = "PictoFlora";
}
//3. gérer l'entete
EntetePresenteur entetePresenteur = new EntetePresenteur(new EnteteVue(titre));
entetePresenteur.go(zoneEntete);
//Actions en fonction de la valeur de l'évènement
if (eventValue.startsWith(ConstantesNavigation.PAGE_RECHERCHE_IMAGES)) {
cache.setHome(ConstantesNavigation.PAGE_RECHERCHE_IMAGES);
lancerMoteurRechercheImages(contenu);
} else if (eventValue.startsWith(ConstantesNavigation.PAGE_VALIDATION)) {
IdentiplanteDeterminationPresenteur presenteur = new IdentiplanteDeterminationPresenteur(new IdentiplanteDeterminationVue(), new ObservationServiceConcret());
presenteur.go(contenu);
} else if (eventValue.startsWith(ConstantesNavigation.PAGE_VALIDATION_PICTOFLORA)) {
PictofloraDeterminationPresenteur presenteur = new PictofloraDeterminationPresenteur(new PictofloraDeterminationVue(), new ObservationServiceConcret(), new ProtocoleServiceConcret());
presenteur.go(contenu);
} else if (eventValue.startsWith(ConstantesNavigation.PAGE_COMPARAISON_EFLORE)) {
ComparaisonEflorePresenteur presenteur = new ComparaisonEflorePresenteur(new ComparaisonEfloreVue(), new ImageServiceConcret());
presenteur.go(contenu);
} else if (eventValue.startsWith(ConstantesNavigation.PAGE_RECHERCHE_OBSERVATIONS)) {
cache.setHome(ConstantesNavigation.PAGE_RECHERCHE_OBSERVATIONS);
lancerMoteurRechercheObservation(contenu);
} else if (eventValue.startsWith(ConstantesNavigation.HOME)) {
String home = cache.getHome();
if (home.startsWith(ConstantesNavigation.PAGE_RECHERCHE_IMAGES)) {
lancerMoteurRechercheImages(contenu);
} else {
lancerMoteurRechercheObservation(contenu);
}
}
else{
lancerMoteurRechercheObservation(contenu);
}
CacheClient.getInstance().mettreAjourUrlCourante();
}
/**
* Afficher ler titre Identiplance
* */
public void afficherTitreIdp(Panel titre) {
titre.clear();
HTML html = new HTML("<h1>IdentiPlante</h1>");
titre.add(html);
}
/**
* Afficher ler titre Identiplance
* */
public void afficherTitrePictoFlora(Panel titre) {
titre.clear();
HTML html = new HTML("<h1>PictoFlora</h1>");
titre.add(html);
}
/**
* Générer la page de recherche observation et l'afficher dans panneau
* @param Panel panneau le panneau pour afficher le résultat
* */
public void lancerMoteurRechercheObservation(Panel panneau) {
MoteurIdentiplantePresenteur presenteur = new MoteurIdentiplantePresenteur(new ObservationServiceConcret(), new MoteurIdentiplanteVue());
presenteur.go(panneau);
}
/**
* Générer la page de recherche images et l'afficher dans panneau
* @param Panel panneau le panneau pour afficher le résultat
* */
public void lancerMoteurRechercheImages(Panel panneau) {
MoteurPictofloraPresenteur presenteur = new MoteurPictofloraPresenteur(new MoteurPictofloraVue(), new ProtocoleServiceConcret());
presenteur.go(panneau);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/moteurrecherche/MoteurRechercheVue.ui.xml
New file
0,0 → 1,90
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
ui:generateLocales="default">
<ui:with field='res' type='org.tela_botanica.del.client.resources.Ressources' />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
 
<ui:style src="MoteurRecherche.css" />
<g:HTMLPanel styleName="limiteMin {style.zoneRecherche}">
<g:TextBox styleName="{style.recherchePrincipale} arrondi" ui:field="recherchePrincipale" text="{constants.rechercherObservation}"></g:TextBox>
<g:Button styleName="{style.boutonRecherche} arrondi" ui:field="boutonRecherche" text="{constants.rechercher}">
</g:Button>
<g:Label styleName="{style.lienRechercheAvancee}" ui:field="lienRechercheAvancee" text="{constants.rechercheAvancee}"></g:Label>
<g:HTMLPanel styleName="{style.rechercheAvancee} ombre-forte" ui:field="rechercheAvancee">
<g:Button ui:field="boutonFermer" styleName="{style.boutonFermer}" text="Fermer"></g:Button>
<g:Button ui:field="boutonVider" styleName="{style.boutonVider}" text="Vider"></g:Button>
 
<g:HTMLPanel styleName="{style.champRecherche}">
<g:Label text="{constants.contientMots}" styleName="petit"/>
<g:TextBox ui:field="contientMots" />
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.champRecherche}">
<g:Label text="{constants.famille}" styleName="petit"/>
<g:TextBox ui:field="famille" />
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.champRecherche}">
<g:Label text="{constants.referentiel}" styleName="petit"/>
<g:ListBox ui:field="referentiel" />
</g:HTMLPanel>
 
<g:HTMLPanel styleName="{style.champRecherche}">
<g:Label text="{constants.taxon}" styleName="petit"/>
<g:HTMLPanel ui:field="taxon" />
</g:HTMLPanel>
 
<g:HTMLPanel styleName="{style.champRecherche}">
<g:Label text="{constants.genre}" styleName="petit"/>
<g:TextBox ui:field="genre" />
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.champRecherche}">
<g:Label text="{constants.commune}" styleName="petit"/>
<g:HTMLPanel ui:field="commune" />
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.champRecherche}">
<g:Label text="{constants.departement}" styleName="petit"/>
<g:TextBox ui:field="departement" />
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.champRecherche}">
<g:Label text="{constants.auteur}" styleName="petit"/>
<g:TextBox ui:field="auteur" />
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.champRecherche}">
<g:Label text="{constants.date} {constants.formatDate}" styleName="petit"/>
<g:TextBox ui:field="date" />
</g:HTMLPanel>
<g:HTMLPanel ui:field="conteneurMotCle" styleName="{style.champRecherche}">
<g:Label text="{constants.tag}" styleName="petit"/>
<g:TextBox ui:field="motCle" />
</g:HTMLPanel>
<g:HTMLPanel ui:field="conteneurMotCleCel" styleName="{style.champRecherche}">
<g:Label text="{constants.tagCel}" styleName="petit"/>
<g:TextBox ui:field="motCleCel" />
</g:HTMLPanel>
<g:HTMLPanel ui:field="conteneurMotCleDel" styleName="{style.champRecherche}">
<g:Label text="{constants.tagDel}" styleName="petit"/>
<g:TextBox ui:field="motCleDel" />
</g:HTMLPanel>
 
<g:Button styleName="{style.boutonRecherche} {style.rechercherAvance}" ui:field="boutonRechercheAvancee" text="{constants.rechercher}"></g:Button>
<g:HTMLPanel styleName="nettoyage" />
</g:HTMLPanel>
<g:HTMLPanel styleName="droite">
<g:HTMLPanel ui:field="zoneRss" styleName="{style.zoneRss}"></g:HTMLPanel>
</g:HTMLPanel>
<g:Label ui:field="recherchePrecedente" styleName="{style.recherchePrecedente}" />
<g:HTMLPanel ui:field="zonePagination" />
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/moteurrecherche/MoteurRecherchePresenteur.java
New file
0,0 → 1,416
package org.tela_botanica.del.client.composants.moteurrecherche;
 
import java.util.Map;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.formulaires.autocompletion.AutoCompletionComboBoxPresenteur;
import org.tela_botanica.del.client.composants.formulaires.autocompletion.AutoCompletionComboBoxVue;
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.composants.rss.RssPresenteur;
import org.tela_botanica.del.client.composants.rss.RssVue;
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.modeles.InformationsRecherche;
import org.tela_botanica.del.client.modeles.ModeRecherche;
import org.tela_botanica.del.client.services.ReferentielService;
import org.tela_botanica.del.client.utils.UtilitairesAutoCompletionService;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasKeyPressHandlers;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.http.client.Response;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public abstract class MoteurRecherchePresenteur extends Presenteur {
 
public abstract interface Vue extends IsWidget {
public void ajouterVue(HasWidgets composite);
 
public HasClickHandlers getLienRechercheAvancee();
 
public void basculerAffichageZoneCache();
 
public HasClickHandlers getBoutonRechercheSimple();
 
public HasClickHandlers getBoutonFermer();
 
public HasClickHandlers getBoutonVider();
 
public HasClickHandlers getBoutonRechercheAvancee();
 
public HasKeyPressHandlers getChampSaisie();
 
public HasClickHandlers getChampSaisieCliquable();
 
public String getValeurRechercheSimple();
 
public String getLabelRecherche();
 
public String getContientMots();
 
public String getDepartement();
 
public HasWidgets getCommune();
 
public HasWidgets getTaxon();
 
public String getFamille();
 
public String getGenre();
 
public String getMotCle();
 
public String getAuteur();
 
public String getDate();
 
public void setValeurRechercheSimple(String valeurRecherche);
 
public void setContientMots(String mots);
 
public void setValeurDepartement(String dpt);
 
public void chargerValeursRecherchePrecedente(InformationsRecherche informationsRecherche);
 
public void focusSaisie();
 
public void nettoyer();
 
public HasKeyPressHandlers getChampsFamille();
 
public HasKeyPressHandlers getChampsGenre();
 
public HasKeyPressHandlers getChampsMotCle();
public HasKeyPressHandlers getChampsMotCleDel();
public HasKeyPressHandlers getChampsMotCleCel();
 
public HasKeyPressHandlers getChampsAuteur();
 
public HasKeyPressHandlers getChampsDate();
public HasKeyPressHandlers getChampsDepartement();
public HasKeyPressHandlers getChampsContientMots();
public HasWidgets getZoneRss();
 
public String getReferentiel();
public void setReferentielLectureSeule(boolean lectureSeule);
 
void remplirListeReferentiels(Map<String, String> listeReferentiels);
 
public String getMotCleDel();
 
public String getMotCleCel();
public void cacherChampsTagsImage();
public void cacherChampsTagsObs();
 
}
 
private Vue vue;
private Config config;
private ModeRecherche modeRecherche;
private RssPresenteur presenteurRss;
public enum TypeMoteur {
SIMPLE, AVANCEE
};
 
private TypeMoteur typeMoteur = TypeMoteur.SIMPLE;
 
private AutoCompletionComboBoxPresenteur completionTaxonsPresenteur = null;
private AutoCompletionComboBoxPresenteur completionCommunesPresenteur = null;
 
public MoteurRecherchePresenteur(Vue vue, ModeRecherche mode) {
initialiser(vue, mode, new Config());
}
 
public MoteurRecherchePresenteur(AutoCompletionComboBoxPresenteur presenteurAutoCompletionTaxon, AutoCompletionComboBoxPresenteur presenteurAutoCompletionCommunes, Vue vue, ModeRecherche mode, Config configuration) {
completionTaxonsPresenteur = presenteurAutoCompletionTaxon;
completionCommunesPresenteur = presenteurAutoCompletionCommunes;
initialiser(vue, mode, configuration);
}
 
private void initialiser(Vue vue, ModeRecherche mode, Config configuration) {
//TODO : fixer le flux avant de le mettre en place
//this.presenteurRss = new RssPresenteur(new RssVue(), CacheClient.getInstance().getInformationsRechercheObservation(), "S'abonner au flux rss des résultats de cette recherche");
//presenteurRss.go(vue.getZoneRss());
this.vue = vue;
setMode(mode);
this.config = configuration;
if (completionTaxonsPresenteur == null)
this.creerCompletionTaxons();
if (completionCommunesPresenteur == null)
this.creerCompletionCommunes();
gererEvenements();
vue.remplirListeReferentiels(ReferentielService.getReferentiels());
if(CacheClient.getInstance().getReferentielNonModifiable()) {
vue.setReferentielLectureSeule(true);
}
if(estPourRechercheImages()) {
vue.cacherChampsTagsObs();
} else {
vue.cacherChampsTagsImage();
}
}
 
public ModeRecherche getMode() {
return modeRecherche;
}
 
private void setMode(ModeRecherche mode) {
modeRecherche = mode;
}
public TypeMoteur getTypeMoteur() {
return this.typeMoteur;
}
public void setTypeMoteur(TypeMoteur typeMoteur) {
this.typeMoteur = typeMoteur;
}
 
public boolean estPourRechercheImages() {
return (modeRecherche == ModeRecherche.MODE_IMAGE);
}
 
public boolean estPourRechercheObservations() {
return (modeRecherche == ModeRecherche.MODE_OBSERVATION);
}
 
private void creerCompletionTaxons() {
String url = this.config.getServiceBaseUrl() + "nomstaxons";
completionTaxonsPresenteur = new AutoCompletionComboBoxPresenteur(new AutoCompletionComboBoxVue(), url) {
protected String effectuerPreTraitementChaineRequete(String requete) {
// si aucun référentiel selectionné, pas de requete
if(vue.getReferentiel() != null && !vue.getReferentiel().equals("")) {
requete = "?masque.nom=" + requete + "&masque.referentiel=" + vue.getReferentiel();
return requete;
} else {
return null;
}
// A décommenter lors de l'utilisation des web services eflore
// return
// RetourAutoCompletionService.effectuerPreTraitementChaineRequeteGenreEspeceEflore(requete);
}
 
@Override
protected String[] parserResultatRequete(Response response) {
return UtilitairesAutoCompletionService.parserResultatRetourSimple(response);
// A décommenter lors de l'utilisation des web services eflore
// return RetourAutoCompletionService.parserRetourOss(response);
}
};
}
 
private void creerCompletionCommunes() {
String url = this.config.getServiceBaseUrl() + "communes";
completionCommunesPresenteur = new AutoCompletionComboBoxPresenteur(new AutoCompletionComboBoxVue(), url) {
protected String effectuerPreTraitementChaineRequete(String requete) {
requete = "?masque.nom=" + requete;
return requete;
}
 
@Override
protected void surSelectionSuggestion(String suggestion) {
setValeur(suggestion);
collecterInfosRecherche();
setValeur(getInformationsRechercheEnCache().getCommune());
vue.setValeurDepartement(getInformationsRechercheEnCache().getDepartement());
}
 
@Override
protected String[] parserResultatRequete(Response response) {
return UtilitairesAutoCompletionService.parserResultatRetourSimple(response);
}
};
}
 
@Override
public void go(HasWidgets composite) {
afficherRequeteEtLancerRecherche();
completionTaxonsPresenteur.go(vue.getTaxon());
completionCommunesPresenteur.go(vue.getCommune());
vue.ajouterVue(composite);
vue.focusSaisie();
}
 
@Override
protected void gererEvenements() {
vue.getLienRechercheAvancee().addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
setTypeMoteur(TypeMoteur.AVANCEE);
vue.setContientMots(vue.getValeurRechercheSimple());
vue.basculerAffichageZoneCache();
}
});
 
vue.getBoutonRechercheSimple().addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
setTypeMoteur(TypeMoteur.SIMPLE);
collecterInfosRecherche();
afficherRequeteEtLancerRecherche();
}
});
 
vue.getBoutonFermer().addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
vue.setValeurRechercheSimple(vue.getContientMots());
vue.basculerAffichageZoneCache();
}
});
 
vue.getBoutonVider().addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
nettoyerChamps();
InformationsRecherche infosRecherche = new InformationsRecherche();
if (estPourRechercheImages()) {
CacheClient.getInstance().setInformationsRechercheImage(infosRecherche);
} else if (estPourRechercheObservations()) {
CacheClient.getInstance().setInformationsRechercheObservation(infosRecherche);
}
}
});
 
vue.getBoutonRechercheAvancee().addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
setTypeMoteur(TypeMoteur.AVANCEE);
collecterInfosRecherche();
vue.basculerAffichageZoneCache();
afficherRequeteEtLancerRecherche();
}
});
 
vue.getChampSaisie().addKeyPressHandler(new KeyPressHandler() {
public void onKeyPress(KeyPressEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
setTypeMoteur(TypeMoteur.SIMPLE);
collecterInfosRecherche();
afficherRequeteEtLancerRecherche();
}
}
});
 
vue.getChampSaisieCliquable().addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
if (vue.getValeurRechercheSimple().equals(vue.getLabelRecherche())) {
vue.setValeurRechercheSimple("");
}
}
});
 
vue.getChampsAuteur().addKeyPressHandler(creerGestionnaireEvenementToucheEntree());
vue.getChampsDate().addKeyPressHandler(creerGestionnaireEvenementToucheEntree());
vue.getChampsFamille().addKeyPressHandler(creerGestionnaireEvenementToucheEntree());
vue.getChampsGenre().addKeyPressHandler(creerGestionnaireEvenementToucheEntree());
vue.getChampsMotCle().addKeyPressHandler(creerGestionnaireEvenementToucheEntree());
vue.getChampsMotCleCel().addKeyPressHandler(creerGestionnaireEvenementToucheEntree());
vue.getChampsMotCleDel().addKeyPressHandler(creerGestionnaireEvenementToucheEntree());
vue.getChampsDepartement().addKeyPressHandler(creerGestionnaireEvenementToucheEntree());
vue.getChampsContientMots().addKeyPressHandler(creerGestionnaireEvenementToucheEntree());
 
}
 
public KeyPressHandler creerGestionnaireEvenementToucheEntree() {
return new KeyPressHandler() {
public void onKeyPress(KeyPressEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
vue.basculerAffichageZoneCache();
collecterInfosRecherche();
afficherRequeteEtLancerRecherche();
}
}
};
}
 
private void nettoyerChamps() {
completionCommunesPresenteur.nettoyer();
completionTaxonsPresenteur.nettoyer();
vue.nettoyer();
}
 
public void collecterInfosRecherche() {
InformationsRecherche informationRecherche = new InformationsRecherche();
informationRecherche.setRechercheLibre(this.getRechercheLibre());
if (this.typeMoteur == TypeMoteur.AVANCEE) {
informationRecherche.setTaxon(completionTaxonsPresenteur.getValeur());
informationRecherche.setDepartement(vue.getDepartement());
informationRecherche.setCommune(completionCommunesPresenteur.getValeur());
informationRecherche.setFamille(vue.getFamille());
informationRecherche.setGenre(vue.getGenre());
if(estPourRechercheObservations()) {
informationRecherche.setMotClef(vue.getMotCle());
} else {
informationRecherche.setMotClefDel(vue.getMotCleDel());
informationRecherche.setMotClefCel(vue.getMotCleCel());
}
informationRecherche.setTag(vue.getMotCle());
informationRecherche.setAuteur(vue.getAuteur());
informationRecherche.setDate(vue.getDate());
informationRecherche.setReferentiel(vue.getReferentiel());
}
if(CacheClient.getInstance().getReferentielNonModifiable()) {
informationRecherche.setReferentiel(CacheClient.getInstance().getReferentielCourant());
}
 
if (estPourRechercheImages()) {
CacheClient.getInstance().setPageCouranteRechercheImages(1);
CacheClient.getInstance().setInformationsRechercheImage(informationRecherche);
} else if (estPourRechercheObservations()) {
CacheClient.getInstance().setPageCouranteRechercheObservations(1);
CacheClient.getInstance().setInformationsRechercheObservation(informationRecherche);
}
}
 
private String getRechercheLibre() {
String rechercheLibre = "";
switch (this.typeMoteur) {
case SIMPLE:
rechercheLibre = vue.getValeurRechercheSimple();
break;
case AVANCEE:
rechercheLibre = vue.getContientMots();
break;
default:
// TODO : voir comment gérer les exceptions proprement
// throw new
// Exception("Le type de moteur de recherche indiqué n'est pas disponible");
}
return rechercheLibre;
}
 
private InformationsRecherche getInformationsRechercheEnCache() {
if (estPourRechercheImages()) {
return CacheClient.getInstance().getInformationsRechercheImage();
} else if (estPourRechercheObservations()) {
return CacheClient.getInstance().getInformationsRechercheObservation();
}
return null;
}
 
public void afficherRequeteEtLancerRecherche() {
InformationsRecherche informationsRecherche = getInformationsRechercheEnCache();
if (informationsRecherche != null) {
completionTaxonsPresenteur.setValeur(informationsRecherche.getTaxon());
completionCommunesPresenteur.setValeur(informationsRecherche.getCommune());
vue.chargerValeursRecherchePrecedente(informationsRecherche);
}
lancerRecherche();
//presenteurRss.genererLien(informationsRecherche);
}
 
public abstract void lancerRecherche();
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/moteurrecherche/MoteurRechercheVue.java
New file
0,0 → 1,316
package org.tela_botanica.del.client.composants.moteurrecherche;
 
import java.util.Iterator;
import java.util.Map;
 
import org.tela_botanica.del.client.i18n.I18n;
import org.tela_botanica.del.client.modeles.InformationsRecherche;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasKeyPressHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
 
public class MoteurRechercheVue extends Composite implements MoteurRecherchePresenteur.Vue {
 
interface Binder extends UiBinder<Widget, MoteurRechercheVue> {
}
 
private static Binder uiBinder = GWT.create(Binder.class);
private String labelRecherche = "";
 
@UiField
Panel rechercheAvancee, taxon, commune, zoneRss, conteneurMotCle, conteneurMotCleCel, conteneurMotCleDel ;
@UiField
Label lienRechercheAvancee, recherchePrecedente;
@UiField
Button boutonRecherche, boutonRechercheAvancee, boutonFermer, boutonVider;
@UiField
TextBox recherchePrincipale, contientMots, departement, famille, genre, motCle, motCleCel, motCleDel, auteur, date;
@UiField
ListBox referentiel;
private boolean referentielLectureSeule = false;
 
public MoteurRechercheVue(String labelRecherche) {
initWidget(uiBinder.createAndBindUi(this));
this.labelRecherche = labelRecherche;
recherchePrincipale.setText(labelRecherche);
rechercheAvancee.setVisible(false);
}
@Override
public void remplirListeReferentiels(Map<String, String> listeReferentiels) {
for (Iterator<String> iterator = listeReferentiels.keySet().iterator(); iterator.hasNext();) {
String codeRef = iterator.next();
referentiel.addItem(listeReferentiels.get(codeRef), codeRef);
}
}
 
public String getLabelRecherche() {
return labelRecherche;
}
 
public HasClickHandlers getLienRechercheAvancee() {
return lienRechercheAvancee;
}
 
public HasClickHandlers getBoutonRechercheSimple() {
return boutonRecherche;
}
 
public HasClickHandlers getBoutonFermer() {
return boutonFermer;
}
 
public HasClickHandlers getBoutonVider() {
return boutonVider;
}
 
public HasClickHandlers getBoutonRechercheAvancee() {
return boutonRechercheAvancee;
}
 
public HasKeyPressHandlers getChampSaisie() {
return recherchePrincipale;
}
 
public String getValeurRechercheSimple() {
return recherchePrincipale.getText();
}
 
public void setValeurRechercheSimple(String valeurRecherche) {
recherchePrincipale.setText(valeurRecherche);
}
 
public HasClickHandlers getChampSaisieCliquable() {
return recherchePrincipale;
}
 
public String getContientMots() {
return contientMots.getText();
}
 
public void setContientMots(String mots) {
contientMots.setText(mots);
}
 
public String getDepartement() {
return departement.getText();
}
 
public void setValeurDepartement(String dpt) {
departement.setValue(dpt);
}
 
public HasWidgets getCommune() {
return commune;
}
 
public HasWidgets getTaxon() {
return taxon;
}
 
public String getFamille() {
return famille.getText();
}
 
public String getGenre() {
return genre.getText();
}
 
public String getMotCle() {
return motCle.getText();
}
 
public String getAuteur() {
return auteur.getText();
}
 
public String getDate() {
return date.getText();
}
public String getReferentiel() {
return referentiel.getValue(referentiel.getSelectedIndex());
}
 
public void focusSaisie() {
this.recherchePrincipale.setFocus(true);
}
 
public void ajouterVue(HasWidgets composite) {
composite.add(this.asWidget());
}
 
public void basculerAffichageZoneCache() {
rechercheAvancee.setVisible(!rechercheAvancee.isVisible());
recherchePrincipale.setVisible(!recherchePrincipale.isVisible());
boutonRecherche.setVisible(!boutonRecherche.isVisible());
}
 
public void nettoyer() {
chargerValeursRecherchePrecedente(new InformationsRecherche());
}
 
public void chargerValeursRecherchePrecedente(InformationsRecherche informationsRecherche) {
recherchePrincipale.setText(informationsRecherche.getRechercheLibre());
contientMots.setText(informationsRecherche.getRechercheLibre());
departement.setText(informationsRecherche.getDepartement());
famille.setText(informationsRecherche.getFamille());
genre.setText(informationsRecherche.getGenre());
motCle.setText(informationsRecherche.getMotClef());
motCleCel.setText(informationsRecherche.getMotClefCel());
motCleDel.setText(informationsRecherche.getMotClefDel());
auteur.setText(informationsRecherche.getAuteur());
date.setText(informationsRecherche.getDate());
for(int i = 0; i < referentiel.getItemCount(); i++) {
if(referentiel.getValue(i).equals(informationsRecherche.getReferentiel())) {
referentiel.setSelectedIndex(i);
}
}
 
afficherLigneInfoRecherche(informationsRecherche);
}
 
/**
* Affiche la ligne d'en tête montrant les elements de la requête à
* l'utilisateur
*
* @param informationRecherche
*/
private void afficherLigneInfoRecherche(InformationsRecherche informationRecherche) {
// tax dep com fam gen ta mo au date
StringBuffer texteRecherchePrecedente = new StringBuffer();
 
if (informationRecherche.getRechercheLibre() != null && !informationRecherche.getRechercheLibre().equals("")) {
texteRecherchePrecedente.append(I18n.getVocabulary().rechercheLibre() + ":" + informationRecherche.getRechercheLibre() + " ");
}
if (informationRecherche.getTaxon() != null && !informationRecherche.getTaxon().equals("")) {
texteRecherchePrecedente.append(I18n.getVocabulary().taxon() + ":" + informationRecherche.getTaxon() + " ");
}
if (informationRecherche.getDepartement() != null && !informationRecherche.getDepartement().equals("")) {
texteRecherchePrecedente.append(I18n.getVocabulary().departement() + ":" + informationRecherche.getDepartement() + " ");
}
if (informationRecherche.getCommune() != null && !informationRecherche.getCommune().equals("")) {
texteRecherchePrecedente.append(I18n.getVocabulary().commune() + ":" + informationRecherche.getCommune() + " ");
}
if (informationRecherche.getFamille() != null && !informationRecherche.getFamille().equals("")) {
texteRecherchePrecedente.append(I18n.getVocabulary().famille() + ":" + informationRecherche.getFamille() + " ");
}
if (informationRecherche.getGenre() != null && !informationRecherche.getGenre().equals("")) {
texteRecherchePrecedente.append(I18n.getVocabulary().genre() + ":" + informationRecherche.getGenre() + " ");
}
if (informationRecherche.getTag() != null && !informationRecherche.getTag().equals("")) {
texteRecherchePrecedente.append(I18n.getVocabulary().tag() + ":" + informationRecherche.getTag() + " ");
}
if (informationRecherche.getMotClef() != null && !informationRecherche.getMotClef().equals("")) {
texteRecherchePrecedente.append(I18n.getVocabulary().mot_clef() + ":" + informationRecherche.getMotClef() + " ");
}
if (informationRecherche.getMotClefCel() != null && !informationRecherche.getMotClefCel().equals("")) {
texteRecherchePrecedente.append(I18n.getVocabulary().tagCel() + ":" + informationRecherche.getMotClefCel() + " ");
}
if (informationRecherche.getMotClefDel() != null && !informationRecherche.getMotClefDel().equals("")) {
texteRecherchePrecedente.append(I18n.getVocabulary().tagDel() + ":" + informationRecherche.getMotClefDel() + " ");
}
if (informationRecherche.getAuteur() != null && !informationRecherche.getAuteur().equals("")) {
texteRecherchePrecedente.append(I18n.getVocabulary().auteur() + ":" + informationRecherche.getAuteur() + " ");
}
if (informationRecherche.getDate() != null && !informationRecherche.getDate().equals("")) {
texteRecherchePrecedente.append(I18n.getVocabulary().date() + ":" + informationRecherche.getDate() + " ");
}
if (informationRecherche.getReferentiel() != null && !informationRecherche.getReferentiel().equals("")) {
texteRecherchePrecedente.append(I18n.getVocabulary().referentiel() + ":" + informationRecherche.getReferentiel() + " ");
}
 
recherchePrecedente.setText(texteRecherchePrecedente.toString());
}
 
@Override
public HasKeyPressHandlers getChampsFamille() {
return famille;
}
 
@Override
public HasKeyPressHandlers getChampsGenre() {
return genre;
}
 
@Override
public HasKeyPressHandlers getChampsMotCle() {
return motCle;
}
 
@Override
public HasKeyPressHandlers getChampsAuteur() {
return auteur;
}
 
@Override
public HasKeyPressHandlers getChampsDate() {
return date;
}
 
@Override
public HasKeyPressHandlers getChampsDepartement() {
return departement;
}
 
@Override
public HasKeyPressHandlers getChampsContientMots() {
return contientMots;
}
public HasWidgets getZoneRss() {
return zoneRss;
}
 
@Override
public void setReferentielLectureSeule(boolean lectureSeule) {
referentielLectureSeule = true;
// la listbox ne possède aucun méthode directe pour être désactivée
DOM.setElementProperty(referentiel.getElement(), "disabled", "disabled");
}
 
@Override
public HasKeyPressHandlers getChampsMotCleDel() {
return motCleDel;
}
 
@Override
public HasKeyPressHandlers getChampsMotCleCel() {
return motCleCel;
}
 
@Override
public String getMotCleDel() {
return motCleDel.getText();
}
 
@Override
public String getMotCleCel() {
return motCleCel.getText();
}
 
@Override
public void cacherChampsTagsImage() {
conteneurMotCleCel.setVisible(false);
conteneurMotCleDel.setVisible(false);
}
 
@Override
public void cacherChampsTagsObs() {
conteneurMotCle.setVisible(false);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/moteurrecherche/MoteurRecherche.css
New file
0,0 → 1,86
.recherchePrincipale {
width: 550px;
font-size: 18px;
padding: 5px;
border: solid 1px #AAA;
float: left;
}
 
.boutonRecherche {
border: solid 1px #AAA;
padding: 5px;
cursor: pointer;
float: left;
margin: 0 10px 0 10px
}
 
.lienRechercheAvancee {
cursor: pointer;
text-decoration: underline;
color: blue;
float: left;
margin-right: 240px;
margin: 5px
}
 
.rechercheAvancee {
border: solid 1px #333;
padding: 15px;
position: absolute;
width: 750px;
margin-top: 0px;
background: white;
z-index: 2000
}
 
.champRecherche {
float: left;
width: 40%;
padding-bottom: 5px
}
 
.champRecherche input {
width: 90%
}
 
.recherchePrecedente {
color: #555;
padding: 5px 5px 10px;
font-style: italic;
clear: left
}
 
.boutonFermer {
float: right;
background: url("./img/cross.png") no-repeat 0 2px;
border: none;
padding: 0 0 0 16px;
color: blue;
text-decoration: underline;
cursor: pointer
}
 
.boutonVider {
float: right;
background: url("./img/cancel.png") no-repeat 0 2px;
border: none;
padding: 0 0 0 16px;
color: blue;
text-decoration: underline;
cursor: pointer
}
 
.rechercherAvance {
margin-top:10px;
margin-left:0px;
}
 
.zoneRecherche {
}
.zoneRss {
float:right;
margin-top:5px;
}
.zoneRss a {
border:none;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/commentaires/DetailCommentaireVue.ui.xml
New file
0,0 → 1,19
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:vues="urn:import:org.tela_botanica.del.client.composants.forum">
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
<ui:style src="detailCommentaireVue.css" />
<g:HTMLPanel styleName="{style.conteneurTableauVotes}">
<g:HTMLPanel ui:field='titre' styleName="titre" />
<g:HTMLPanel ui:field='auteur' styleName="{style.auteur}" />
<g:HTMLPanel ui:field="ligneCommentaire" styleName="{style.zoneCommentaires}"></g:HTMLPanel>
<g:HTMLPanel ui:field="panneauChargement" styleName="{style.chargement}">
<g:Image url="./img/wait.gif"></g:Image>
</g:HTMLPanel>
<g:HTMLPanel ui:field="aucuneDonnees" visible="false"><g:Label text="{constants.aucunCommentaireEffectue}"></g:Label></g:HTMLPanel>
<g:Button ui:field="boutonAjoutCommentaire" styleName="bouton {style.boutonAjouterCommentaire}"
text="{constants.ajouterCommentaire}" />
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/commentaires/LigneCommentaireVue.java
New file
0,0 → 1,38
package org.tela_botanica.del.client.composants.commentaires;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
 
public class LigneCommentaireVue extends Composite implements LigneCommentairePresenteur.Vue {
 
interface LigneCommentaireVueUiBinder extends UiBinder<Widget, LigneCommentaireVue> {};
private static LigneCommentaireVueUiBinder uiBinder = GWT.create(LigneCommentaireVueUiBinder.class);
//Composants
@UiField
Label commentaire, auteur, date;
public LigneCommentaireVue() {
initWidget(uiBinder.createAndBindUi(this));
}
@Override
public void setCommentaire(String commentaire) {
this.commentaire.setText(commentaire);
}
@Override
public void setAuteur(String auteur) {
this.auteur.setText(auteur);
}
@Override
public void setDate(String date) {
this.date.setText(date);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/commentaires/DetailCommentairePresenteur.java
New file
0,0 → 1,170
package org.tela_botanica.del.client.composants.commentaires;
 
import java.util.List;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlayDefilanteVue;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlaySimplePresenteur;
import org.tela_botanica.del.client.composants.formulaires.formulairecommentaire.FormulaireCommentairePresenteur;
import org.tela_botanica.del.client.composants.formulaires.formulairecommentaire.FormulaireCommentaireVue;
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.modeles.Commentaire;
import org.tela_botanica.del.client.modeles.InterventionForum;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.ajoutcommentaire.EvenementAjoutCommentaire;
import org.tela_botanica.del.client.navigation.evenement.ajoutcommentaire.GestionnaireEvenementAjoutCommentaire;
import org.tela_botanica.del.client.services.rest.CommentaireService;
import org.tela_botanica.del.client.services.rest.CommentaireServiceConcret;
import org.tela_botanica.del.client.services.rest.async.ListeCommentairesCallback;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
/**
* Cette classe permet d'afficher une popup avec la liste des commentaires
* associées à une proposition de determination
*
* @author LIENS
*
*/
public class DetailCommentairePresenteur extends Presenteur {
 
/**
* Interface de la vue correspondante
*
* @author LIENS
*
*/
public interface Vue extends IsWidget {
public void afficherCommentairesProposition(PropositionDetermination propositionDetermination);
 
public void afficherAucuneDonnees();
 
public void stopChargement();
 
public void startChargement();
public HasClickHandlers getBoutonAjoutCommentaire();
}
 
// La vue correspondante
private Vue vue;
 
// La proposition de determination
private PropositionDetermination propositionDetermination;
//le servcie de recuperation des commentaires
private CommentaireService commentaireService;
 
/**
* Constructeur
*
* @param vue
* @param propositionDetermination
*/
public DetailCommentairePresenteur(Vue vue, CommentaireService commentaireService, PropositionDetermination propositionDetermination) {
this.vue = vue;
this.propositionDetermination = propositionDetermination;
this.commentaireService = commentaireService;
}
 
/**
* Declenchement du présenteur
*/
public void go(HasWidgets container) {
container.add(vue.asWidget());
gererEvenements();
}
 
/**
* Affichage des commentaires
*/
public void afficherCommentaires() {
 
// affichage de l'icone de chargement
vue.startChargement();
// si l'id de la propostion est égal est nulle alors celle ci est une proposition
// crée par l'interface à partir de l'obs et n'a donc pas de commentaires
if(propositionDetermination.getId() != null) {
 
// Appel du service
commentaireService.chargerCommentaires(propositionDetermination, new ListeCommentairesCallback() {
 
@Override
public void surRetour(List<Commentaire> commentaires) {
 
propositionDetermination.setListeCommentaires(commentaires);
// s'il existe des commentaires ils sont affichés
if (propositionDetermination.getTotalCommentaires() > 0) {
 
// affichage des commentaires associés à la proposition dans
// la vue
vue.afficherCommentairesProposition(propositionDetermination);
 
// supression de l'icone de chargement
vue.stopChargement();
} else {
 
// affichage d'un message precisant qu'il n'y a pas de
// commentaires
vue.afficherAucuneDonnees();
 
// supression de l'icone de chargement
vue.stopChargement();
}
 
}
 
@Override
public void surErreur(String messageErreur) {
Window.alert(messageErreur);
vue.stopChargement();
}
});
} else {
// affichage d'un message precisant qu'il n'y a pas de
// commentaires
vue.afficherAucuneDonnees();
 
// supression de l'icone de chargement
vue.stopChargement();
}
}
 
/**
* Gestion des evenements du presenteur
*/
@Override
protected void gererEvenements() {
final FenetreOverlaySimplePresenteur fenetreOverlaySimplePresenteur = new FenetreOverlaySimplePresenteur(new FenetreOverlayDefilanteVue());
 
vue.getBoutonAjoutCommentaire().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
// TODO : > mettre proprement l'intervention
// TODO : >actualiser les affichages
CacheClient.getInstance().setObservationCourante(propositionDetermination.getObservation());
FormulaireCommentairePresenteur commentairePresenteur = new FormulaireCommentairePresenteur(propositionDetermination.getObservation().getInterventionsForum().get(propositionDetermination.getObservation().getInterventionsForum().size()-1), new CommentaireServiceConcret(), new FormulaireCommentaireVue());
fenetreOverlaySimplePresenteur.ouvrirFenetreModale(commentairePresenteur);
}
});
BusEvenementiel.getInstance().addHandler(EvenementAjoutCommentaire.TYPE, new GestionnaireEvenementAjoutCommentaire() {
 
@Override
public void onAjoutCommentaire(EvenementAjoutCommentaire event) {
if (fenetreOverlaySimplePresenteur != null && fenetreOverlaySimplePresenteur.fenetreModaleEstOuverte()) {
fenetreOverlaySimplePresenteur.fermerFenetreModale();
}
}
});
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/commentaires/DetailCommentaireVue.java
New file
0,0 → 1,118
package org.tela_botanica.del.client.composants.commentaires;
 
import java.util.List;
 
import org.tela_botanica.del.client.i18n.I18n;
import org.tela_botanica.del.client.modeles.Commentaire;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
/**
* Cette classe permet d'afficher une popup avec la liste des commentaires
* associées à une proposition de determination
*
* @author LIENS
*
*/
public class DetailCommentaireVue extends Composite implements DetailCommentairePresenteur.Vue {
 
private static DetailListeVotesDeterminationVueUIiBinder uiBinder = GWT.create(DetailListeVotesDeterminationVueUIiBinder.class);
 
interface DetailListeVotesDeterminationVueUIiBinder extends UiBinder<Widget, DetailCommentaireVue> {
};
 
@UiField
HTMLPanel titre, auteur, aucuneDonnees;
 
@UiField
Panel panneauChargement, ligneCommentaire;
 
@UiField
Button boutonAjoutCommentaire;
@Override
public Button getBoutonAjoutCommentaire() {
return boutonAjoutCommentaire;
}
 
public DetailCommentaireVue() {
initWidget(uiBinder.createAndBindUi(this));
}
 
/**
* Affiche les commentaires associées à une proposition de determination
*/
@Override
public void afficherCommentairesProposition(PropositionDetermination propositionDetermination) {
HTML htmlTitre = new HTML(propositionDetermination.getEspece());
titre.add(htmlTitre);
HTML htmlAuteur = new HTML(I18n.getVocabulary().proposePar()+propositionDetermination.getAuteur());
auteur.add(htmlAuteur);
 
LigneCommentairePresenteur presenteurCommentaire = new LigneCommentairePresenteur(new LigneCommentaireVue(), propositionDetermination);
presenteurCommentaire.go(ligneCommentaire);
 
creerListeCommentaireRecursive(propositionDetermination.getListeCommentaires());
}
 
/**
* Affiche une liste de commentaires recursivement
* @param commentaires
*/
private void creerListeCommentaireRecursive(List<Commentaire> commentaires) {
 
for (Commentaire commentaire : commentaires) {
chargerCommentaire(commentaire);
if (commentaire.getListeCommentaires().size() > 0) {
creerListeCommentaireRecursive(commentaire.getListeCommentaires());
}
}
}
 
/**
* Affiche un commentaire
* @param commentaire
*/
private void chargerCommentaire(Commentaire commentaire) {
LigneCommentairePresenteur presenteurCommentaire = new LigneCommentairePresenteur(new LigneCommentaireVue(), commentaire);
presenteurCommentaire.go(ligneCommentaire);
}
 
/**
* Affiche un icone de début de chargement
*/
@Override
public void startChargement() {
panneauChargement.setHeight((this.getOffsetHeight() / 2) + "px");
panneauChargement.setWidth((this.getOffsetWidth() / 2) + "px");
panneauChargement.setVisible(true);
}
 
/**
* Cache l'icone de début de chargement
*/
@Override
public void stopChargement() {
panneauChargement.setVisible(false);
}
 
/**
* Affiche un message indiquant qu'il n'y a aucun commentaire à présenter
*/
@Override
public void afficherAucuneDonnees() {
aucuneDonnees.setVisible(true);
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/commentaires/ligneCommentaire.css
New file
0,0 → 1,25
.commentaire {
font-size: 11px;
background: #DDD;
padding: 3px;
margin-bottom:5px;
}
 
.auteur {
padding-left:3px;
float: left;
font-size:11px;
color:#AAA;
font-style:italic;
}
 
.date {
float: left;
font-size:11px;
color:#DDD;
font-style:italic;
}
 
.date:before {
content:", ";
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/commentaires/LigneCommentaireVue.ui.xml
New file
0,0 → 1,17
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:vues="urn:import:org.tela_botanica.del.client.composants.forum">
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
<ui:style src="ligneCommentaire.css" />
<g:HTMLPanel>
<g:HorizontalPanel ui:field="zoneAuteur">
<g:Label ui:field="auteur" styleName="{style.auteur}"/>
<g:Label ui:field="date" styleName="{style.date}"/>
</g:HorizontalPanel>
<g:HTMLPanel>
<g:Label ui:field="commentaire" styleName="commentaire {style.commentaire}"/>
</g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/commentaires/detailCommentaireVue.css
New file
0,0 → 1,41
.conteneurTableauVotes {
z-index: 1500;
padding: 30px;
padding-right: 21px;
padding-top: 20px;
background: white;
width: 370px;
margin: 0 auto;
margin-top: 75px;
padding-bottom:50px;
}
 
.table {
border:solid 1px #DDD;
width: 100%;
}
 
.chargement {
padding-left: 165px;
}
 
.auteur {
color: #6C6865;
font-family: arial;
font-size: 13px;
font-style: italic;
font-weight: bold;
letter-spacing: 0;
line-height: 18px;
text-transform: none;
margin-top: -10px;
}
 
.boutonAjouterCommentaire {
margin:30px 0;
}
 
.zoneCommentaires {
max-height: 400px;
overflow:auto;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/commentaires/LigneCommentairePresenteur.java
New file
0,0 → 1,70
package org.tela_botanica.del.client.composants.commentaires;
 
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.modeles.Commentaire;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
 
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class LigneCommentairePresenteur extends Presenteur {
 
public interface Vue extends IsWidget {
public void setCommentaire(String commentaire);
public void setAuteur(String auteur);
public void setDate(String date);
}
 
private Vue vue;
private PropositionDetermination proposition;
private Commentaire commentaire;
public LigneCommentairePresenteur(Vue vue, PropositionDetermination proposition) {
this.vue = vue;
this.proposition = proposition;
afficherCommentaire();
}
public LigneCommentairePresenteur(Vue vue, Commentaire commentaire) {
this.vue = vue;
this.commentaire = commentaire;
afficherCommentaire();
}
 
public void afficherCommentaire() {
if (proposition != null) {
String commentaire = proposition.getCommentaire();
vue.setCommentaire(commentaire);
String date = DateTimeFormat.getFormat("dd/MM/yyyy").format(proposition.getDate());
vue.setDate(date);
String auteur = proposition.getAuteur();
vue.setAuteur(auteur);
} else if (commentaire != null) {
String commentaire = this.commentaire.getCommentaire();
vue.setCommentaire(commentaire);
String date = DateTimeFormat.getFormat("dd/MM/yyyy").format(this.commentaire.getDate());
vue.setDate(date);
String auteur = this.commentaire.getAuteur();
vue.setAuteur(auteur);
}
}
/**
* Declenchement du présenteur
*/
public void go(HasWidgets container) {
container.add(vue.asWidget());
gererEvenements();
}
 
protected void gererEvenements() {
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulaires/formulairecommentaire/formulaireCommentaire.css
New file
0,0 → 1,69
.formulaireProposition {
z-index: 1500;
padding: 50px;
background: white;
width: 300px;
margin: 0 auto;
margin-top: 75px;
}
 
.boutonProposer:hover {
background-color: #AAA
}
 
.colonneGauche,.colonneDroite {
width: 250px;
}
 
.colonneGauche {
padding-right: 30px
}
 
.colonneGauche select {
width: 100%
}
 
.colonneGauche input {
width: 95%
}
 
.commentaire {
width: 250px;
height: 100px
}
 
.propositionTaxon {
width: 100%;
height: 30px;
}
 
.boutonProposer {
border: solid 1px #AAA;
cursor: pointer;
float: left;
margin-top: 10px;
margin-bottom: 5px;
margin-right: 30px;
float: right;
background: url(./img/add.png) no-repeat 5px 7px #DDD;
padding: 5px;
padding-left: 25px;
cursor: pointer
}
 
 
.zoneNom {
width:30%;
float:left;
margin-right:5px;
}
 
.zonePrenom {
width:30%;
float:left;
}
 
.zoneEmail {
clear:left;
padding-top:5px;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulaires/formulairecommentaire/FormulaireCommentaireVue.ui.xml
New file
0,0 → 1,36
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary"/>
<ui:style src="formulaireCommentaire.css" />
<g:VerticalPanel styleName="{style.formulaireProposition}">
<g:Label text="{constants.ajouterCommentaire}" styleName="titre"/>
<g:Label text="{constants.infoProposerCommentaire}" styleName="petit"/>
<g:HTML><br /></g:HTML>
<g:HTMLPanel>
<g:HTMLPanel styleName="{style.colonneGauche}">
<g:Label text="{constants.vous}" styleName="sousTitre"/>
<g:Label text="{constants.infoVous}" styleName="petit" />
<g:HTMLPanel styleName="{style.zoneNom}">
<g:Label text="{constants.nom}" styleName="petit" />
<g:TextBox ui:field="nom"/>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.zonePrenom}">
<g:Label text="{constants.prenom}" styleName="petit" />
<g:TextBox ui:field="prenom"/>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.zoneEmail}">
<g:Label text="Votre adresse email : " styleName="petit" />
<g:TextBox ui:field="courriel" />
</g:HTMLPanel>
<g:HTML><br /></g:HTML>
<g:Label text="{constants.commentaire}" styleName="sousTitre"/>
<g:TextArea ui:field="commentaire" styleName="{style.commentaire}" />
</g:HTMLPanel>
</g:HTMLPanel>
<g:Button text="{constants.boutonProposer}" ui:field="boutonValidationCommentaire" styleName="{style.boutonProposer} arrondi"/>
</g:VerticalPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulaires/formulairecommentaire/FormulaireCommentairePresenteur.java
New file
0,0 → 1,210
package org.tela_botanica.del.client.composants.formulaires.formulairecommentaire;
 
import java.util.Date;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.composants.validation.ValidateurChampTexteNonNul;
import org.tela_botanica.del.client.modeles.Commentaire;
import org.tela_botanica.del.client.modeles.Contributeur;
import org.tela_botanica.del.client.modeles.InterventionForum;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.modeles.Utilisateur;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.ajoutcommentaire.EvenementAjoutCommentaire;
import org.tela_botanica.del.client.services.rest.CommentaireService;
import org.tela_botanica.del.client.services.rest.async.AjoutCommentaireCallback;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class FormulaireCommentairePresenteur extends Presenteur {
 
// le meme presenteur gere les commentaires pour les observations et pour
// les possesseurs de commentaires, mais la logique est differente, d'ou la
// necessité de separer les deux objets metiers
private Observation observation;
 
private InterventionForum possesseurDeCommentaires;
 
public interface Vue extends IsWidget {
 
public HasText getNomObjet();
 
public HasText getPrenomObjet();
 
public String getNom();
 
public String getPrenom();
 
public String getCourriel();
 
public abstract HasText getCommentaire();
 
public abstract HasClickHandlers getBoutonValidationCommentaire();
 
public void afficherStyleErreurNom(String styleErreur);
 
public void supprimerStyleErreurNom(String styleErreur);
 
public void afficherStyleErreurPrenom(String styleErreur);
 
public void supprimerStyleErreurPrenom(String styleErreur);
public void afficherStyleErreurCourriel(String styleErreur);
 
public void supprimerStyleErreurCourriel(String styleErreur);
 
public void afficherStyleErreurCommentaire(String styleErreur);
 
public void supprimerStyleErreurCommentaire(String styleErreur);
 
void afficherNomPrenomEtDesactiver(String nom, String prenom, String courriel);
 
public HasText getCourrielObjet();
}
 
private Vue vue;
private CommentaireService commentaireService;
 
public FormulaireCommentairePresenteur(Observation observation, CommentaireService commentaireService, Vue vue) {
this.observation = observation;
this.vue = vue;
this.commentaireService = commentaireService;
}
 
public FormulaireCommentairePresenteur(InterventionForum possesseurDeCommentaires, CommentaireService commentaireService, Vue vue) {
this.possesseurDeCommentaires = possesseurDeCommentaires;
this.commentaireService = commentaireService;
this.vue = vue;
}
 
public void go(HasWidgets composite) {
remplirAvecInfosUtilisateur();
composite.add(vue.asWidget());
gererEvenements();
}
 
private void remplirAvecInfosUtilisateur() {
Utilisateur utilisateur = CacheClient.getInstance().getUtilisateur();
if (utilisateur.estIdentifie()) {
vue.afficherNomPrenomEtDesactiver(utilisateur.getNom(), utilisateur.getPrenom(), utilisateur.getCourriel());
}
}
 
protected void gererEvenements() {
vue.getBoutonValidationCommentaire().addClickHandler(new ClickHandler() {
 
@Override
public void onClick(ClickEvent event) {
if (!validerSaisie()) {
return;
}
 
surValidationCommentaire();
}
});
}
 
public void surValidationCommentaire() {
String texteCommentaire = vue.getCommentaire().getText();
String idUtilisateur = null;
if (CacheClient.getInstance().getUtilisateur().estIdentifie()) {
idUtilisateur = CacheClient.getInstance().getUtilisateur().getId();
}
 
Contributeur contributeur = new Contributeur(idUtilisateur, vue.getNom(), vue.getPrenom(), vue.getCourriel());
final Commentaire commentaire = new Commentaire(contributeur, new Date(), texteCommentaire);
 
if (observation != null) {
commentaire.setObservation(observation);
commentaire.setParent(null);
} else if (possesseurDeCommentaires != null) {
commentaire.setObservation(CacheClient.getInstance().getObservationCourante());
commentaire.setParent(possesseurDeCommentaires);
}
commentaireService.ajouterCommentaire(commentaire, new AjoutCommentaireCallback() {
 
@Override
public void surRetour(String idNouveauCommentaire) {
commentaire.setId(idNouveauCommentaire);
if (observation != null) {
observation.getInterventionsForum().add(commentaire);
} else if (possesseurDeCommentaires != null) {
possesseurDeCommentaires.getListeCommentaires().add(commentaire);
}
BusEvenementiel.getInstance().fireEvent(new EvenementAjoutCommentaire(commentaire));
}
 
@Override
public void surErreur(String messageErreur) {
Window.alert(messageErreur);
}
});
}
 
private boolean validerSaisie() {
 
ValidateurChampTexteNonNul validateurNom = new ValidateurChampTexteNonNul(vue.getNomObjet()) {
@Override
public void afficherStyleErreur(String styleErreur) {
vue.afficherStyleErreurNom(styleErreur);
}
 
@Override
public void supprimerStyleErreur(String styleErreur) {
vue.supprimerStyleErreurNom(styleErreur);
}
};
ValidateurChampTexteNonNul validateurPrenom = new ValidateurChampTexteNonNul(vue.getPrenomObjet()) {
@Override
public void afficherStyleErreur(String styleErreur) {
vue.afficherStyleErreurPrenom(styleErreur);
}
 
@Override
public void supprimerStyleErreur(String styleErreur) {
vue.supprimerStyleErreurPrenom(styleErreur);
}
};
ValidateurChampTexteNonNul validateurCourriel = new ValidateurChampTexteNonNul(vue.getCourrielObjet()) {
@Override
public void afficherStyleErreur(String styleErreur) {
vue.afficherStyleErreurCourriel(styleErreur);
}
 
@Override
public void supprimerStyleErreur(String styleErreur) {
vue.supprimerStyleErreurCourriel(styleErreur);
}
};
 
ValidateurChampTexteNonNul validateurCommentaire = new ValidateurChampTexteNonNul(vue.getCommentaire()) {
@Override
public void afficherStyleErreur(String styleErreur) {
vue.afficherStyleErreurCommentaire(styleErreur);
}
 
@Override
public void supprimerStyleErreur(String styleErreur) {
vue.supprimerStyleErreurCommentaire(styleErreur);
}
};
boolean nomSaisi = validateurNom.valider();
boolean prenomSaisi = validateurPrenom.valider();
boolean courrielSaisi = validateurCourriel.valider();
boolean commentaireSaisi = validateurCommentaire.valider();
 
return nomSaisi && prenomSaisi && courrielSaisi && commentaireSaisi;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulaires/formulairecommentaire/FormulaireCommentaireVue.java
New file
0,0 → 1,126
package org.tela_botanica.del.client.composants.formulaires.formulairecommentaire;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
 
public class FormulaireCommentaireVue extends Composite implements FormulaireCommentairePresenteur.Vue {
@UiField
public TextBox nom, prenom, courriel;
 
@UiField
public TextArea commentaire;
 
@UiField
public Button boutonValidationCommentaire;
 
interface FormulairePropositionUIiBinder extends UiBinder<Widget, FormulaireCommentaireVue> {
};
 
FormulairePropositionUIiBinder uiBinder = GWT.create(FormulairePropositionUIiBinder.class);
 
public FormulaireCommentaireVue() {
initWidget(uiBinder.createAndBindUi(this));
}
 
@Override
public String getNom() {
return nom.getText();
}
@Override
public String getPrenom() {
return prenom.getText();
}
 
@Override
public TextArea getCommentaire() {
return commentaire;
}
 
@Override
public Button getBoutonValidationCommentaire() {
return boutonValidationCommentaire;
}
@Override
public void afficherStyleErreurCommentaire(String styleErreur) {
commentaire.addStyleName(styleErreur);
}
 
@Override
public void supprimerStyleErreurCommentaire(String styleErreur) {
commentaire.removeStyleName(styleErreur);
}
@Override
public void afficherStyleErreurNom(String styleErreur) {
nom.addStyleName(styleErreur);
}
 
@Override
public void supprimerStyleErreurNom(String styleErreur) {
nom.removeStyleName(styleErreur);
}
@Override
public void afficherStyleErreurPrenom(String styleErreur) {
prenom.addStyleName(styleErreur);
}
 
@Override
public void supprimerStyleErreurPrenom(String styleErreur) {
prenom.removeStyleName(styleErreur);
}
@Override
public void afficherNomPrenomEtDesactiver(String nom, String prenom, String courriel) {
this.nom.setText(nom);
this.nom.setEnabled(false);
this.prenom.setText(prenom);
this.prenom.setEnabled(false);
this.courriel.setText(courriel);
this.courriel.setEnabled(false);
}
 
@Override
public HasText getNomObjet() {
return nom;
}
@Override
public HasText getPrenomObjet() {
return prenom;
}
 
@Override
public String getCourriel() {
return courriel.getText();
}
 
@Override
public void afficherStyleErreurCourriel(String styleErreur) {
courriel.addStyleName(styleErreur);
}
 
@Override
public void supprimerStyleErreurCourriel(String styleErreur) {
courriel.removeStyleName(styleErreur);
}
 
@Override
public HasText getCourrielObjet() {
return courriel;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulaires/identification/FormulaireIdentificationVueBinderImplGenMessages.properties
New file
0,0 → 1,10
texteConnexion=<a href="http://www.tela-botanica.org/page:inscription">S''inscrire... </a> \
<p class="connect gris">Devenez telabotaniste et partagez votre passion pour le végétal !</p> \
<p> <a href="http://www.tela-botanica.org/page:inscription?m=f_oubli_mdp" id="lien_inscription">Mot de passe perdu ? </a></p>
 
 
 
#<a href="/page:inscription">S'inscrire... </a>
# <p class="connectgris">Devenez telabotaniste et partagez votre passion pour le végétal !</p>
# <p> <a href="http://www.tela-botanica.org/page:inscription?m=f_oubli_mdp" id="lien_inscription">Mot de passe perdu ? </a></p>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulaires/identification/FormulaireIdentificationVue.ui.xml
New file
0,0 → 1,34
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui' ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateLocales="default">
<ui:with field='res' type='org.tela_botanica.del.client.resources.Ressources' />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
<ui:style src="identification.css" />
<g:HTMLPanel styleName="{style.zoneIdentification} {style.zoneFormulaire}">
<g:Label ui:field="titreSeConnecter" styleName="{style.connecter}" text="{constants.titreSeConnecter}" />
<g:Label ui:field="titreEstIdentifie" styleName="{style.connecter}" text="{constants.titreEstIdentifie}" />
<g:HTMLPanel ui:field="zoneUtilisateur">
<g:HTMLPanel styleName="{style.infoConnexion}">
<g:Label ui:field="email" styleName="{style.email}">Email</g:Label>
<g:Label ui:field="preferences" styleName="{style.preferences}" text="{constants.preferences}"></g:Label>
<g:Label ui:field="deconnecter" styleName="{style.deconnecter}" text="{constants.seDeconnecter}" />
</g:HTMLPanel>
</g:HTMLPanel>
<g:HTMLPanel ui:field="zoneFormulaire">
<g:HTMLPanel styleName="{style.colonneGauche}">
<g:Label text="{constants.login}" />
<g:TextBox ui:field="login" styleName="{style.login}" />
<g:Label text="{constants.motdepasse}" />
<g:PasswordTextBox ui:field="motdepasse" styleName="{style.motdepasse}"></g:PasswordTextBox>
<g:Button ui:field="boutonOK" styleName="{style.boutonOK}">OK</g:Button>
<g:Label ui:field="erreurIdentification" styleName="{style.erreur}"></g:Label>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.colonneDroite}">
<ui:msg key="texteConnexion">Texte de connexion</ui:msg>
</g:HTMLPanel>
</g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulaires/identification/FormulaireIdentificationPresenteur.java
New file
0,0 → 1,198
package org.tela_botanica.del.client.composants.formulaires.identification;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlayDefilanteVue;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlaySimplePresenteur;
import org.tela_botanica.del.client.composants.preferences.PreferencesPresenteur;
import org.tela_botanica.del.client.composants.preferences.PreferencesVue;
import org.tela_botanica.del.client.modeles.Utilisateur;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.changementEtatUtilisateur.EvenementChangementEtatUtilisateur;
import org.tela_botanica.del.client.navigation.evenement.changementPreferences.EvenementChangementPreferences;
import org.tela_botanica.del.client.navigation.evenement.changementPreferences.GestionnaireEvenementChangementPreferences;
import org.tela_botanica.del.client.services.rest.PreferencesServiceConcret;
import org.tela_botanica.del.client.services.rest.UtilisateurService;
import org.tela_botanica.del.client.services.rest.async.UtilisateurCallback;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasKeyPressHandlers;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class FormulaireIdentificationPresenteur {
FenetreOverlaySimplePresenteur fenetreModalePresenteur = null;
 
public abstract interface Vue extends IsWidget {
public void ajouterVue(HasWidgets composite);
 
public HasClickHandlers getSeConnecter();
 
public HasClickHandlers getSeDeconnecter();
 
public void basculerAffichageFormulaire(boolean estConnecte);
 
public void basculerModeConnecte(Utilisateur utilisateur);
 
public HasClickHandlers getBoutonOK();
 
public HasText getLogin();
 
public HasText getMotdepasse();
 
public void afficherErreur();
 
public void masquerErreur();
 
public void viderFormulaire();
 
public void setErreur(String idTexte);
 
public String getErreur();
 
public HasKeyPressHandlers getLoginHasKeyPressHandler();
 
public HasKeyPressHandlers getMotdepasseHasKeyPressHandler();
 
HasClickHandlers getZonePreferencesClickHandler();
}
 
private Vue vue;
private Utilisateur utilisateur;
private UtilisateurService utilisateurService;
 
public FormulaireIdentificationPresenteur(Vue vue, UtilisateurService utilisateurService) {
this.vue = vue;
this.utilisateurService = utilisateurService;
utilisateurService.obtenirUtilisateur(new UtilisateurCallback() {
 
@Override
public void surRetour(Utilisateur objetRetour) {
utilisateur = objetRetour;
CacheClient.getInstance().setUtilisateur(utilisateur);
rafraichir();
}
});
gererEvenements();
}
 
public void rafraichir() {
utilisateur = CacheClient.getInstance().getUtilisateur();
vue.basculerModeConnecte(this.utilisateur);
BusEvenementiel.getInstance().fireEvent(new EvenementChangementEtatUtilisateur(utilisateur));
}
 
public void gererEvenements() {
vue.getBoutonOK().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
surTentativeLogin();
}
});
 
vue.getSeDeconnecter().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
deconnecterUtilisateur();
}
});
 
vue.getLoginHasKeyPressHandler().addKeyPressHandler(creerGestionnaireEvenementToucheEntree());
vue.getMotdepasseHasKeyPressHandler().addKeyPressHandler(creerGestionnaireEvenementToucheEntree());
vue.getZonePreferencesClickHandler().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if(utilisateur.estIdentifie()) {
PreferencesPresenteur preferencesPresenteur = new PreferencesPresenteur(new PreferencesVue(), new PreferencesServiceConcret());
fenetreModalePresenteur = new FenetreOverlaySimplePresenteur(new FenetreOverlayDefilanteVue());
fenetreModalePresenteur.ouvrirFenetreModale(preferencesPresenteur);
}
}
});
BusEvenementiel.getInstance().addHandler(EvenementChangementPreferences.TYPE, new GestionnaireEvenementChangementPreferences() {
@Override
public void onChangementPreferences(EvenementChangementPreferences event) {
if(fenetreModalePresenteur != null && fenetreModalePresenteur.fenetreModaleEstOuverte()) {
fenetreModalePresenteur.fermerFenetreModale();
}
}
});
}
 
private void surTentativeLogin() {
String login = vue.getLogin().getText();
String motdepasse = vue.getMotdepasse().getText();
 
if (login.equals("") || motdepasse.equals("")) {
gererErreur("saisirLogin");
} else {
connecterUtilisateur(login, motdepasse);
}
}
 
public KeyPressHandler creerGestionnaireEvenementToucheEntree() {
return new KeyPressHandler() {
public void onKeyPress(KeyPressEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
surTentativeLogin();
}
}
};
}
 
public void gererErreur(String erreur) {
vue.setErreur(erreur);
vue.afficherErreur();
}
 
public void connecterUtilisateur(String login, final String motdepasse) {
 
utilisateurService.connecterUtilisateur(login, motdepasse, new UtilisateurCallback() {
 
public void surErreur(String message) {
vue.setErreur("identificationRefus");
vue.afficherErreur();
}
 
@Override
public void surRetour(Utilisateur objetRetour) {
utilisateur = objetRetour;
CacheClient.getInstance().setUtilisateur(utilisateur);
if (utilisateur.estIdentifie()) {
vue.masquerErreur();
rafraichir();
vue.viderFormulaire();
}
}
});
}
 
public void deconnecterUtilisateur() {
utilisateurService.deconnecterUtilisateur(new UtilisateurCallback() {
 
public void surErreur(String message) {
vue.setErreur("identificationRefus");
vue.afficherErreur();
}
 
@Override
public void surRetour(Utilisateur objetRetour) {
utilisateur = objetRetour;
CacheClient.getInstance().setUtilisateur(utilisateur);
rafraichir();
}
});
}
 
public void go(HasWidgets composite) {
vue.ajouterVue(composite);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulaires/identification/FormulaireIdentificationVue.java
New file
0,0 → 1,148
package org.tela_botanica.del.client.composants.formulaires.identification;
 
import org.tela_botanica.del.client.i18n.I18n;
import org.tela_botanica.del.client.modeles.Utilisateur;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasKeyPressHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
 
public class FormulaireIdentificationVue extends Composite implements FormulaireIdentificationPresenteur.Vue {
interface Binder extends UiBinder<Widget, FormulaireIdentificationVue> {
}
private static Binder uiBinder = GWT.create(Binder.class);
@UiField
Label titreSeConnecter, titreEstIdentifie, deconnecter, email, erreurIdentification, preferences;
@UiField Panel zoneFormulaire;
@UiField Button boutonOK;
@UiField TextBox login, motdepasse;
public FormulaireIdentificationVue() {
initWidget(uiBinder.createAndBindUi(this));
titreSeConnecter.setVisible(false);
erreurIdentification.setVisible(false);
}
@Override
public void ajouterVue(HasWidgets composite) {
composite.add(this.asWidget());
}
 
@Override
public HasClickHandlers getSeConnecter() {
return titreSeConnecter;
}
 
@Override
public void basculerAffichageFormulaire(boolean estConnecte) {
zoneFormulaire.setVisible(!estConnecte);
}
 
@Override
public void basculerModeConnecte(Utilisateur utilisateur) {
//Dans le mode non-connecté, on veut :
// - un bandeau vert avec ecrit Identifiez-vous
// - le formulaire courriel/password/texte et btn ok
// dans le mode connecté on veut :
// - un bandeau vert avec écrit Bienvenue
// - l'email de l'utilisateur
// - un btn déconnecter
// - un btn préférences
boolean estConnecte = utilisateur.estIdentifie();
// mode non-connecté
titreSeConnecter.setVisible(!estConnecte);
titreEstIdentifie.setVisible(estConnecte);
deconnecter.setVisible(estConnecte);
preferences.setVisible(estConnecte);
email.setText(utilisateur.getNomPrenomFormate());
email.setVisible(estConnecte);
basculerAffichageFormulaire(estConnecte);
}
 
@Override
public HasClickHandlers getBoutonOK() {
return boutonOK;
}
 
@Override
public TextBox getLogin() {
return login;
}
 
@Override
public TextBox getMotdepasse() {
return motdepasse;
}
 
@Override
public HasClickHandlers getSeDeconnecter() {
return deconnecter;
}
@Override
public void afficherErreur() {
erreurIdentification.setVisible(true);
}
@Override
public void masquerErreur() {
erreurIdentification.setVisible(false);
}
@Override
public void viderFormulaire() {
login.setText("");
motdepasse.setText("");
}
@Override
public void setErreur(String idTexte) {
String texte = "";
if (idTexte.equals("saisirLogin")) {
texte = I18n.getMessages().saisirLogin();
} else {
texte = I18n.getMessages().identificationRefus();
}
erreurIdentification.setText(texte);
}
public String getErreur() {
return erreurIdentification.getText();
}
 
@Override
public HasKeyPressHandlers getLoginHasKeyPressHandler() {
return login;
}
 
@Override
public HasKeyPressHandlers getMotdepasseHasKeyPressHandler() {
return motdepasse;
}
@Override
public HasClickHandlers getZonePreferencesClickHandler() {
return preferences;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulaires/identification/identification.css
New file
0,0 → 1,86
.zoneIdentification {
font-size:11px;
padding:30px 15px 22px 15px;
height:70px;
background: none repeat scroll 0 0 white;
border: 1px solid #99C242;
border-radius: 0 10px 10px 10px;
text-align: left;
text-decoration: none;
width: 350px;
}
 
.connecter {
background-color: #99C242;
border-radius: 0 10px 0 0;
color: white;
font-size: 12px;
padding: 5px 5px 5px 9px;
text-align: left;
text-transform: uppercase;
width: 347px;
position:absolute;
margin-left:-15px;
margin-top:-30px;
padding-right:25px
}
 
.deconnecter, .preferences {
text-decoration: underline;
color: blue;
cursor: pointer
}
 
.email, .preferences {
padding-right: 10px
}
 
.zoneFormulaire {
}
 
.login {
width:150px;
font-size:11px;
}
 
.motdepasse {
width:150px;
font-size:11px;
}
 
.erreur {
color: red;
position:absolute;
margin-top:13px;
}
 
.boutonOK {
font-size:11px;
}
 
.colonneGauche {
float:left;
padding-bottom:15px;
margin-right:5px;
width:210px;
}
 
.colonneDroite {
float:left;
margin-right:5px;
padding-bottom:15px;
}
 
.zoneUtilisateur {
text-align:center;
}
 
.infoConnexion {
text-align:center;
font-size:15px;
}
 
.infoConnexion>div:first-child {
margin-top:10px;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulaires/formulaireproposition/formulaireProposition.css
New file
0,0 → 1,71
.formulaireProposition {
z-index: 1500;
padding: 30px;
padding-right: 21px;
padding-top: 20px;
background: white;
width: 370px;
margin: 0 auto;
margin-top: 75px;
padding-bottom:50px;
}
 
.boutonProposer:hover {
background-color: #AAA
}
 
.colonneGauche,.colonneDroite {
width: 300px;
}
 
.colonneGauche {
padding-right: 30px
}
 
.colonneGauche select {
width: 100%
}
 
.colonneGauche input {
width: 95%
}
 
.commentaire {
width: 260px;
height: 100px;
}
 
.propositionTaxon {
width: 100%;
height: 30px;
}
 
.boutonProposer {
border: solid 1px #AAA;
cursor: pointer;
float: left;
margin-top: 10px;
margin-bottom: 5px;
margin-right: 5px;
float: right;
background: url(./img/add.png) no-repeat 5px 7px #DDD;
padding: 5px;
padding-left: 25px;
cursor: pointer
}
 
.zoneNom {
width:30%;
float:left;
margin-right:5px;
}
 
.zonePrenom {
width:30%;
float:left;
}
 
.zoneEmail {
clear:left;
padding-top:5px;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulaires/formulaireproposition/FormulairePropositionVue.ui.xml
New file
0,0 → 1,42
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:vues="urn:import:org.tela_botanica.del.client.composants.forum">
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary"/>
<ui:style src="formulaireProposition.css" />
<g:HTMLPanel styleName="{style.formulaireProposition}">
<g:Label text="{constants.proposerSaDetermination}" styleName="titre"/>
<g:HTML><br /></g:HTML>
<g:HTMLPanel styleName="{style.colonneGauche}">
<g:Label ui:field="labelnomPrenom" text="{constants.vous}" styleName="sousTitre"/>
<g:HTMLPanel styleName="{style.zoneNom}">
<g:Label text="{constants.nom}" styleName="petit" />
<g:TextBox ui:field="nom"/>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.zonePrenom}">
<g:Label text="{constants.prenom}" styleName="petit" />
<g:TextBox ui:field="prenom"/>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.zoneEmail}">
<g:Label text="Votre adresse email : " styleName="petit" />
<g:TextBox ui:field="courriel" />
</g:HTMLPanel>
<g:HTML><br /></g:HTML>
<g:Label text="{constants.choisirUnTaxon}" styleName="sousTitre"/>
<g:Label text="{constants.referentiel}" styleName="petit"/>
<g:ListBox ui:field="referentiel" />
<g:HTML HTML="{constants.infoTaxon}" styleName="petit"/>
<g:LayoutPanel ui:field="propositionTaxon" styleName="{style.propositionTaxon}" />
<g:HTML><br /></g:HTML>
<g:Label text="{constants.commentaire}" styleName="sousTitre"/>
<g:TextArea ui:field="commentaires" styleName="{style.commentaire}" />
<g:Button text="{constants.boutonProposer}" ui:field="boutonValidationProposition" styleName="{style.boutonProposer} arrondi"/>
</g:HTMLPanel>
</g:HTMLPanel>
 
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulaires/formulaireproposition/FormulairePropositionPresenteur.java
New file
0,0 → 1,262
package org.tela_botanica.del.client.composants.formulaires.formulaireproposition;
 
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.formulaires.autocompletion.AutoCompletionComboBoxPresenteur;
import org.tela_botanica.del.client.composants.formulaires.autocompletion.AutoCompletionComboBoxVue;
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.composants.validation.ValidateurChampTexteNonNul;
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.modeles.Contributeur;
import org.tela_botanica.del.client.modeles.InterventionForum;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.modeles.Utilisateur;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.ajoutdetermination.EvenementAjoutDetermination;
import org.tela_botanica.del.client.services.ReferentielService;
import org.tela_botanica.del.client.services.rest.PropositionDeterminationService;
import org.tela_botanica.del.client.services.rest.async.PropositionDeterminationCallBack;
import org.tela_botanica.del.client.utils.UtilitairesAutoCompletionService;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.http.client.Response;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class FormulairePropositionPresenteur extends Presenteur {
 
public interface Vue extends IsWidget {
public HasText getObjetNom();
 
public HasText getObjetPrenom();
 
public HasWidgets getPropositionTaxon();
 
public HasText getCommentaires();
 
public HasClickHandlers getBoutonValidationProposition();
 
public void afficherNomPrenomEtDesactiver(String nom, String prenom);
 
public String getCourriel();
 
public void afficherEmailEtDesactiver(String courriel);
 
public String getNom();
 
public String getPrenom();
 
public void afficherStyleErreurNom(String styleErreur);
 
public void supprimerStyleErreurNom(String styleErreur);
 
public void afficherStyleErreurPrenom(String styleErreur);
 
public void supprimerStyleErreurPrenom(String styleErreur);
public void afficherPropositionDejaEffectuée(String taxon);
 
public HasText getObjetCourriel();
public void setReferentiel(String referentiel);
public String getReferentiel();
 
public void afficherStyleErreurCourriel(String styleErreur);
 
void supprimerStyleErreurCourriel(String styleErreur);
 
void remplirListeReferentiels(Map<String, String> listeReferentiels);
}
 
private Vue vue;
private Config config;
private AutoCompletionComboBoxPresenteur autoCompletionNomTaxonsPresenteur;
private PropositionDeterminationService propositionDeterminationService;
private Map<String, String> cacheTaxons = new HashMap<String, String>();
 
public FormulairePropositionPresenteur(Vue vue, PropositionDeterminationService propositionDeterminationService) {
this.vue = vue;
this.propositionDeterminationService=propositionDeterminationService;
config = new Config();
creerCompletionTaxons();
remplirAvecInfosUtilisateur();
}
 
private void remplirAvecInfosUtilisateur() {
Utilisateur utilisateur = CacheClient.getInstance().getUtilisateur();
if (utilisateur.estIdentifie()) {
vue.afficherNomPrenomEtDesactiver(utilisateur.getNom(), utilisateur.getPrenom());
vue.afficherEmailEtDesactiver(utilisateur.getCourriel());
}
}
 
private void creerCompletionTaxons() {
String url = this.config.getServiceBaseUrl() + "nomstaxons";
vue.remplirListeReferentiels(ReferentielService.getReferentiels());
final String referentiel = CacheClient.getInstance().getObservationCourante().getReferentiel();
vue.setReferentiel(referentiel.substring(0, 5));
autoCompletionNomTaxonsPresenteur = new AutoCompletionComboBoxPresenteur(new AutoCompletionComboBoxVue(), url) {
protected String effectuerPreTraitementChaineRequete(String requete) {
// si aucun référentiel selectionné, pas de requete
if(vue.getReferentiel() != null && !vue.getReferentiel().equals("") && !vue.getReferentiel().equals("tous")) {
requete = "?masque.nom=" + requete + "&masque.referentiel=" + vue.getReferentiel().substring(0, 5);
return requete;
} else {
return null;
}
}
 
@Override
protected String[] parserResultatRequete(Response response) {
cacheTaxons = UtilitairesAutoCompletionService.extraireTaxonsNumNomsResultatRetourSimple(response);
return UtilitairesAutoCompletionService.parserResultatRetourSimple(response);
}
};
}
 
public void go(HasWidgets composite) {
autoCompletionNomTaxonsPresenteur.go(vue.getPropositionTaxon());
composite.add(vue.asWidget());
gererEvenements();
}
 
protected void gererEvenements() {
vue.getBoutonValidationProposition().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
 
if (!validerSaisieProposition()) {
return;
} else {
final PropositionDetermination propositionAjoutee = collecterValeursSaisieProposition();
if(verifierPropositionDejaAjoutee(propositionAjoutee)){
BusEvenementiel.getInstance().fireEvent(new EvenementAjoutDetermination(propositionAjoutee));
vue.afficherPropositionDejaEffectuée(propositionAjoutee.getEspece());
return;
}
 
propositionDeterminationService.ajouterProposition(propositionAjoutee, new PropositionDeterminationCallBack() {
 
@Override
public void surRetour(String idNouvelleProposition) {
propositionAjoutee.setId(idNouvelleProposition);
CacheClient.getInstance().getObservationCourante().ajouterPropositionDetermination(propositionAjoutee);
EvenementAjoutDetermination evenementAjoutDetermination = new EvenementAjoutDetermination(propositionAjoutee);
BusEvenementiel.getInstance().fireEvent(evenementAjoutDetermination);
}
 
});
}
}
});
}
 
private boolean verifierPropositionDejaAjoutee(PropositionDetermination propositionDetermination){
for(InterventionForum interventionForum: CacheClient.getInstance().getObservationCourante().getInterventionsForum()){
if(interventionForum instanceof PropositionDetermination){
if(((PropositionDetermination)interventionForum).getEspece().equals(propositionDetermination.getEspece())){
return true;
}
}
}
return false;
}
private boolean validerSaisieProposition() {
 
ValidateurChampTexteNonNul validateurNom = new ValidateurChampTexteNonNul(vue.getObjetNom()) {
@Override
public void afficherStyleErreur(String styleErreur) {
vue.afficherStyleErreurNom(styleErreur);
}
 
@Override
public void supprimerStyleErreur(String styleErreur) {
vue.supprimerStyleErreurNom(styleErreur);
}
};
 
ValidateurChampTexteNonNul validateurPrenom = new ValidateurChampTexteNonNul(vue.getObjetPrenom()) {
@Override
public void afficherStyleErreur(String styleErreur) {
vue.afficherStyleErreurPrenom(styleErreur);
}
 
@Override
public void supprimerStyleErreur(String styleErreur) {
vue.supprimerStyleErreurPrenom(styleErreur);
}
};
ValidateurChampTexteNonNul validateurCourriel = new ValidateurChampTexteNonNul(vue.getObjetCourriel()) {
@Override
public void afficherStyleErreur(String styleErreur) {
vue.afficherStyleErreurCourriel(styleErreur);
}
 
@Override
public void supprimerStyleErreur(String styleErreur) {
vue.supprimerStyleErreurCourriel(styleErreur);
}
};
 
ValidateurChampTexteNonNul validateurTaxon = new ValidateurChampTexteNonNul(autoCompletionNomTaxonsPresenteur.getAutoCompletionComboBoxVue().getSuggestBox()) {
@Override
public void afficherStyleErreur(String styleErreur) {
autoCompletionNomTaxonsPresenteur.afficherStyleErreur(styleErreur);
}
 
@Override
public void supprimerStyleErreur(String styleErreur) {
autoCompletionNomTaxonsPresenteur.supprimerStyleErreur(styleErreur);
}
};
 
boolean nomSaisi = validateurNom.valider();
boolean prenomSaisi = validateurPrenom.valider();
boolean courrielSaisi = validateurCourriel.valider();
boolean taxonSaisi = validateurTaxon.valider();
 
return nomSaisi && prenomSaisi && courrielSaisi && taxonSaisi;
}
 
private PropositionDetermination collecterValeursSaisieProposition() {
PropositionDetermination propositionAjoutee = new PropositionDetermination(CacheClient.getInstance().getObservationCourante());
propositionAjoutee.setId(CacheClient.getInstance().getObservationCourante().getId());
 
String idUtilisateur = null;
if (CacheClient.getInstance().getUtilisateur().estIdentifie()) {
idUtilisateur = CacheClient.getInstance().getUtilisateur().getId();
}
 
Contributeur contributeur = new Contributeur(idUtilisateur, vue.getNom(), vue.getPrenom(), vue.getCourriel());
propositionAjoutee.setContributeur(contributeur);
propositionAjoutee.setDate(new Date());
String nomTaxon = autoCompletionNomTaxonsPresenteur.getValeur();
propositionAjoutee.setEspece(nomTaxon);
if(cacheTaxons.containsKey(nomTaxon)) {
propositionAjoutee.setNumNomenclatural(cacheTaxons.get(nomTaxon));
}
if(vue.getReferentiel() != "tous") {
propositionAjoutee.setReferentiel(vue.getReferentiel());
}
if (vue.getCommentaires().getText() != "") {
String contenuCommentaire = vue.getCommentaires().getText();
propositionAjoutee.setCommentaire(contenuCommentaire);
}
 
return propositionAjoutee;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulaires/formulaireproposition/FormulairePropositionVue.java
New file
0,0 → 1,168
package org.tela_botanica.del.client.composants.formulaires.formulaireproposition;
 
import java.util.Iterator;
import java.util.Map;
 
import org.tela_botanica.del.client.i18n.I18n;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
 
public class FormulairePropositionVue extends Composite implements FormulairePropositionPresenteur.Vue {
 
@UiField
public TextBox nom, prenom, courriel;
 
@UiField
public LayoutPanel propositionTaxon;
 
@UiField
public TextArea commentaires;
 
@UiField
public Button boutonValidationProposition;
@UiField
public Label labelnomPrenom;
@UiField
ListBox referentiel;
 
interface FormulairePropositionUIiBinder extends UiBinder<Widget, FormulairePropositionVue> {
};
 
FormulairePropositionUIiBinder uiBinder = GWT.create(FormulairePropositionUIiBinder.class);
 
public FormulairePropositionVue() {
initWidget(uiBinder.createAndBindUi(this));
}
 
 
@Override
public LayoutPanel getPropositionTaxon() {
return propositionTaxon;
}
 
@Override
public TextArea getCommentaires() {
return commentaires;
}
 
@Override
public Button getBoutonValidationProposition() {
return boutonValidationProposition;
}
 
@Override
public void afficherStyleErreurNom(String styleErreur) {
nom.addStyleName(styleErreur);
}
 
@Override
public void supprimerStyleErreurNom(String styleErreur) {
nom.removeStyleName(styleErreur);
}
@Override
public void afficherStyleErreurPrenom(String styleErreur) {
prenom.addStyleName(styleErreur);
}
 
@Override
public void supprimerStyleErreurPrenom(String styleErreur) {
prenom.removeStyleName(styleErreur);
}
@Override
public void afficherNomPrenomEtDesactiver(String nom, String prenom) {
this.nom.setText(nom);
this.prenom.setText(prenom);
this.nom.setEnabled(false);
this.prenom.setEnabled(false);
}
@Override
public void afficherEmailEtDesactiver(String courriel) {
this.courriel.setText(courriel);
this.courriel.setEnabled(false);
}
public void afficherPropositionDejaEffectuée(String taxon)
{
Window.alert(I18n.getMessages().propositionDejaEffectuee(taxon));
}
 
@Override
public String getCourriel() {
return courriel.getText();
}
 
@Override
public String getNom() {
return nom.getText();
}
 
@Override
public String getPrenom() {
return prenom.getText();
}
 
 
@Override
public HasText getObjetNom() {
return this.nom;
}
@Override
public HasText getObjetPrenom() {
return this.prenom;
}
 
 
@Override
public HasText getObjetCourriel() {
return this.courriel;
}
 
@Override
public void afficherStyleErreurCourriel(String styleErreur) {
courriel.setStyleName(styleErreur);
}
@Override
public void supprimerStyleErreurCourriel(String styleErreur) {
courriel.removeStyleName(styleErreur);
}
 
@Override
public void remplirListeReferentiels(Map<String, String> listeReferentiels) {
for (Iterator<String> iterator = listeReferentiels.keySet().iterator(); iterator.hasNext();) {
String codeRef = iterator.next();
referentiel.addItem(listeReferentiels.get(codeRef), codeRef);
}
}
@Override
public void setReferentiel(String codeReferentiel) {
for(int i = 0; i < referentiel.getItemCount(); i++) {
if(referentiel.getValue(i).equals(codeReferentiel)) {
referentiel.setSelectedIndex(i);
}
}
}
 
@Override
public String getReferentiel() {
return referentiel.getValue(referentiel.getSelectedIndex());
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulaires/autocompletion/AutoCompletionComboBoxPresenteur.java
New file
0,0 → 1,191
package org.tela_botanica.del.client.composants.formulaires.autocompletion;
 
import com.google.gwt.event.dom.client.HasKeyPressHandlers;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.logical.shared.HasSelectionHandlers;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.SuggestOracle;
import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
 
public abstract class AutoCompletionComboBoxPresenteur {
public interface Vue extends IsWidget {
public void ajouterVue(HasWidgets composite);
public HasKeyPressHandlers getSuggestBoxHasKeyPressHandlers();
public String getValeur();
public void remplirListe(String[] suggestions);
public void afficherSuggestions(SuggestOracle.Request request,SuggestOracle.Callback response);
public void afficherListeDeroulante();
public void nettoyer();
public void setValeur(String valeur);
public HasSelectionHandlers<Suggestion> getSuggestBoxHasSelectionChangeHandlers();
public HasText getSuggestBox();
public void afficherStyleErreur(String styleErreur);
public void supprimerStyleErreur(String styleErreur);
}
private Vue autoCompletionComboBoxVue;
SuggestOracle.Request requeteOracle;
SuggestOracle.Callback callBackOracle;
Timer suggestionTimer = null;
int tempsAvantRequete = 500;
String urlRequete = "";
public AutoCompletionComboBoxPresenteur(Vue vue, String urlRequete) {
this.autoCompletionComboBoxVue = vue;
this.urlRequete = urlRequete;
gererEvenements();
}
public void go(HasWidgets composite) {
autoCompletionComboBoxVue.ajouterVue(composite);
}
public void gererEvenements() {
autoCompletionComboBoxVue.getSuggestBoxHasKeyPressHandlers().addKeyPressHandler(new KeyPressHandler() {
public void onKeyPress(KeyPressEvent event) {
if(event.getUnicodeCharCode() != 0) {
gererTimer();
}
}
});
requeteOracle = new SuggestOracle.Request();
callBackOracle = new SuggestOracle.Callback() {
 
public void onSuggestionsReady(SuggestOracle.Request request, SuggestOracle.Response response) {
autoCompletionComboBoxVue.afficherListeDeroulante();
}
};
autoCompletionComboBoxVue.getSuggestBoxHasSelectionChangeHandlers().addSelectionHandler(new SelectionHandler<SuggestOracle.Suggestion>(){
@Override
public void onSelection(SelectionEvent<Suggestion> event) {
surSelectionSuggestion(event.getSelectedItem().getReplacementString());
}
});
}
public void gererTimer() {
if(suggestionTimer == null) {
suggestionTimer = new Timer() {
public void run() {
requeteSuggestions();
}
};
suggestionTimer.schedule(tempsAvantRequete);
} else {
suggestionTimer.schedule(tempsAvantRequete);
}
}
public void setTempsAvantRequete(int temps) {
tempsAvantRequete = temps;
}
public int getTempsAvantRequete(int temps) {
return tempsAvantRequete;
}
public String getValeur() {
return autoCompletionComboBoxVue.getValeur();
}
public void setValeur(String taxon) {
autoCompletionComboBoxVue.setValeur(taxon);
}
public void nettoyer() {
autoCompletionComboBoxVue.nettoyer();
}
public void requeteSuggestions() {
final String requete = URL.encodeQueryString(autoCompletionComboBoxVue.getValeur());
String requeteAjax = effectuerPreTraitementChaineRequete(requete);
// ceci permet au composant qui utilise l'autocomplétion
// d'annuler une requete
if(requeteAjax == null) {
return;
}
String urlProxy = urlRequete+requeteAjax;
RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, urlProxy) ;
try {
rb.sendRequest(null, new RequestCallback() {
public void onError(final Request request, final Throwable exception) {
// TODO Auto-generated method stub
}
 
public void onResponseReceived(final Request request,
final Response response) {
surReponseRequete(requete, response);
}
}) ;
 
} catch (RequestException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void surReponseRequete(String requete, Response response) {
String[] valeurs = parserResultatRequete(response);
autoCompletionComboBoxVue.remplirListe(valeurs);
requeteOracle.setQuery(requete);
autoCompletionComboBoxVue.afficherSuggestions(requeteOracle, callBackOracle);
}
protected void surSelectionSuggestion(String suggestion) {
return;
}
/**
* Permet d'intervenir sur la chaine tapée par l'utilisateur avant que celle-ci ne soit passée
* à la requête asynchrone pour pouvoir la formater (pour mettre en minuscule, séparer des termes)
* par défaut renvoie la chaine telle quelle, à surcharger au besoin
* @param String requete chaine de recherche contenant ce que l'utilisateur à tapé
* @return String une chaine transformée
*/
protected String effectuerPreTraitementChaineRequete(String requete) {
return requete;
}
/**
* Parse les résultats de la requete afin de pouvoir les utiliser à implémenter par le
* composants qui crée la combobox selon le contexte et le web service appelé.
* @param Response la réponse à la requête asynchrone
* @return String[] le tableau des suggestions qui sera affiché dans la combobox
*/
protected abstract String[] parserResultatRequete(Response response);
 
public Vue getAutoCompletionComboBoxVue() {
return autoCompletionComboBoxVue;
}
public void afficherStyleErreur(String styleErreur) {
autoCompletionComboBoxVue.afficherStyleErreur(styleErreur);
}
public void supprimerStyleErreur(String styleErreur) {
autoCompletionComboBoxVue.supprimerStyleErreur(styleErreur);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulaires/autocompletion/AutoCompletionComboBoxVue.java
New file
0,0 → 1,85
package org.tela_botanica.del.client.composants.formulaires.autocompletion;
 
import com.google.gwt.event.dom.client.HasKeyPressHandlers;
import com.google.gwt.event.logical.shared.HasSelectionHandlers;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.SuggestOracle;
import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
 
public class AutoCompletionComboBoxVue extends LayoutPanel implements AutoCompletionComboBoxPresenteur.Vue {
 
MultiWordSuggestOracle msu = new MultiWordSuggestOracle();
SuggestBox suggestions = new SuggestBox(msu);
 
public AutoCompletionComboBoxVue() {
add(suggestions);
//TODO: voir avec greg si la taille doit être définie ici
setHeight("25px");
setWidth("100%");
}
@Override
public SuggestBox getSuggestBox() {
return suggestions;
}
public void remplirListe(String[] listePropositions) {
msu.clear();
for (int i = 0; i < listePropositions.length; i++) {
msu.add(listePropositions[i]);
}
}
@Override
public void afficherSuggestions(SuggestOracle.Request requeteOracle, SuggestOracle.Callback callBackOracle) {
msu.requestSuggestions(requeteOracle, callBackOracle);
}
@Override
public void afficherListeDeroulante() {
suggestions.showSuggestionList();
}
public void nettoyer() {
suggestions.setText("");
}
public void setValeur(String taxon) {
suggestions.setValue(taxon);
}
 
@Override
public HasKeyPressHandlers getSuggestBoxHasKeyPressHandlers() {
return suggestions;
}
@Override
public HasSelectionHandlers<Suggestion> getSuggestBoxHasSelectionChangeHandlers() {
return suggestions;
}
 
@Override
public String getValeur() {
return suggestions.getText();
}
 
@Override
public void ajouterVue(HasWidgets composite) {
composite.add(this.asWidget());
}
 
@Override
public void afficherStyleErreur(String styleErreur) {
suggestions.addStyleName(styleErreur);
}
 
@Override
public void supprimerStyleErreur(String styleErreur) {
suggestions.removeStyleName(styleErreur);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/forum/ArbreCommentaireVue.java
New file
0,0 → 1,50
package org.tela_botanica.del.client.composants.forum;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
 
import org.tela_botanica.del.client.modeles.Commentaire;
import org.tela_botanica.del.client.modeles.InterventionForum;
 
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.TreeItem;
 
public class ArbreCommentaireVue extends Tree implements ArbreCommentairePresenteur.Vue {
 
public ArbreCommentaireVue() {
super();
}
 
public void creerArbreCommentaire(InterventionForum possesseurDeCommentaires) {
TreeItem racineArbreCommentaires = new TreeItem();
addItem(racineArbreCommentaires);
 
if (possesseurDeCommentaires instanceof Commentaire) {
List<Commentaire> commentaires = new ArrayList<Commentaire>();
commentaires.add((Commentaire) possesseurDeCommentaires);
creerListeCommentaireRecursive(racineArbreCommentaires, commentaires);
} else {
creerListeCommentaireRecursive(racineArbreCommentaires, possesseurDeCommentaires.getListeCommentaires());
}
}
 
private void creerListeCommentaireRecursive(TreeItem parentTreeItem, List<Commentaire> commentaires) {
 
for (Commentaire commentaire : commentaires) {
String commentaireHTML = commentaire.getCommentaire();
HTML commentaireWidget = new HTML(commentaireHTML);
parentTreeItem.setWidget(commentaireWidget);
if (commentaire.getListeCommentaires().size() != 0) {
TreeItem childTreeItem = new TreeItem();
parentTreeItem.addItem(childTreeItem);
creerListeCommentaireRecursive(childTreeItem, commentaire.getListeCommentaires());
}
}
parentTreeItem.setState(true);
 
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/forum/forum.css
New file
0,0 → 1,0
.table {}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/forum/ForumVue.ui.xml
New file
0,0 → 1,11
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:vues="urn:import:org.tela_botanica.del.client.composants.forum">
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
<ui:style src="forum.css" />
<g:HTMLPanel>
<g:HTMLPanel ui:field='panneauInterventions' styleName="{style.table}" />
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/forum/ForumPresenteur.java
New file
0,0 → 1,114
package org.tela_botanica.del.client.composants.forum;
 
import java.util.Collections;
import java.util.List;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.forum.interventions.ForumInterventionPresenteur;
import org.tela_botanica.del.client.composants.forum.interventions.ForumInterventionVue;
import org.tela_botanica.del.client.modeles.Commentaire;
import org.tela_botanica.del.client.modeles.InterventionForum;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.ajoutcommentaire.EvenementAjoutCommentaire;
import org.tela_botanica.del.client.navigation.evenement.ajoutcommentaire.GestionnaireEvenementAjoutCommentaire;
import org.tela_botanica.del.client.navigation.evenement.ajoutdetermination.EvenementAjoutDetermination;
import org.tela_botanica.del.client.navigation.evenement.ajoutdetermination.GestionnaireEvenementAjoutDetermination;
import org.tela_botanica.del.client.navigation.evenement.suppressioncommentaire.EvenementSuppressionCommentaire;
import org.tela_botanica.del.client.navigation.evenement.suppressioncommentaire.GestionnaireEvenementSuppressionCommentaire;
import org.tela_botanica.del.client.navigation.evenement.suppressiondetermination.EvenementSuppressionDetermination;
import org.tela_botanica.del.client.navigation.evenement.suppressiondetermination.GestionnaireEvenementSuppressionDetermination;
import org.tela_botanica.del.client.services.rest.CommentaireServiceConcret;
import org.tela_botanica.del.client.services.rest.PropositionDeterminationServiceConcret;
import org.tela_botanica.del.client.utils.ComparateurPropositionDetermination;
 
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class ForumPresenteur {
 
public interface Vue extends IsWidget {
 
public abstract HasWidgets getPanneauInterventions();
 
public abstract void vider();
}
 
private Vue vue;
 
public ForumPresenteur(Vue vue) {
this.vue = vue;
}
 
public void go(HasWidgets composite) {
 
chargerDeterminations();
composite.add(vue.asWidget());
 
gererEvenements();
}
 
private void chargerDeterminations() {
 
vue.vider();
List<PropositionDetermination> interventions = CacheClient.getInstance().getObservationCourante().getPropositionDeterminations();
Collections.sort(interventions, new ComparateurPropositionDetermination());
for (InterventionForum interventionCourante : interventions) {
ForumInterventionPresenteur presenteur = new ForumInterventionPresenteur(new ForumInterventionVue(), interventionCourante, new CommentaireServiceConcret(), new PropositionDeterminationServiceConcret());
presenteur.go(vue.getPanneauInterventions());
ajouterCommentairesRecursivement(interventionCourante, presenteur);
}
List<Commentaire> commentaires = CacheClient.getInstance().getObservationCourante().getCommentairesForum();
for (InterventionForum interventionCourante : commentaires) {
ForumInterventionPresenteur presenteur = new ForumInterventionPresenteur(new ForumInterventionVue(), interventionCourante, new CommentaireServiceConcret(), new PropositionDeterminationServiceConcret());
presenteur.go(vue.getPanneauInterventions());
ajouterCommentairesRecursivement(interventionCourante, presenteur);
}
}
 
private void ajouterCommentairesRecursivement(InterventionForum interventionCourante, ForumInterventionPresenteur presenteur) {
List<Commentaire> fils = interventionCourante.getListeCommentaires();
for (InterventionForum interventionFils : fils) {
ForumInterventionPresenteur presenteurFils = new ForumInterventionPresenteur(new ForumInterventionVue(), interventionFils, new CommentaireServiceConcret(), new PropositionDeterminationServiceConcret());
ajouterCommentairesRecursivement(interventionFils, presenteurFils);
presenteur.ajouterEnfant(presenteurFils);
}
}
 
private void gererEvenements() {
BusEvenementiel.getInstance().addHandler(EvenementAjoutDetermination.TYPE, new GestionnaireEvenementAjoutDetermination() {
 
@Override
public void onAjoutDetermination(EvenementAjoutDetermination event) {
chargerDeterminations();
}
});
 
BusEvenementiel.getInstance().addHandler(EvenementAjoutCommentaire.TYPE, new GestionnaireEvenementAjoutCommentaire() {
 
@Override
public void onAjoutCommentaire(EvenementAjoutCommentaire event) {
chargerDeterminations();
}
});
 
BusEvenementiel.getInstance().addHandler(EvenementSuppressionDetermination.TYPE, new GestionnaireEvenementSuppressionDetermination() {
 
@Override
public void onSuppressionDetermination(EvenementSuppressionDetermination event) {
chargerDeterminations();
}
});
 
BusEvenementiel.getInstance().addHandler(EvenementSuppressionCommentaire.TYPE, new GestionnaireEvenementSuppressionCommentaire() {
 
@Override
public void onSuppressionCommentaire(EvenementSuppressionCommentaire event) {
chargerDeterminations();
}
});
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/forum/interventions/forumIntervention.css
New file
0,0 → 1,82
.nombreVotes {
width:15px;
height:16px;
padding-left: 10px;
float:right;
margin-left:10px;
}
 
.infobulle {
background: none repeat scroll 0 0 #1A5AC3;
color: white;
font-size: 11px;
height: 11px;
line-height: 0.9;
margin-left: 2px;
margin-top: 8px;
min-width: 7px;
padding: 1px;
position: absolute;
}
 
.proposition {
width:550px;
padding:10px;
background:#EEE;
margin-bottom:5px;
}
.nom {
margin-right:4px;
margin-top:1px;
}
.le {
margin-top:1px;
}
.date {
margin-left:3px;
margin-top:1px;
}
.determination {
clear:left;
float:left;
margin-top:1px;
margin-right:3px;
}
.nomtaxon {
float:left;
font-size:15px;
}
.voter div{
font-size:18px;
color:#333;
text-align:right;
margin-bottom:-3px;
}
.commentaire {
clear:left
}
.daccord {
clear:left;
margin-right:5px;
}
.repondre {
margin-top:3px;
float:left;
cursor:pointer;
margin-bottom:5px;
font-size:10px;
}
 
.suppression {
width:15px;
height:16px;
background:url('./img/cancel.png') no-repeat;
cursor: pointer;
margin-top:-15px;
margin-left:99%;
position:relative;
}
 
.labelVoter {
padding-left:9px;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/forum/interventions/ForumInterventionVue.ui.xml
New file
0,0 → 1,36
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:vues="urn:import:org.tela_botanica.del.client.composants.forum">
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
<ui:style src="forumIntervention.css" />
<g:FocusPanel ui:field="proposition" styleName="{style.proposition}">
<g:HTMLPanel>
<g:FocusPanel ui:field="conteneurLienSuppression" styleName="{style.suppression}">
<g:HTML ui:field="supprimer" />
</g:FocusPanel>
<g:HTMLPanel styleName="gauche nettoyage" ui:field="zoneDetermination">
<g:Label ui:field="nomTaxon" styleName="{style.nomtaxon}" />
</g:HTMLPanel>
<g:HTMLPanel styleName="droite" ui:field="zoneVoter">
<g:HorizontalPanel>
<g:Label text="Score " styleName="petit" />
<g:Label text="Voter" styleName="{style.labelVoter} petit" />
</g:HorizontalPanel>
<g:HTMLPanel ui:field="voter" styleName="{style.voter} gauche" />
<g:FocusPanel ui:field="conteneurPanneauVotes" styleName="{style.nombreVotes}">
<g:HTML ui:field="nbVotesHtml" styleName="{style.infobulle}"/>
</g:FocusPanel>
</g:HTMLPanel>
<g:Label text="Détermination proposée par " ui:field="labelDeterminationProposee" styleName="{style.determination} petit" />
<g:Label ui:field="nom" styleName="{style.nom} petit gauche" />
<g:Label text="le" styleName="{style.le} gauche petit"/>
<g:Label ui:field="date" styleName="{style.date} gauche petit"/>
<g:Label ui:field="commentaire" styleName="{style.commentaire}"/>
<g:Label text="Répondre" styleName="{style.repondre} labelLien" ui:field="repondre"/>
<g:HTML><br /></g:HTML>
<g:HTMLPanel ui:field="zoneEnfants"></g:HTMLPanel>
</g:HTMLPanel>
</g:FocusPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/forum/interventions/ForumInterventionPresenteur.java
New file
0,0 → 1,270
package org.tela_botanica.del.client.composants.forum.interventions;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlayDefilanteVue;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlaySimplePresenteur;
import org.tela_botanica.del.client.composants.formulaires.formulairecommentaire.FormulaireCommentairePresenteur;
import org.tela_botanica.del.client.composants.formulaires.formulairecommentaire.FormulaireCommentaireVue;
import org.tela_botanica.del.client.composants.forum.ArbreCommentairePresenteur;
import org.tela_botanica.del.client.composants.forum.ArbreCommentaireVue;
import org.tela_botanica.del.client.composants.votes.barrerepartition.BarreRepartitionVotePresenteur;
import org.tela_botanica.del.client.composants.votes.barrerepartition.BarreRepartitionVoteVue;
import org.tela_botanica.del.client.composants.votes.details.DetailListeVotesDeterminationPresenteur;
import org.tela_botanica.del.client.composants.votes.details.DetailListeVotesDeterminationVue;
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.i18n.I18n;
import org.tela_botanica.del.client.modeles.Commentaire;
import org.tela_botanica.del.client.modeles.InterventionForum;
import org.tela_botanica.del.client.modeles.MoyenneVote;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.ajoutcommentaire.EvenementAjoutCommentaire;
import org.tela_botanica.del.client.navigation.evenement.ajoutcommentaire.GestionnaireEvenementAjoutCommentaire;
import org.tela_botanica.del.client.navigation.evenement.ajoutdetermination.EvenementAjoutDetermination;
import org.tela_botanica.del.client.navigation.evenement.ajoutdetermination.GestionnaireEvenementAjoutDetermination;
import org.tela_botanica.del.client.navigation.evenement.suppressioncommentaire.EvenementSuppressionCommentaire;
import org.tela_botanica.del.client.navigation.evenement.suppressiondetermination.EvenementSuppressionDetermination;
import org.tela_botanica.del.client.services.CalculVoteDeterminationService;
import org.tela_botanica.del.client.services.rest.CommentaireService;
import org.tela_botanica.del.client.services.rest.CommentaireServiceConcret;
import org.tela_botanica.del.client.services.rest.PropositionDeterminationService;
import org.tela_botanica.del.client.services.rest.VoteDeterminationServiceConcret;
import org.tela_botanica.del.client.services.rest.async.SuppressionCommentaireCallback;
import org.tela_botanica.del.client.services.rest.async.SuppressionPropositionDeterminationCallback;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasMouseOutHandlers;
import com.google.gwt.event.dom.client.HasMouseOverHandlers;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class ForumInterventionPresenteur {
 
public interface Vue extends IsWidget {
void ajouterInterventionDetermination(PropositionDetermination determination, IsWidget barreRepartition, IsWidget arbreCommentaires);
void ajouterInterventionCommentaire(Commentaire commentaire, IsWidget arbreCommentaires);
HasClickHandlers getRepondre();
HasWidgets getEnfants();
HasClickHandlers getLienSuppression();
void afficherLienSuppression();
void cacherLienSuppression();
HasMouseOverHandlers getConteneurInterventionMouseOver();
HasMouseOutHandlers getConteneurInterventionMouseOut();
HasClickHandlers getEspece();
void ajouterLienEspece();
HasClickHandlers getAuteur();
void ajouterLienAuteur();
void cacherDeterminationProposee();
void ajouterLienVotes();
void masquerLienVotes();
void setNbVotes(int votes);
public HasClickHandlers getZoneNbVotes();
}
 
private Vue vue;
 
private InterventionForum interventionForum;
private CommentaireService commentaireService;
private PropositionDeterminationService propositionDeterminationService;
private FenetreOverlaySimplePresenteur overlay;
 
private int nbVotes;
public ForumInterventionPresenteur(Vue vue, InterventionForum interventionForum, CommentaireService commentaireService, PropositionDeterminationService propositionDeterminationService) {
this.vue = vue;
this.interventionForum = interventionForum;
this.commentaireService = commentaireService;
this.propositionDeterminationService = propositionDeterminationService;
}
 
public void go(HasWidgets composite) {
chargerIntervention();
composite.add(vue.asWidget());
gererEvenements();
}
public void ajouterEnfant(ForumInterventionPresenteur presenteur) {
presenteur.go(vue.getEnfants());
}
 
private void chargerIntervention() {
if (interventionForum instanceof PropositionDetermination) {
ajouterPropositionDetermination((PropositionDetermination) interventionForum);
} else if (interventionForum instanceof Commentaire) {
ajouterCommentaire((Commentaire) interventionForum);
vue.cacherDeterminationProposee();
}
}
 
private void ajouterPropositionDetermination(PropositionDetermination propositionDetermination) {
this.nbVotes = propositionDetermination.getVotesDeterminations().size();
BarreRepartitionVotePresenteur barreRepartitionVotePresenteur = new BarreRepartitionVotePresenteur(new BarreRepartitionVoteVue(), new VoteDeterminationServiceConcret());
barreRepartitionVotePresenteur.toggleNomEspece();
calculerEtAfficherVoteDetermination(barreRepartitionVotePresenteur, propositionDetermination);
ArbreCommentairePresenteur arbreCommentairePresenteur = new ArbreCommentairePresenteur(new ArbreCommentaireVue(), propositionDetermination);
vue.ajouterInterventionDetermination(propositionDetermination, barreRepartitionVotePresenteur.getBarreRepartitionVoteVue(), arbreCommentairePresenteur.getArbreCommentaireVue());
final String nn = propositionDetermination.getNumNomenclatural();
final String referentiel = propositionDetermination.getReferentiel();
// @TODO harmoniser les valeurs qui veulent dire "y en n'a pas" plutôt que !equals("kedal") :-/
if (nn != null && !nn.equals(0) && !nn.equals("0") && referentiel != null && !referentiel.equals("")) {
vue.ajouterLienEspece();
vue.getEspece().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Config config = new Config();
String efloreUrlFicheTpl = config.getUrl("efloreTaxon");
String efloreUrlFiche = efloreUrlFicheTpl.replaceAll("referentiel-nn-num_nom", referentiel.substring(0,5)+"-nn-"+nn);
Window.open(efloreUrlFiche, "Fiche eflore", null);
}
});
}
final String idContributeur = propositionDetermination.getContributeur().getId();
if (idContributeur != null && !idContributeur.equals("0")) {
vue.ajouterLienAuteur();
vue.getAuteur().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Config config = new Config();
Window.open(config.getUrl("annuaire") + idContributeur, "Consultation de l'annuaire", null);
}
});
}
}
 
private void ajouterCommentaire(Commentaire proposition) {
ArbreCommentairePresenteur arbreCommentairePresenteur = new ArbreCommentairePresenteur(new ArbreCommentaireVue(), proposition);
vue.ajouterInterventionCommentaire(proposition, arbreCommentairePresenteur.getArbreCommentaireVue());
}
 
private void calculerEtAfficherVoteDetermination(BarreRepartitionVotePresenteur barreRepartitionVotePresenteur, PropositionDetermination propositionDetermination) {
MoyenneVote votes = CalculVoteDeterminationService.calculerVoteDetermination(propositionDetermination);
barreRepartitionVotePresenteur.afficherVotes(votes);
}
private void gererEvenements() {
if (this.nbVotes > 0) {
vue.setNbVotes(this.nbVotes);
vue.ajouterLienVotes();
vue.getZoneNbVotes().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if (nbVotes > 0) {
FenetreOverlaySimplePresenteur fenetreOverlaySimplePresenteur = new FenetreOverlaySimplePresenteur(
new FenetreOverlayDefilanteVue());
DetailListeVotesDeterminationPresenteur detailListeVotesDeterminationPresenteur = new DetailListeVotesDeterminationPresenteur(
new DetailListeVotesDeterminationVue());
fenetreOverlaySimplePresenteur
.ouvrirFenetreModale(detailListeVotesDeterminationPresenteur);
detailListeVotesDeterminationPresenteur
.afficherVotes((PropositionDetermination) interventionForum);
}
}
});
} else {
vue.masquerLienVotes();
}
vue.getRepondre().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
FormulaireCommentairePresenteur commentairePresenteur = new FormulaireCommentairePresenteur(interventionForum, new CommentaireServiceConcret(), new FormulaireCommentaireVue());
overlay = new FenetreOverlaySimplePresenteur(new FenetreOverlayDefilanteVue());
overlay.ouvrirFenetreModale(commentairePresenteur);
}
});
vue.getConteneurInterventionMouseOver().addMouseOverHandler(new MouseOverHandler() {
@Override
public void onMouseOver(MouseOverEvent event) {
if(peutSupprimerIntervention()) {
vue.afficherLienSuppression();
}
}
});
vue.getConteneurInterventionMouseOut().addMouseOutHandler(new MouseOutHandler() {
@Override
public void onMouseOut(MouseOutEvent event) {
if(peutSupprimerIntervention()) {
vue.cacherLienSuppression();
}
}
});
 
vue.getLienSuppression().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
String message = "";
if (interventionForum instanceof PropositionDetermination) {
message = I18n.getVocabulary().confirmationSuppressionDetermination();
} else if (interventionForum instanceof Commentaire) {
message = I18n.getVocabulary().confirmationSuppressionCommentaire();
}
if(Window.confirm(message)) {
supprimerIntervention();
}
}
});
vue.cacherLienSuppression();
BusEvenementiel.getInstance().addHandler(EvenementAjoutDetermination.TYPE, new GestionnaireEvenementAjoutDetermination() {
@Override
public void onAjoutDetermination(EvenementAjoutDetermination event) {
if(overlay != null && overlay.fenetreModaleEstOuverte()) {
overlay.fermerFenetreModale();
}
}
});
 
BusEvenementiel.getInstance().addHandler(EvenementAjoutCommentaire.TYPE, new GestionnaireEvenementAjoutCommentaire() {
@Override
public void onAjoutCommentaire(EvenementAjoutCommentaire event) {
if(overlay != null && overlay.fenetreModaleEstOuverte()) {
overlay.fermerFenetreModale();
}
}
});
}
private boolean peutSupprimerIntervention() {
return (!interventionForum.aDesCommentaires() && interventionForum.getContributeur() != null && interventionForum.getContributeur().getId().equals(CacheClient.getInstance().getUtilisateur().getId()));
}
private void supprimerIntervention() {
if(interventionForum instanceof PropositionDetermination) {
propositionDeterminationService.supprimerProposition((PropositionDetermination)interventionForum, new SuppressionPropositionDeterminationCallback() {
@Override
public void surRetour(String objetRetour) {
CacheClient.getInstance().getObservationCourante().supprimerIntervention(interventionForum);
BusEvenementiel.getInstance().fireEvent(new EvenementSuppressionDetermination((PropositionDetermination)interventionForum));
}
});
}
if(interventionForum instanceof Commentaire) {
commentaireService.supprimerCommentaire((Commentaire)interventionForum, new SuppressionCommentaireCallback() {
@Override
public void surRetour(String objetRetour) {
CacheClient.getInstance().getObservationCourante().supprimerIntervention(interventionForum);
BusEvenementiel.getInstance().fireEvent(new EvenementSuppressionCommentaire((Commentaire)interventionForum));
}
});
}
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/forum/interventions/ForumInterventionVue.java
New file
0,0 → 1,166
package org.tela_botanica.del.client.composants.forum.interventions;
 
import org.tela_botanica.del.client.composants.forum.interventions.ForumInterventionPresenteur.Vue;
import org.tela_botanica.del.client.modeles.Commentaire;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasMouseOutHandlers;
import com.google.gwt.event.dom.client.HasMouseOverHandlers;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class ForumInterventionVue extends Composite implements Vue {
 
private static ForumUIiBinder uiBinder = GWT.create(ForumUIiBinder.class);
 
interface ForumUIiBinder extends UiBinder<Widget, ForumInterventionVue> {
};
 
@UiField
FocusPanel proposition;
 
@UiField
Label nom, nomTaxon, date, commentaire, repondre, labelDeterminationProposee;
@UiField
HTMLPanel voter, zoneVoter, zoneDetermination, zoneEnfants;
@UiField
FocusPanel conteneurLienSuppression;
@UiField
HTML supprimer, nbVotesHtml;
@UiField
FocusPanel conteneurPanneauVotes;
public ForumInterventionVue() {
initWidget(uiBinder.createAndBindUi(this));
}
@Override
public HasClickHandlers getLienSuppression() {
return conteneurLienSuppression;
}
@Override
public void afficherLienSuppression() {
conteneurLienSuppression.removeStyleName("invisible");
}
@Override
public void cacherLienSuppression() {
conteneurLienSuppression.addStyleName("invisible");
}
 
@Override
public void ajouterInterventionDetermination(PropositionDetermination determination, IsWidget barreRepartition, IsWidget arbreCommentaires) {
 
nom.setText(determination.getAuteur());
nomTaxon.setText(determination.getEspece());
voter.add(barreRepartition);
date.setText(DateTimeFormat.getFormat("dd/MM/yyyy").format(determination.getDate()));
commentaire.setText(determination.getCommentaire());
if (determination.estFils()) {
proposition.setStyleName("enfant");
}
}
 
@Override
public void ajouterInterventionCommentaire(Commentaire nouveauCommentaire, IsWidget arbreCommentaires) {
 
zoneVoter.setVisible(false);
zoneDetermination.setVisible(false);
nom.setText(nouveauCommentaire.getAuteur());
date.setText(DateTimeFormat.getFormat("dd/MM/yyyy").format(nouveauCommentaire.getDate()));
commentaire.setText(nouveauCommentaire.getCommentaire());
if (nouveauCommentaire.estFils()) {
proposition.setStyleName("enfant");
}
}
@Override
public HasClickHandlers getRepondre() {
return repondre;
}
 
@Override
public HasWidgets getEnfants() {
return zoneEnfants;
}
 
@Override
public HasMouseOverHandlers getConteneurInterventionMouseOver() {
return proposition;
}
 
@Override
public HasMouseOutHandlers getConteneurInterventionMouseOut() {
return proposition;
}
public HasClickHandlers getEspece() {
return nomTaxon;
}
public void ajouterLienEspece() {
nomTaxon.addStyleName("labelLien");
}
public HasClickHandlers getAuteur() {
return nom;
}
public void ajouterLienAuteur() {
nom.addStyleName("lien");
nom.setTitle("Voir le profil");
}
public void cacherDeterminationProposee() {
labelDeterminationProposee.setVisible(false);
}
 
@Override
public void ajouterLienVotes() {
conteneurPanneauVotes.addStyleName("nombreVotes");
}
public void masquerLienVotes() {
conteneurPanneauVotes.removeStyleName("nombreVotes");
nbVotesHtml.setVisible(false);
}
 
@Override
public void setNbVotes(int votes) {
nbVotesHtml.setText(String.valueOf(votes));
}
public HasClickHandlers getZoneNbVotes() {
return this.conteneurPanneauVotes;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/forum/ForumVue.java
New file
0,0 → 1,36
package org.tela_botanica.del.client.composants.forum;
 
 
import org.tela_botanica.del.client.composants.forum.ForumPresenteur.Vue;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;
 
public class ForumVue extends Composite implements Vue {
 
private static ForumUIiBinder uiBinder = GWT.create(ForumUIiBinder.class);
 
interface ForumUIiBinder extends UiBinder<Widget, ForumVue> {
};
 
@UiField
HTMLPanel panneauInterventions;
 
public ForumVue() {
initWidget(uiBinder.createAndBindUi(this));
}
 
@Override
public HTMLPanel getPanneauInterventions() {
return panneauInterventions;
}
 
@Override
public void vider() {
panneauInterventions.clear();
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/forum/ArbreCommentairePresenteur.java
New file
0,0 → 1,40
package org.tela_botanica.del.client.composants.forum;
 
import org.tela_botanica.del.client.modeles.InterventionForum;
 
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class ArbreCommentairePresenteur {
private InterventionForum possesseurDeCommentaires;
public interface Vue extends IsWidget {
public void creerArbreCommentaire(InterventionForum possesseurDeCommentaires);
}
private Vue vue;
public ArbreCommentairePresenteur(Vue vue, InterventionForum possesseurDeCommentaires) {
this.vue = vue;
this.possesseurDeCommentaires = possesseurDeCommentaires;
vue.creerArbreCommentaire(this.possesseurDeCommentaires);
}
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
}
public IsWidget getArbreCommentaireVue() {
return vue;
}
public InterventionForum getPossesseurDeCommentaires() {
return possesseurDeCommentaires;
}
public void gererEvenements() {
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/pagination/PaginationVue.ui.xml
New file
0,0 → 1,16
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui' ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat' ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator" ui:generateLocales="default">
<ui:with field='res' type='org.tela_botanica.del.client.resources.Ressources'/>
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary"/>
<ui:style src="pagination.css" />
<g:HorizontalPanel styleName="{style.pagination}">
<g:Button ui:field="boutonPremierePage" styleName="{style.boutonPremierePage}" text=" " />
<g:Button ui:field="boutonPrecedent" styleName="{style.boutonPrecedent}" text=" " />
<g:TextBox styleName="{style.pageCourante} petit" ui:field="saisiePageCourante"/>
<g:Label styleName="{style.nombreTotal} petit" ui:field="nbTotalPages" />
<g:Button ui:field="boutonSuivant" styleName="{style.boutonSuivant}" text=" "/>
<g:Button ui:field="boutonDernierePage" styleName="{style.boutonDernierePage}" text=" " />
<g:Label styleName="{style.labelSelecteurPasAfficher} petit" text="{constants.afficher}" />
<g:TextBox ui:field="selecteurPas" styleName="{style.selecteurElements} petit" text="10"/>
<g:Label styleName="{style.labelSelecteurPas} petit" text="{constants.elements_par_page}" />
</g:HorizontalPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/pagination/PaginationPresenteur.java
New file
0,0 → 1,304
package org.tela_botanica.del.client.composants.pagination;
 
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.pagination.EvenementChangementPage;
import org.tela_botanica.del.client.navigation.evenement.pagination.EvenementChangementPas;
import org.tela_botanica.del.client.navigation.evenement.pagination.GestionnaireEvenementChangementPage;
import org.tela_botanica.del.client.navigation.evenement.pagination.GestionnaireEvenementChangementPas;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasChangeHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
/**
* @author gregoire Pagination GENERIQUE qui permet d'afficher un nombre donné
* d'éléments (pas) La méthode changerPage est abstraite et doit être
* définie lors de l'instanciation de la classe pagination pour
* permettre d'afficher la suite des éléments La méthode
* actualiserPasCache est abstraite car le pas est différent en fonction
* de la page où l'on se trouve
* */
public abstract class PaginationPresenteur {
 
public interface Vue extends IsWidget {
public HasClickHandlers getBoutonSuivant();
public HasClickHandlers getBoutonPrecedent();
public HasClickHandlers getBoutonPremierePage();
public HasClickHandlers getBoutonDernierePage();
public void masquerBoutonPrecedent();
public void afficherBoutonPrecedent();
public void masquerBoutonSuivant();
public void afficherBoutonSuivant();
public boolean boutonPrecedentEstAffiche();
public boolean boutonSuivantEstAffiche();
public HasChangeHandlers getSelecteurPas();
public int getPasSelectionne();
public void afficherPas(int pas);
public void mettreNbTotalPages(int nbPages);
public HasChangeHandlers getSaisiePageCourante();
public int getPageSaisie();
public void setPageCourante(int pageCourante);
}
 
private Vue vue;
private int nbPage = 1;
private int pageCourante = 1;
private int nbElementsTotal = 0;
private int pas = 10;
 
private String groupePagination = null;
 
/**
* Constructeur de l'application
*
* @param nbElementsTotal
* : le nombre total des éléments à paginer
* @param pas
* : le nombre d'éléments à afficher par page
* */
public PaginationPresenteur(Vue vue, int nbElementsTotal, int pas, int pageCourante) {
this.nbElementsTotal = nbElementsTotal;
this.vue = vue;
this.pas = pas;
this.pageCourante = pageCourante;
vue.setPageCourante(pageCourante);
this.nbPage = calculerNbPage();
}
 
/**
* Methode go du modèle MVP
*
* @param container
* : la vue ou éxécuter l'affichage
*/
public void go(HasWidgets container) {
container.add(vue.asWidget());
gererEvenements();
actualiserPas();
actualiserAffichageBoutons();
vue.mettreNbTotalPages(nbPage);
}
 
/**
* Gérer les évènements sur les boutons statiques (précédent, suivant et
* selecteur pas)
* */
protected void gererEvenements() {
vue.getSaisiePageCourante().addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
int pageSaisie;
try {
pageSaisie = vue.getPageSaisie();
if (pageSaisie < 0) {
pageSaisie = 1;
} else if (pageSaisie > nbPage){
pageSaisie = nbPage;
}
} catch (NumberFormatException e) {
pageSaisie = pageCourante;
}
pageCourante = pageSaisie;
chargerElements(pas * (pageCourante - 1), pas * (pageCourante));
vue.setPageCourante(pageCourante);
actualiserAffichageBoutons();
}
});
vue.getSelecteurPas().addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
int pasSelectionne;
try {
pasSelectionne = vue.getPasSelectionne();
if (pasSelectionne < 0) {
pasSelectionne = 1;
} else if (pasSelectionne > 100){
pasSelectionne = 100;
}
} catch (NumberFormatException e) {
pasSelectionne = pas;
}
changerPas(pasSelectionne);
}
});
 
vue.getBoutonPrecedent().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
allerALaPagePrecedente();
}
});
 
vue.getBoutonSuivant().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
allerALapageSuivante();
}
});
 
vue.getBoutonPremierePage().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
allerALaPremierePage();
}
});
 
vue.getBoutonDernierePage().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
allerAlaDernierePage();
}
});
 
BusEvenementiel.getInstance().addHandler(EvenementChangementPage.TYPE, new GestionnaireEvenementChangementPage() {
 
@Override
public void onChangementPage(EvenementChangementPage event) {
if (event.getGroupePagination() == groupePagination) {
pageCourante = event.getPageAAfficher();
vue.setPageCourante(pageCourante);
actualiserAffichageBoutons();
vue.mettreNbTotalPages(nbPage);
}
}
});
 
BusEvenementiel.getInstance().addHandler(EvenementChangementPas.TYPE, new GestionnaireEvenementChangementPas() {
 
@Override
public void onChangementPas(EvenementChangementPas event) {
if (event.getGroupePagination() == groupePagination) {
// modifie le pas et les liens en fonction
pas = event.getPas();
actualiserPas();
}
}
});
}
 
private void gererDecalagePageCourante(int ancienPas, int nouveauPas) {
if (ancienPas != nouveauPas) {
double rapportPas = (double) ancienPas / (double) nouveauPas;
pageCourante = (int) (Math.ceil((double) pageCourante * (double) rapportPas));
}
}
 
public void actualiserPas() {
actualiserPasCache(pas);
vue.afficherPas(pas);
}
 
public int getPageCourante() {
return this.pageCourante;
}
 
public int getPas() {
return this.pas;
}
 
public void setPageCourante(int pageCourante) {
this.pageCourante = pageCourante;
}
 
public void changerPas(int nouveauPas) {
 
// TODO corriger bug qui ne charge pas la bonne page ds certains cas
// gererDecalagePageCourante(pas, nouveauPas);
// pas = nouveauPas;
// chargerElements((pageCourante - 1)*pas, pageCourante*pas);
pas = nouveauPas;
this.nbPage = calculerNbPage();
chargerElements(0, pas);
BusEvenementiel.getInstance().fireEvent(new EvenementChangementPas(nouveauPas, groupePagination));
BusEvenementiel.getInstance().fireEvent(new EvenementChangementPage(1, groupePagination));
}
 
public void allerALaPagePrecedente() {
if (pageCourante > 1) {
int pageAAfficher = pageCourante - 1;
pageCourante = pageAAfficher;
chargerElements(pas * (pageAAfficher - 1), pas * (pageAAfficher));
BusEvenementiel.getInstance().fireEvent(new EvenementChangementPage(pageAAfficher, groupePagination));
}
 
}
 
public void allerALapageSuivante() {
if (pageCourante < nbPage) {
int pageAAfficher = pageCourante + 1;
pageCourante = pageAAfficher;
chargerElements(pas * (pageAAfficher - 1), pas * (pageAAfficher));
BusEvenementiel.getInstance().fireEvent(new EvenementChangementPage(pageAAfficher, groupePagination));
}
}
 
public void allerALaPremierePage() {
int pageAAfficher = 1;
pageCourante = pageAAfficher;
chargerElements(0, pas);
BusEvenementiel.getInstance().fireEvent(new EvenementChangementPage(pageAAfficher, groupePagination));
}
 
public void allerAlaDernierePage() {
int pageAAfficher = nbPage;
pageCourante = pageAAfficher;
chargerElements(pas * (pageAAfficher - 1), pas * (pageAAfficher));
BusEvenementiel.getInstance().fireEvent(new EvenementChangementPage(pageAAfficher, groupePagination));
}
 
/** calcule le nombre de page en fonction du pas */
private int calculerNbPage() {
Double nombrePages = Math.ceil((double) nbElementsTotal / (double) pas);
return nombrePages.intValue();
}
 
public void setNbPages(int nbPages) {
this.nbPage = nbPages;
}
 
public int getNbPages() {
return nbPage;
}
 
public Vue getVue() {
return vue;
}
 
public abstract void chargerElements(int debut, int fin);
 
public abstract void actualiserPasCache(int pas);
 
public void setPas(int pas) {
this.pas = pas;
}
 
public void setGroupePagination(String groupePagination) {
this.groupePagination = groupePagination;
}
 
public String getGroupePagination() {
return groupePagination;
}
 
public void actualiserAffichageBoutons() {
if (nbPage == 1) {
vue.masquerBoutonPrecedent();
vue.masquerBoutonSuivant();
} else if (pageCourante == 1) {
vue.masquerBoutonPrecedent();
vue.afficherBoutonSuivant();
} else {
vue.afficherBoutonPrecedent();
if (pageCourante == nbPage) {
vue.masquerBoutonSuivant();
}
}
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/pagination/PaginationVue.java
New file
0,0 → 1,129
package org.tela_botanica.del.client.composants.pagination;
 
import org.tela_botanica.del.client.i18n.I18n;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasChangeHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
 
public class PaginationVue extends Composite implements PaginationPresenteur.Vue {
 
@UiField
TextBox saisiePageCourante;
 
@UiField
TextBox selecteurPas;
 
@UiField
Button boutonPrecedent, boutonSuivant, boutonPremierePage, boutonDernierePage;
 
@UiField
Label nbTotalPages;
 
interface MyUiBinder extends UiBinder<Widget, PaginationVue> {
}
 
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
 
public PaginationVue() {
initWidget(uiBinder.createAndBindUi(this));
}
 
public void afficherPas(int pas) {
selecteurPas.setText(String.valueOf(pas));
}
 
public void mettreNbTotalPages(int nbPages) {
nbTotalPages.setText((I18n.getMessages().parmi_nb_pages(nbPages)));
}
 
public void masquerBoutonPrecedent() {
boutonPremierePage.setVisible(false);
boutonPrecedent.setVisible(false);
}
 
public void afficherBoutonPrecedent() {
boutonPremierePage.setVisible(true);
boutonPrecedent.setVisible(true);
}
 
public void masquerBoutonSuivant() {
boutonDernierePage.setVisible(false);
boutonSuivant.setVisible(false);
}
 
public void afficherBoutonSuivant() {
boutonDernierePage.setVisible(true);
boutonSuivant.setVisible(true);
}
 
public TextBox getSelecteurPas() {
return selecteurPas;
}
 
@Override
public HasChangeHandlers getSaisiePageCourante() {
return saisiePageCourante;
}
 
@Override
public HasClickHandlers getBoutonSuivant() {
return boutonSuivant;
}
 
@Override
public HasClickHandlers getBoutonPrecedent() {
return boutonPrecedent;
}
 
@Override
public HasClickHandlers getBoutonPremierePage() {
return boutonPremierePage;
}
 
@Override
public HasClickHandlers getBoutonDernierePage() {
return boutonDernierePage;
}
 
@Override
public int getPasSelectionne() throws NumberFormatException {
return Integer.parseInt(selecteurPas.getText());
}
 
@Override
public boolean boutonPrecedentEstAffiche() {
return boutonPrecedent.isVisible() && boutonPremierePage.isVisible();
}
 
@Override
public boolean boutonSuivantEstAffiche() {
return boutonSuivant.isVisible() && boutonDernierePage.isVisible();
}
 
public Label getNbTotalPages() {
return nbTotalPages;
}
 
@Override
public int getPageSaisie() throws NumberFormatException {
return Integer.parseInt(saisiePageCourante.getText());
}
@Override
public void setPageCourante(int pageCourante) {
saisiePageCourante.setText(String.valueOf(pageCourante));
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/pagination/pagination.css
New file
0,0 → 1,16
.pagination {width:100%;}
.selecteurElements {float:right; width:2em}
.pageCourante {width:2.6em}
.pagination button {border:none; border-right:solid 1px #DDD; cursor:pointer; width:30px}
.zoneLiens {}
.zoneLiens button:hover {background:#8EB533}
select {background:white}
 
.boutonPrecedent {border:solid 1px #8EB533; width:20px; height:20px; background:url(./img/prev.png) no-repeat}
.boutonSuivant {border:solid 1px #8EB533; width:20px; height:20px; background:url(./img/next.png) no-repeat}
.boutonPremierePage {width:20px; height:20px; background:url(./img/first.png) no-repeat}
.boutonDernierePage {width:20px; height:20px; background:url(./img/last.png) no-repeat}
 
.nombreTotal {margin-left:5px;}
.labelSelecteurPas{margin-left:5px;margin-right:5px; margin-top: 3px;}
.labelSelecteurPasAfficher{margin-left:10px;;margin-right:5px; margin-top: 3px;}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/validation/ValidateurChampTexteAbstrait.java
New file
0,0 → 1,40
package org.tela_botanica.del.client.composants.validation;
 
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.TextBox;
 
public abstract class ValidateurChampTexteAbstrait extends ValidateurFormulaireAbstrait {
 
private HasText textBox;
protected String styleErreur = "erreurFormTexte";
 
public ValidateurChampTexteAbstrait(HasText textBox) {
this.textBox = textBox;
}
public ValidateurChampTexteAbstrait(TextBox textBox, String styleErreur) {
this.textBox = textBox;
this.styleErreur = styleErreur;
}
 
public HasText getTextBox() {
return textBox;
}
 
public void setTextBox(TextBox textBox) {
this.textBox = textBox;
}
public String getStyleErreur() {
return styleErreur;
}
 
public void setStyleErreur(String styleErreur) {
this.styleErreur = styleErreur;
}
public void afficherStyleErreur(String styleErreur) {};
public void supprimerStyleErreur(String styleErreur) {};
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/validation/ValidateurChampTexteNonNul.java
New file
0,0 → 1,26
package org.tela_botanica.del.client.composants.validation;
 
import org.tela_botanica.del.client.i18n.I18n;
 
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.TextBox;
 
public class ValidateurChampTexteNonNul extends ValidateurChampTexteAbstrait {
public ValidateurChampTexteNonNul(HasText textBox) {
super(textBox);
}
 
@Override
public boolean valider() {
if (getTextBox().getText().length() >= 0 && !getTextBox().getText().equals("")) {
supprimerStyleErreur(getStyleErreur());
return true;
} else {
afficherStyleErreur(getStyleErreur());
return false;
}
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/validation/ValidateurFormulaireAbstrait.java
New file
0,0 → 1,9
package org.tela_botanica.del.client.composants.validation;
 
public abstract class ValidateurFormulaireAbstrait {
 
public abstract boolean valider();
public abstract void afficherStyleErreur(String styleErreur);
public abstract void supprimerStyleErreur(String styleErreur);
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/validation/ValidateurChampDouble.java
New file
0,0 → 1,28
package org.tela_botanica.del.client.composants.validation;
 
import org.tela_botanica.del.client.i18n.I18n;
 
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.TextBox;
 
 
public class ValidateurChampDouble extends ValidateurChampTexteAbstrait {
 
public ValidateurChampDouble(HasText textBox) {
super(textBox);
}
 
@Override
public boolean valider() {
try {
Double.parseDouble(getTextBox().getText());
supprimerStyleErreur(getStyleErreur());
return true;
} catch (Exception e) {
afficherStyleErreur(getStyleErreur());
return false;
}
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/validation/ValidateurChampNCaracteres.java
New file
0,0 → 1,32
package org.tela_botanica.del.client.composants.validation;
 
import org.tela_botanica.del.client.i18n.I18n;
 
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.TextBox;
 
public class ValidateurChampNCaracteres extends ValidateurChampTexteAbstrait {
 
private int nbCaracteres = 0;
public ValidateurChampNCaracteres(TextBox textBox) {
super(textBox);
// TODO Auto-generated constructor stub
}
public void setNbCaracteres(int nbCaracteresMax) {
nbCaracteres = nbCaracteresMax;
}
 
@Override
public boolean valider() {
if(getTextBox().getText().length()>=nbCaracteres){
supprimerStyleErreur(getStyleErreur());
return true;
} else {
afficherStyleErreur(getStyleErreur());
return false;
}
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/validation/ValidateurChampNumerique.java
New file
0,0 → 1,29
package org.tela_botanica.del.client.composants.validation;
 
import org.tela_botanica.del.client.i18n.I18n;
 
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.TextBox;
 
public class ValidateurChampNumerique extends ValidateurChampTexteAbstrait {
 
public ValidateurChampNumerique(HasText textBox) {
super(textBox);
}
 
@Override
public boolean valider() {
try{
Integer.parseInt(getTextBox().getText());
supprimerStyleErreur(getStyleErreur());
return true;
} catch (Exception e) {
supprimerStyleErreur(getStyleErreur());
return false;
}
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/validation/ValidateurChampFlottant.java
New file
0,0 → 1,26
package org.tela_botanica.del.client.composants.validation;
 
import org.tela_botanica.del.client.i18n.I18n;
 
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.TextBox;
 
public class ValidateurChampFlottant extends ValidateurChampTexteAbstrait {
 
public ValidateurChampFlottant(TextBox textBox) {
super(textBox);
}
 
@Override
public boolean valider() {
try {
Float.parseFloat(getTextBox().getText());
supprimerStyleErreur(getStyleErreur());
return true;
} catch (Exception e) {
afficherStyleErreur(getStyleErreur());
return false;
}
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/fenetreoverlay/FenetreOverlayDefilanteVue.ui.xml
New file
0,0 → 1,16
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui' ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
ui:generateLocales="default">
 
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
<g:VerticalPanel styleName="fenetreDefilante" ui:field="conteneurGlobal">
<g:FocusPanel ui:field="overlay" />
<g:HorizontalPanel ui:field="conteneurOverlayContenu" styleName="">
<g:Button ui:field="boutonPrecedent" text="" />
<g:FocusPanel ui:field="overlayContenu" />
<g:Button ui:field="boutonSuivant" text="" />
<g:Button ui:field="boutonFermer" />
</g:HorizontalPanel>
</g:VerticalPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/fenetreoverlay/FenetreOverlaySimplePresenteur.java
New file
0,0 → 1,28
package org.tela_botanica.del.client.composants.fenetreoverlay;
 
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
 
/**
* Simple implémentation de la fenetre overlay defilante avec masquage direct des boutons
* suivant et précédent et simplification de la méthode
* @author aurelien
*
*/
public class FenetreOverlaySimplePresenteur extends FenetreOverlayDefilantePresenteur {
 
public FenetreOverlaySimplePresenteur(Vue vue) {
super(0, vue);
afficherBoutonsSuivantsPrecedents(false);
setFermableSurClicExterieur(false);
}
public void ouvrirFenetreModale(Presenteur presenteur) {
super.ouvrirFenetreModaleDefilante(0, presenteur);
}
 
@Override
public void surClicBoutonSuivant() {}
 
@Override
public void surClicBoutonPrecedent() {}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/fenetreoverlay/FenetreOverlayDefilantePresenteur.java
New file
0,0 → 1,161
package org.tela_botanica.del.client.composants.fenetreoverlay;
 
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
 
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.HasBlurHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasFocusHandlers;
import com.google.gwt.event.dom.client.HasKeyDownHandlers;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.shared.HasHandlers;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasVisibility;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.RootPanel;
 
public abstract class FenetreOverlayDefilantePresenteur {
 
public interface Vue extends IsWidget {
public HasKeyDownHandlers getConteneurGlobal();
public IsWidget getOverlay();
public void afficherBoutonsSuivantsPrecedents(boolean afficher);
public HasClickHandlers getOverlayHasClickHandlers();
public HasVisibility getOverlayVisibility();
public IsWidget getOverlayContenu();
public HasVisibility getOverlayContenuVisibility();
public HasWidgets getOverlayContenuHasWidgets();
public HasClickHandlers getBoutonFermer();
public HasClickHandlers getBoutonSuivant();
public HasClickHandlers getBoutonPrecedent();
public void setStyleOverlay(String style);
public void setStyleOverlayContenu(String style);
public void setOverlayContenu(IsWidget w);
public void viderOverlay();
public void viderOverlayContenu();
public void surOuvertureFenetre();
public void surFermetureFenetre();
public void surSetContenuFenetre();
}
private Vue vue;
private boolean fenetreModaleOuverte = false;
private boolean fermableSurClicExterieur = true;
private int indexElementAffiche = 0;
 
// Constructeur
public FenetreOverlayDefilantePresenteur(int indexElementAffiche, Vue vue) {
this.indexElementAffiche = indexElementAffiche;
this.vue = vue;
gererEvenements();
}
// Afficheur
public void go() {
go(null);
}
 
public void go(HasWidgets composite) {
}
 
// Gestion des évènements
protected void gererEvenements() {
vue.getBoutonFermer().addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
fermerFenetreModale();
}
});
vue.getBoutonPrecedent().addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
surClicBoutonPrecedent();
}
});
vue.getBoutonSuivant().addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
surClicBoutonSuivant();
}
});
vue.getConteneurGlobal().addKeyDownHandler(new KeyDownHandler() {
@Override
public void onKeyDown(KeyDownEvent event) {
if(event.getNativeKeyCode() == KeyCodes.KEY_LEFT) {
surClicBoutonPrecedent();
}
if(event.getNativeKeyCode() == KeyCodes.KEY_RIGHT) {
surClicBoutonSuivant();
}
}
});
vue.getOverlayHasClickHandlers().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if(fermableSurClicExterieur) {
fermerFenetreModale();
}
}
});
}
 
public void ouvrirFenetreModaleDefilante(int indexElementAffiche, Presenteur presenteurModal) {
vue.setStyleOverlay("overlay");
vue.setStyleOverlayContenu("overlayContenu");
vue.getOverlayContenuVisibility().setVisible(true);
vue.getOverlayVisibility().setVisible(true);
RootPanel.get().add(vue.asWidget());
fenetreModaleOuverte = true;
setContenuFenetreModale(indexElementAffiche, presenteurModal);
vue.surOuvertureFenetre();
}
public void setContenuFenetreModale(int indexElementAffiche, Presenteur presenteurModal) {
this.indexElementAffiche = indexElementAffiche;
vue.viderOverlayContenu();
presenteurModal.go(vue.getOverlayContenuHasWidgets());
vue.surSetContenuFenetre();
}
public abstract void surClicBoutonSuivant();
public abstract void surClicBoutonPrecedent();
public boolean fenetreModaleEstOuverte() {
return fenetreModaleOuverte;
}
 
public void fermerFenetreModale() {
vue.viderOverlay();
vue.viderOverlayContenu();
RootPanel.get().remove(vue.asWidget());
fenetreModaleOuverte = false;
vue.surFermetureFenetre();
}
public int getIndexElementAffiche() {
return indexElementAffiche;
}
public void setFermableSurClicExterieur(boolean fermableSurClicExterieur) {
this.fermableSurClicExterieur = fermableSurClicExterieur;
}
 
public void afficherBoutonsSuivantsPrecedents(boolean afficher) {
vue.afficherBoutonsSuivantsPrecedents(afficher);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/fenetreoverlay/FenetreOverlayDefilanteVue.java
New file
0,0 → 1,230
package org.tela_botanica.del.client.composants.fenetreoverlay;
 
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlayDefilantePresenteur.Vue;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasBlurHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasFocusHandlers;
import com.google.gwt.event.dom.client.HasKeyDownHandlers;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasVisibility;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
 
public class FenetreOverlayDefilanteVue extends Composite implements Vue {
 
interface MyUiBinder extends UiBinder<Widget, FenetreOverlayDefilanteVue> {
}
@UiField
VerticalPanel conteneurGlobal;
 
@UiField
FocusPanel overlay;
@UiField
FocusPanel overlayContenu;
 
@UiField
Button boutonFermer, boutonSuivant, boutonPrecedent;
@UiField
HorizontalPanel conteneurOverlayContenu;
private int hauteurContenu = 0;
private int largeurContenu = 0;
// contiennent les coordonnées actuelles du scroll
// pour le rétablir une fois la fenêtre fermée
private int topFenetre = 0;
private int gaucheFenetre = 0;
private Timer timerPlacement = null;
public FocusPanel getOverlay() {
return overlay;
}
 
public FocusPanel getOverlayContenu() {
return overlayContenu;
}
@Override
public HasClickHandlers getOverlayHasClickHandlers() {
return overlayContenu;
}
 
public Button getBoutonFermer() {
return boutonFermer;
}
 
public Button getBoutonSuivant() {
return boutonSuivant;
}
 
public Button getBoutonPrecedent() {
return boutonPrecedent;
}
 
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
 
public FenetreOverlayDefilanteVue() {
initWidget(uiBinder.createAndBindUi(this));
boutonFermer.setStyleName("fermerOverlay");
boutonPrecedent.setStyleName("precedentOverlay");
boutonSuivant.setStyleName("suivantOverlay");
Window.addResizeHandler(new ResizeHandler() {
@Override
public void onResize(ResizeEvent event) {
gererDimensionsEtPositionnerBoutons();
}
});
}
@Override
public HasKeyDownHandlers getConteneurGlobal() {
return overlayContenu;
}
 
@Override
public HasVisibility getOverlayVisibility() {
return overlay;
}
 
@Override
public HasVisibility getOverlayContenuVisibility() {
return overlayContenu;
}
 
@Override
public HasWidgets getOverlayContenuHasWidgets() {
return overlayContenu;
}
 
@Override
public void setStyleOverlay(String style) {
overlay.setStyleName(style);
}
 
@Override
public void setStyleOverlayContenu(String style) {
overlayContenu.setStyleName(style);
}
 
@Override
public void setOverlayContenu(IsWidget w) {
overlayContenu.clear();
overlayContenu.add(w);
}
 
@Override
public void viderOverlay() {
overlay.clear();
}
 
@Override
public void viderOverlayContenu() {
overlayContenu.clear();
}
private void gererDimensionsEtPositionnerBoutons() {
UIObject overlayContenuUi = overlayContenu.getWidget();
if(overlayContenuUi == null) {
return;
}
int topBoutonFermer = 65;
int topBoutonsSuivantsPrecedent = (topBoutonFermer + overlayContenuUi.getOffsetHeight())/2 + 20;
int left = overlayContenuUi.getAbsoluteLeft() - 20;
int right = overlayContenuUi.getAbsoluteLeft() + overlayContenuUi.getOffsetWidth() - 12;
DOM.setStyleAttribute(boutonPrecedent.getElement(), "left",left+"px");
DOM.setStyleAttribute(boutonPrecedent.getElement(), "top", topBoutonsSuivantsPrecedent+"px");
DOM.setStyleAttribute(boutonSuivant.getElement(), "left",right+"px");
DOM.setStyleAttribute(boutonSuivant.getElement(), "top", topBoutonsSuivantsPrecedent+"px");
DOM.setStyleAttribute(boutonFermer.getElement(), "left",(right - 10)+"px");
DOM.setStyleAttribute(boutonFermer.getElement(), "top", topBoutonFermer+"px");
setDimensionsContenu(overlayContenuUi.getOffsetHeight(), overlayContenuUi.getOffsetWidth());
}
private void setDimensionsContenu(int hauteur, int largeur) {
largeurContenu = largeur;
hauteurContenu = hauteur;
}
 
@Override
public void surOuvertureFenetre() {
// enregistrement des coordonnées des scrool
topFenetre = Window.getScrollTop();
gaucheFenetre = Window.getScrollLeft();
// scroll désactivé pour ne pas fausser le positionnement des boutons
Window.enableScrolling(false);
// Pas trouvé mieux que le timer pour bien redimensionner
// à voir s il existe une meilleure solution qui n'oblige pas
// par avance à connaitre le type d'objet contenu dans l'overlayContenu
// ou bien la taille de la fenetre
timerPlacement = new Timer() {
@Override
public void run() {
if(tailleDuContenuEstModifiee()) {
// On repositionne les boutons
gererDimensionsEtPositionnerBoutons();
}
}
};
timerPlacement.scheduleRepeating(30);
}
private boolean tailleDuContenuEstModifiee() {
UIObject overlayContenuUi = overlayContenu.getWidget();
return overlayContenuUi != null
&& (overlayContenuUi.getOffsetHeight() != hauteurContenu
|| overlayContenuUi.getOffsetWidth() != largeurContenu);
}
 
@Override
public void surFermetureFenetre() {
Window.enableScrolling(true);
// replacement de la fenêtre à la position de scroll d'origine
Window.scrollTo(gaucheFenetre, topFenetre);
timerPlacement.cancel();
}
@Override
public void surSetContenuFenetre() {
// nécessaire pour le défilement avec les touches du clavier
overlayContenu.setFocus(true);
}
 
@Override
public void afficherBoutonsSuivantsPrecedents(boolean afficher) {
boutonPrecedent.setVisible(afficher);
boutonSuivant.setVisible(afficher);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/presenteur/Presenteur.java
New file
0,0 → 1,73
package org.tela_botanica.del.client.composants.presenteur;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RootPanel;
 
public abstract class Presenteur {
 
private Panel overlay;
private Panel overlayContenu;
private PresenteurVue presenteurVue;
private boolean fenetreModaleOuverte = false;
 
// Constructeur
public Presenteur() {
}
 
// Afficheur
public void go() {
go(null);
}
 
public abstract void go(HasWidgets composite);
 
// Gestion des évènements
protected abstract void gererEvenements();
 
public void ouvrirFenetreModale(Presenteur presenteurModal) {
presenteurVue = new PresenteurVue();
overlay = presenteurVue.overlay;
overlay.setStyleName("overlay");
overlay.setVisible(false);
RootPanel.get().add(overlay);
 
overlayContenu = presenteurVue.overlayContenu;
overlayContenu.setStyleName("overlayContenu");
 
Button boutonFermer = presenteurVue.boutonFermer;
boutonFermer.setStyleName("fermerOverlay");
boutonFermer.addClickHandler(new ClickHandler() {
 
public void onClick(ClickEvent event) {
fermerFenetreModale();
}
});
 
presenteurModal.go(overlayContenu);
 
RootPanel.get().add(overlayContenu);
overlayContenu.setVisible(true);
 
overlayContenu.add(boutonFermer);
overlay.setVisible(true);
fenetreModaleOuverte = true;
}
public boolean fenetreModaleEstOuverte() {
return fenetreModaleOuverte;
}
 
public void fermerFenetreModale() {
overlay.clear();
overlayContenu.clear();
RootPanel.get().remove(overlay);
RootPanel.get().remove(overlayContenu);
fenetreModaleOuverte = false;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/presenteur/PresenteurVue.java
New file
0,0 → 1,29
package org.tela_botanica.del.client.composants.presenteur;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;
 
public class PresenteurVue extends Composite {
 
// Annotation can be used to change the name of the associated xml file
// @UiTemplate("ObservationRechercheVue.ui.xml")
interface MyUiBinder extends UiBinder<Widget, PresenteurVue> {
}
 
@UiField
HTMLPanel overlay, overlayContenu;
 
@UiField
Button boutonFermer;
 
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
 
protected PresenteurVue() {
initWidget(uiBinder.createAndBindUi(this));
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/presenteur/PresenteurVue.ui.xml
New file
0,0 → 1,13
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui' ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
ui:generateLocales="default">
 
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
<g:VerticalPanel>
<g:Button ui:field="boutonFermer" text="{constants.fermer}" />
<g:HTMLPanel ui:field="overlay" />
<g:HTMLPanel ui:field="overlayContenu" />
</g:VerticalPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votes/details/DetailListeVotesDeterminationVue.java
New file
0,0 → 1,132
package org.tela_botanica.del.client.composants.votes.details;
 
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
 
import org.tela_botanica.del.client.i18n.I18n;
import org.tela_botanica.del.client.modeles.MoyenneVote;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.modeles.VoteDetermination;
import org.tela_botanica.del.client.services.CalculVoteDeterminationService;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class DetailListeVotesDeterminationVue extends Composite implements DetailListeVotesDeterminationPresenteur.Vue {
private static DetailListeVotesDeterminationVueUIiBinder uiBinder = GWT.create(DetailListeVotesDeterminationVueUIiBinder.class);
 
interface DetailListeVotesDeterminationVueUIiBinder extends UiBinder<Widget, DetailListeVotesDeterminationVue> {
};
@UiField
HTMLPanel titre, auteur, aucuneDonnees, detailVotePour, detailVoteContre;
@UiField
Label scorePour, scoreContre, date;
@UiField
Panel panneauChargement;
 
public DetailListeVotesDeterminationVue() {
initWidget(uiBinder.createAndBindUi(this));
}
public String formaterDate(String dateNonFormatee) {
try {
DateTimeFormat parseur = DateTimeFormat.getFormat("yyyy-dd-MM HH:mm:ss");
Date date = parseur.parse(dateNonFormatee);
DateTimeFormat formateur = DateTimeFormat.getFormat("dd/MM/yyyy");
return formateur.format(date);
} catch (IllegalArgumentException e) {
return "";
}
}
 
@Override
public void afficherVotes(PropositionDetermination propositionDetermination) {
HTML htmlTitre = new HTML(propositionDetermination.getEspece());
titre.add(htmlTitre);
HTML htmlAuteur = new HTML(I18n.getVocabulary().proposePar()+propositionDetermination.getAuteur());
auteur.add(htmlAuteur);
String date = formaterDate(propositionDetermination.getObservation().getDateReleve());
this.date.setText(date);
Map<String, VoteDetermination> listeVotes = propositionDetermination.getVotesDeterminations();
int votesAnonymesPour = 0;
int votesAnonymesContre = 0;
MoyenneVote moyenne = CalculVoteDeterminationService.calculerMoyenneVoteDetermination(propositionDetermination, listeVotes.size());
scorePour.setText(moyenne.getScore()+"%");
scoreContre.setText((100 - moyenne.getScore())+"%");
for (Iterator<String> iterator = listeVotes.keySet().iterator(); iterator.hasNext();) {
VoteDetermination voteDetermination = listeVotes.get(iterator.next());
if (voteDetermination.getVote() == 1) {
//Votes pour
if (voteDetermination.getAuteur() != null) {
ajouterVote(voteDetermination, detailVotePour);
} else {
votesAnonymesPour++;
}
} else {
//Votes contre
if (voteDetermination.getAuteur() != null) {
ajouterVote(voteDetermination, detailVoteContre);
} else {
votesAnonymesContre++;
}
}
}
if (votesAnonymesPour > 0) {
LigneVotePresenteur presenteurVote= new LigneVotePresenteur(new LigneVoteVue(), votesAnonymesPour);
presenteurVote.go(detailVotePour);
}
if (votesAnonymesContre > 0) {
LigneVotePresenteur presenteurVote= new LigneVotePresenteur(new LigneVoteVue(), votesAnonymesContre);
presenteurVote.go(detailVoteContre);
}
}
public void ajouterVote(VoteDetermination vote, HasWidgets panel) {
LigneVotePresenteur presenteurVote = new LigneVotePresenteur(new LigneVoteVue(), vote);
presenteurVote.go(panel);
}
@Override
public void startChargement() {
panneauChargement.setHeight((this.getOffsetHeight()/2)+"px");
panneauChargement.setWidth((this.getOffsetWidth()/2)+"px");
panneauChargement.setVisible(true);
}
 
@Override
public void stopChargement() {
panneauChargement.setVisible(false);
}
 
@Override
public void afficherAucuneDonnees() {
aucuneDonnees.setVisible(true);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votes/details/LigneVoteVue.ui.xml
New file
0,0 → 1,12
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:vues="urn:import:org.tela_botanica.del.client.composants.forum">
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
<ui:style src="ligneVote.css" />
<g:HTMLPanel styleName="nettoyage">
<g:Label ui:field="auteur" styleName="{style.auteur}"></g:Label>
<g:Label ui:field="dateOuNb" styleName="{style.colonne2}"></g:Label>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votes/details/LigneVotePresenteur.java
New file
0,0 → 1,56
package org.tela_botanica.del.client.composants.votes.details;
 
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.i18n.I18n;
import org.tela_botanica.del.client.modeles.VoteDetermination;
 
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class LigneVotePresenteur extends Presenteur {
 
public interface Vue extends IsWidget {
public void setAuteur(String auteur);
public void setColonneDateEtNb(String date);
}
private Vue vue;
private VoteDetermination vote;
public LigneVotePresenteur(Vue vue, VoteDetermination vote) {
this.vue = vue;
this.vote = vote;
afficherProposition();
}
//Pour les votes anonymes
public LigneVotePresenteur(Vue vue, int nbVotes) {
this.vue = vue;
vue.setAuteur(I18n.getMessages().etVotesAnonymes(String.valueOf(nbVotes)));
}
public void afficherProposition() {
vue.setAuteur(vote.getAuteur().getNomComplet());
vue.setColonneDateEtNb(DateTimeFormat.getFormat("dd/MM/yyyy").format(vote.getDate()));
}
/**
* Declenchement du présenteur
*/
public void go(HasWidgets container) {
container.add(vue.asWidget());
gererEvenements();
}
 
protected void gererEvenements() {
}
 
}
 
 
 
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votes/details/LigneVoteVue.java
New file
0,0 → 1,33
package org.tela_botanica.del.client.composants.votes.details;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
 
public class LigneVoteVue extends Composite implements LigneVotePresenteur.Vue {
 
interface LigneVoteVueUiBinder extends UiBinder<Widget, LigneVoteVue> {};
private static LigneVoteVueUiBinder uiBinder = GWT.create(LigneVoteVueUiBinder.class);
//Composants
@UiField
Label auteur, dateOuNb;
public LigneVoteVue() {
initWidget(uiBinder.createAndBindUi(this));
}
@Override
public void setAuteur(String auteur) {
this.auteur.setText(auteur);
}
@Override
public void setColonneDateEtNb(String date) {
this.dateOuNb.setText(date);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votes/details/detailListeVotesDeterminationVue.css
New file
0,0 → 1,93
.conteneurTableauVotes {
z-index: 1500;
padding: 30px;
padding-right: 21px;
padding-top: 20px;
background: white;
width: 600px;
margin: 0 auto;
margin-top: 75px;
padding-bottom:25px;
}
 
.chargement {
padding-left: 165px;
}
 
.auteur {
color: #6C6865;
font-family: arial;
font-size: 13px;
letter-spacing: 0;
line-height: 18px;
text-transform: none;
}
 
.date {
color: #6C6865;
font-family: arial;
font-size: 13px;
letter-spacing: 0;
line-height: 18px;
text-transform: none;
margin-left:3px
}
 
.dateLabel {
color: #6C6865;
font-family: arial;
font-size: 13px;
letter-spacing: 0;
line-height: 18px;
text-transform: none;
margin-left:3px;
text-transform:lowercase
}
 
 
.detailVotePour {
width:250px;
float:left;
margin-bottom:15px
}
.detailVoteContre {
width:250px;
float:left;
}
.titreVotes div {
font-size:16px;
color:#8EB533;
margin-bottom:5px;
margin-right:15px;
float:left;
font-weight:bold;
}
.titreVotesContre div {
color:#f06a6a;
}
.detailVotes {
clear:left;
}
.detailVotes div {
float:left;
font-size:12px;
margin-bottom:1px;
}
.espece {
font-size: 15px;
font-weight: bold;
margin-right:3px;
margin-bottom:10px;
}
 
.lignePonderation {
margin-top:4px;
margin-left:20px;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votes/details/DetailListeVotesDeterminationVue.ui.xml
New file
0,0 → 1,46
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:vues="urn:import:org.tela_botanica.del.client.composants.forum">
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
<ui:style src="detailListeVotesDeterminationVue.css" />
<g:HTMLPanel styleName="{style.conteneurTableauVotes}">
<g:HorizontalPanel> <g:HTMLPanel ui:field='titre' styleName="{style.espece}" />
<g:HTMLPanel ui:field='auteur' styleName="{style.auteur}" />
<g:Label text="{constants.dateReleve}" styleName="{style.dateLabel}"></g:Label>
<g:Label ui:field='date' styleName="{style.date}"></g:Label>
</g:HorizontalPanel>
<g:HTML><hr /></g:HTML>
<g:HTMLPanel styleName="{style.detailVotePour}">
<g:HTMLPanel styleName="{style.titreVotes}">
<g:Label>Votes Pour</g:Label>
<g:Label ui:field="scorePour">%</g:Label>
</g:HTMLPanel>
<g:HTMLPanel ui:field="detailVotePour" styleName="{style.detailVotes}">
</g:HTMLPanel>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.detailVoteContre}">
<g:HorizontalPanel styleName="{style.titreVotes} {style.titreVotesContre}">
<g:Label>Votes Contre</g:Label>
<g:Label ui:field="scoreContre">%</g:Label>
</g:HorizontalPanel>
<g:HTMLPanel ui:field="detailVoteContre" styleName="{style.detailVotes}">
</g:HTMLPanel>
</g:HTMLPanel>
<g:HTML><hr class="nettoyage"/></g:HTML>
<g:HTMLPanel ui:field="panneauChargement" styleName="{style.chargement}">
<g:Image url="./img/wait.gif"></g:Image>
</g:HTMLPanel>
<g:HTMLPanel ui:field="aucuneDonnees" visible="false"><g:Label text="{constants.aucunVoteEffectue}"></g:Label></g:HTMLPanel>
<g:HTML>
<br class="nettoyage" />
</g:HTML>
<g:HTML styleName="petit aide">Ces votes permettent de confirmer ou non une détermination proposée par un membre du réseau. <br />
Vous pouvez changer à tout moment votre vote à l'aide de <img src="./img/pouce_bas.png" /> ou <img src="./img/pouce_haut.png" />. <br />
</g:HTML>
<g:HTML styleName="{style.lignePonderation} petit">Une pondération s'opère pour le calcul des votes : vote en tant que membre identifié (3 points) / non identifié (1 point).</g:HTML>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votes/details/ligneVote.css
New file
0,0 → 1,9
.auteur {
padding-right:10px;
width:150px;
}
 
.colonne2:before {
content:(' - ');
}
 
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votes/details/DetailListeVotesDeterminationPresenteur.java
New file
0,0 → 1,70
package org.tela_botanica.del.client.composants.votes.details;
 
import java.util.HashMap;
 
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.modeles.VoteDetermination;
import org.tela_botanica.del.client.services.rest.VoteDeterminationServiceConcret;
import org.tela_botanica.del.client.services.rest.async.ListeVotesDeterminationCallback;
 
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class DetailListeVotesDeterminationPresenteur extends Presenteur {
 
public interface Vue extends IsWidget {
public void afficherVotes(PropositionDetermination propositionDetermination);
 
void stopChargement();
 
void startChargement();
 
public void afficherAucuneDonnees();
}
 
private Vue vue;
 
public DetailListeVotesDeterminationPresenteur(Vue vue) {
this.vue = vue;
}
 
public void go(HasWidgets container) {
container.add(vue.asWidget());
}
 
public void afficherVotes(final PropositionDetermination propositionDetermination) {
vue.startChargement();
VoteDeterminationServiceConcret voteService = new VoteDeterminationServiceConcret();
voteService.consulterVotesPourPropositionDetermination(propositionDetermination, new ListeVotesDeterminationCallback() {
 
@Override
public void surErreur(String messageErreur) {
Window.alert(messageErreur);
vue.stopChargement();
}
 
@Override
public void surRetour(HashMap<String, VoteDetermination> votesComplets) {
if (votesComplets != null && votesComplets.size() > 0) {
for (VoteDetermination voteDetermination : votesComplets.values()) {
voteDetermination.setPropositionDetermination(propositionDetermination);
}
 
propositionDetermination.setVotesDeterminations(votesComplets);
vue.afficherVotes(propositionDetermination);
vue.stopChargement();
} else {
vue.afficherAucuneDonnees();
vue.stopChargement();
}
}
});
}
 
@Override
protected void gererEvenements() {
// TODO Auto-generated method stub
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votes/moyennevotes/moyenne.css
New file
0,0 → 1,72
.moyenne {
background: none repeat scroll 0 0 #333333;
display: block;
margin-left: -5px;
margin-top: -7px;
padding: 5px;
width: 116px;
}
 
.petit {
font-size: 11px;
color: #AAA
}
 
.barreVote {
padding: 0 5px 0 5px
}
 
.validerVote {
font-size: 11px;
margin-left: 5px;
float:left
}
 
.zoneBoutonsVote {
position:absolute;
}
 
.annuler {
background: url("./img/cancel.png") no-repeat;
border: none;
padding-left: 16px;
padding-top: 16px;
margin-left: 5px;
cursor: pointer;
}
 
.zoneNoteGlobale {
background: none repeat scroll 0 0 #333333;
margin-left: 122px;
margin-top: -5px;
position: absolute;
white-space: nowrap;
width: 113px;
height:29px;
padding:5px;
}
 
.zoneFleur {
position:absolute;
top:5px;
margin-left:86px;
}
 
.protocole {
width:124px;
white-space:nowrap;
text-overflow:ellipsis;
overflow:hidden;
}
 
.zoneVoter {
background: none repeat scroll 0 0 #8EB533;
color: white;
font-size: 15px;
height: 29px;
margin-left: -5px;
margin-top: -18px;
padding: 10px 5px 0 39px;
position: absolute;
width: 82px;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votes/moyennevotes/MoyenneVoteVue.ui.xml
New file
0,0 → 1,28
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui' ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator" ui:generateLocales="default">
 
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary"/>
<ui:style src="moyenne.css" />
 
<g:HTMLPanel styleName="{style.moyenne}">
<g:HTMLPanel styleName="{style.zoneNoteGlobale}">
<g:Label styleName="petit enligne">Note générale</g:Label><g:Label ui:field="noteGenerale" styleName="petit enligne"/>
<g:Label ui:field="nbVotes" styleName="{style.petit}"/>
<g:HTMLPanel ui:field="zoneFleur" styleName="{style.zoneFleur}"></g:HTMLPanel>
</g:HTMLPanel>
<g:HorizontalPanel>
<g:Label styleName="{style.petit} {style.protocole}" ui:field="protocole" text="protocole"/>
</g:HorizontalPanel>
<g:Label ui:field="zoneVoter" styleName="{style.zoneVoter}">Votez !</g:Label>
<g:HorizontalPanel ui:field="zoneDeVote">
<g:FocusPanel ui:field="voter" styleName="{style.barreVote}"/>
<g:HTMLPanel ui:field="votePrisEnCompte"><g:Label text="{constants.votePrisEnCompte}"></g:Label></g:HTMLPanel>
<g:HTMLPanel ui:field="voteModifie"><g:Label text="{constants.voteModifie}"></g:Label></g:HTMLPanel>
<g:HTMLPanel ui:field="voteSupprime"><g:Label text="{constants.voteSupprime}"></g:Label></g:HTMLPanel>
<g:HTMLPanel styleName="{style.zoneBoutonsVote}">
<g:Button ui:field="boutonAnnuler" title="{constants.supprimerVote}" styleName="{style.annuler}"></g:Button>
</g:HTMLPanel>
</g:HorizontalPanel>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votes/moyennevotes/MoyenneVotePresenteur.java
New file
0,0 → 1,267
package org.tela_botanica.del.client.composants.votes.moyennevotes;
 
import java.util.Iterator;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.votefleur.VoteFleurPresenteur;
import org.tela_botanica.del.client.composants.votefleur.VoteFleurVue;
import org.tela_botanica.del.client.modeles.Image;
import org.tela_botanica.del.client.modeles.Protocole;
import org.tela_botanica.del.client.modeles.VoteProtocole;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.changementEtatUtilisateur.EvenementChangementEtatUtilisateur;
import org.tela_botanica.del.client.navigation.evenement.changementEtatUtilisateur.GestionnaireEvenementChangementEtatUtilisateur;
import org.tela_botanica.del.client.navigation.evenement.suppressioncommentaire.EvenementSuppressionCommentaire;
import org.tela_botanica.del.client.navigation.evenement.suppressioncommentaire.GestionnaireEvenementSuppressionCommentaire;
import org.tela_botanica.del.client.services.rest.VoteProtocoleService;
import org.tela_botanica.del.client.services.rest.async.AjoutVoteProtocoleCallback;
import org.tela_botanica.del.client.services.rest.async.VoteProtocoleCallback;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasMouseMoveHandlers;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class MoyenneVotePresenteur {
 
public interface Vue extends IsWidget {
public HasClickHandlers getBoutonAnnuler();
 
public HasClickHandlers getVotes();
 
public int getValeurVote();
 
public void afficherBoutonAnnuler();
 
public void masquerBoutonAnnuler();
 
public void afficherNbVotes();
 
public void masquerNbVotes();
 
public void reinitialiserVotes();
 
public void rafraichir(int moyenneVote, int nbVotes);
 
public void ajouterAuParent(HasWidgets composite);
 
public void afficherVotePrisEnCompte();
 
public HasWidgets getZoneFleur();
 
public HasText getZoneProtocole();
 
public void setNoteGenerale(int note);
 
public void afficherVoteModifie();
 
public HasMouseMoveHandlers getZoneVoter();
public void masquerZoneVoter();
 
public void setNoteGeneraleToolTip(double valeurVoteTotalPrecise);
 
void desactiverInteractionVote();
 
void activerInteractionVote();
 
void afficherVoteSupprime();
}
 
private Vue vue;
private Protocole protocole;
private Image image;
 
private int valeurVoteDefaut = -1;
private int valeurVoteUtilisateur = -1;
private int valeurVoteTotal = 0;
private double valeurVoteTotalPrecise = 0.0;
 
// TODO: on devrait passer un conteneur qui permet d'accéder à ces services
private VoteProtocoleService voteProtocoleService;
 
public MoyenneVotePresenteur(Image image, Protocole protocole, Vue vue,
VoteProtocoleService voteProtocoleService) {
this.vue = vue;
this.protocole = protocole;
this.image = image;
this.voteProtocoleService = voteProtocoleService;
 
String nomProtocole = protocole.getNom();
nomProtocole = nomProtocole.substring(0, 1).toUpperCase()
+ nomProtocole.substring(1).toLowerCase();
vue.getZoneProtocole().setText(nomProtocole);
}
 
public void go(HasWidgets composite) {
vue.ajouterAuParent(composite);
gererEvenements();
rafraichirVue();
}
 
public void gererEvenements() {
vue.getZoneVoter().addMouseMoveHandler(new MouseMoveHandler() {
@Override
public void onMouseMove(MouseMoveEvent event) {
vue.masquerZoneVoter();
}
});
vue.getVotes().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
valeurVoteUtilisateur = vue.getValeurVote();
enregistrerVote();
vue.afficherBoutonAnnuler();
vue.masquerNbVotes();
}
});
 
vue.getBoutonAnnuler().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
valeurVoteUtilisateur = valeurVoteDefaut;
vue.masquerBoutonAnnuler();
supprimerVote();
vue.afficherNbVotes();
vue.reinitialiserVotes();
}
});
BusEvenementiel.getInstance().addHandler(EvenementChangementEtatUtilisateur.TYPE, new GestionnaireEvenementChangementEtatUtilisateur() {
@Override
public void onModificationEtatUtilisateur(EvenementChangementEtatUtilisateur evenementChangementEtatUtilisateur) {
rafraichirVue();
}
});
}
 
public void setValeurVoteUtilisateur(int valeurVoteUtilisateur) {
this.valeurVoteUtilisateur = valeurVoteUtilisateur;
}
 
public void enregistrerVote() {
vue.desactiverInteractionVote();
final VoteProtocole voteProtocole = new VoteProtocole();
voteProtocole.setProtocole(this.protocole);
voteProtocole.setVote(valeurVoteUtilisateur);
String idContributeur = CacheClient.getInstance().getUtilisateur()
.getId();
voteProtocole.setContributeur(idContributeur);
//TODO: ceci devrait pouvoir être factorisé
if (image.utilisateurAVotePourProtocole(this.protocole.getId() + "",
idContributeur)) {
voteProtocole.setId(image.getVotesProtocoles(this.protocole.getId()+"").get(idContributeur).getId());
VoteProtocoleCallback vpc = new VoteProtocoleCallback() {
@Override
public void surRetour(Void objetRetour) {
image.ajouterVoteProtocole(voteProtocole);
rafraichirVue();
vue.afficherVoteModifie();
vue.activerInteractionVote();
}
};
voteProtocoleService.modifierVote(image.getIdImage(),
voteProtocole, vpc);
} else {
AjoutVoteProtocoleCallback vpc = new AjoutVoteProtocoleCallback() {
@Override
public void surRetour(String idVote) {
voteProtocole.setId(idVote);
image.ajouterVoteProtocole(voteProtocole);
rafraichirVue();
vue.afficherVotePrisEnCompte();
vue.activerInteractionVote();
}
};
voteProtocoleService.ajouterVote(image.getIdImage(), voteProtocole,
vpc);
}
}
public void supprimerVote() {
vue.desactiverInteractionVote();
final String idContributeur = CacheClient.getInstance().getUtilisateur()
.getId();
final VoteProtocole voteProtocole = image.getVotesProtocoles(protocole.getId()).get(idContributeur);
VoteProtocoleCallback vpc = new VoteProtocoleCallback() {
@Override
public void surRetour(Void objetRetour) {
// TODO: voir si l'on affiche un message en cas de succès ?
image.supprimerVoteProtocole(protocole.getId() + "", idContributeur);
rafraichirVue();
vue.afficherVoteSupprime();
vue.activerInteractionVote();
}
 
};
voteProtocoleService.supprimerVote(image.getIdImage(), voteProtocole, vpc);
}
 
public int getValeurVoteTotal() {
return valeurVoteTotal;
}
 
public IsWidget getVue() {
return vue;
}
 
private void rafraichirVue() {
valeurVoteTotal = calculerMoyenneVotesArrondie();
valeurVoteTotalPrecise = calculerMoyenneVotes();
VoteProtocole voteProtocole = image.getVotesProtocoles(
protocole.getId()).get(
CacheClient.getInstance().getUtilisateur().getId());
int voteUtilisateur = 0;
if (voteProtocole != null) {
voteUtilisateur = voteProtocole.getVote();
vue.masquerZoneVoter();
}
if(image.utilisateurAVotePourProtocole(protocole.getId()+"", CacheClient.getInstance().getUtilisateur().getId())) {
vue.afficherBoutonAnnuler();
}
 
VoteFleurPresenteur presenteurFleur = new VoteFleurPresenteur(
new VoteFleurVue());
presenteurFleur.setNote(valeurVoteTotal);
vue.setNoteGenerale(valeurVoteTotal);
vue.setNoteGeneraleToolTip(valeurVoteTotalPrecise);
presenteurFleur.go(vue.getZoneFleur());
vue.rafraichir(voteUtilisateur,
image.getVotesProtocoles(protocole.getId()).size());
}
public double calculerMoyenneVotes() {
double valeurVote = 0;
double nbVote = 0;
for (Iterator<String> iterator = image
.getVotesProtocoles(protocole.getId()).keySet().iterator(); iterator
.hasNext();) {
VoteProtocole imageCelValidationData = image.getVotesProtocoles(
protocole.getId()).get(iterator.next());
valeurVote += (double) imageCelValidationData.getVote() / 5;
nbVote++;
}
 
if (nbVote > 0) {
valeurVote /= nbVote;
valeurVote *= 5;
}
 
return valeurVote;
}
 
public int calculerMoyenneVotesArrondie() {
double valeurVote = calculerMoyenneVotes();
return (int) Math.round(valeurVote);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votes/moyennevotes/MoyenneVoteVue.java
New file
0,0 → 1,171
package org.tela_botanica.del.client.composants.votes.moyennevotes;
 
import org.cobogw.gwt.user.client.ui.Rating;
import org.tela_botanica.del.client.composants.votes.barrerepartition.InfoBulleAnim;
import org.tela_botanica.del.client.i18n.I18n;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasMouseMoveHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class MoyenneVoteVue extends Composite implements MoyenneVotePresenteur.Vue {
 
// Annotation can be used to change the name of the associated xml file
// @UiTemplate("MoyenneVoteVue.ui.xml")
interface MyUiBinder extends UiBinder<Widget, MoyenneVoteVue> {
}
 
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
private Rating votes;
private int valeurOrigine;
private InfoBulleAnim animerVotePrisEnCompte;
private InfoBulleAnim animerVoteModifie;
private InfoBulleAnim animerVoteSupprime;
@UiField
FocusPanel voter;
 
@UiField
Panel votePrisEnCompte, voteModifie, voteSupprime, zoneFleur;
@UiField
Label nbVotes, protocole, noteGenerale;
 
@UiField
Button boutonAnnuler;
@UiField
Label zoneVoter;
public MoyenneVoteVue() {
initWidget(uiBinder.createAndBindUi(this));
votes = new Rating(0, 5);
votes.setReadOnly(false);
voter.add(votes);
masquerBoutonAnnuler();
votePrisEnCompte.setVisible(false);
animerVotePrisEnCompte = new InfoBulleAnim(votePrisEnCompte);
animerVoteModifie = new InfoBulleAnim(voteModifie);
animerVoteSupprime = new InfoBulleAnim(voteSupprime);
}
public HasClickHandlers getBoutonAnnuler() {
return boutonAnnuler;
}
public HasText getNbVotes() {
return nbVotes;
}
public HasClickHandlers getVotes() {
return votes;
}
public int getValeurVote() {
return votes.getValue();
}
 
public void afficherBoutonAnnuler() {
boutonAnnuler.setVisible(true);
}
public void masquerBoutonAnnuler() {
boutonAnnuler.setVisible(false);
}
public void afficherNbVotes () {
nbVotes.setVisible(true);
}
public void masquerNbVotes () {
nbVotes.setVisible(false);
}
public void reinitialiserVotes() {
votes.setValue(valeurOrigine);
}
public void rafraichir(int voteUtilisateur, int nombreVotes) {
valeurOrigine = voteUtilisateur;
String valeurVote = nombreVotes+" "+I18n.getVocabulary().nbVotes();
if (nombreVotes > 1) {
valeurVote += "s";
}
nbVotes.setText(valeurVote);
votes.setValue(voteUtilisateur);
}
 
@Override
public void ajouterAuParent(HasWidgets composite) {
composite.add(this);
}
@Override
public void afficherVotePrisEnCompte() {
votePrisEnCompte.setStyleName("votePrisEnCompteOui");
animerVotePrisEnCompte.run(2000);
}
public HasWidgets getZoneFleur() {
return zoneFleur;
}
public HasText getZoneProtocole() {
return protocole;
}
public void setNoteGenerale(int note) {
noteGenerale.setText(" : " + note);
}
@Override
public void setNoteGeneraleToolTip(double valeurVoteTotalPrecise) {
double valeurArrondie = (double)Math.round(valeurVoteTotalPrecise * 1000) / 1000;
zoneFleur.setTitle(I18n.getVocabulary().votesMoyennePrecise()+valeurArrondie);
}
public void afficherVoteModifie() {
voteModifie.setStyleName("votePrisEnCompteOui");
animerVoteModifie.run(2000);
}
@Override
public void afficherVoteSupprime() {
voteSupprime.setStyleName("voteSupprime");
animerVoteSupprime.run(2000);
}
public HasMouseMoveHandlers getZoneVoter() {
return zoneVoter;
}
public void masquerZoneVoter() {
zoneVoter.setVisible(false);
}
@Override
public void desactiverInteractionVote() {
votes.setReadOnly(true);
boutonAnnuler.setEnabled(false);
boutonAnnuler.addStyleName("elementMasque");
votes.addStyleName("elementMasque");
}
@Override
public void activerInteractionVote() {
votes.setReadOnly(false);
boutonAnnuler.setEnabled(true);
boutonAnnuler.removeStyleName("elementMasque");
votes.removeStyleName("elementMasque");
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votes/barrerepartition/barreRepartition.css
New file
0,0 → 1,93
.conteneurBarre {
width:130px;
display: inline;
}
 
.conteneurBarreOuiNon {
display: inline;
float: right;
}
 
.labelTaxon {
float: left;
margin-right: 5px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 190px;
margin-bottom: 5px;
text-align:left;
}
 
.barre {
width:50px;
height:15px;
background:#BBB;
float:left;
margin-right:2px;
margin-left:2px;
display: inline;
float:left;
}
 
.pourcentage {
position:absolute;
font-size:10px;
width:48px;
text-align:center;
}
 
.barreOui {
background:#8EB533;
padding-bottom:15px;
}
 
.barreNon {
background:#f06a6a;
padding-bottom:15px;
}
 
.boutonOui, .boutonNon {
text-align:center;
color:white;
line-height:1em;
font-size:15px;
font-weight:bold;
cursor:pointer;
float:left;
background:#AAA;
}
 
.boutonOui {
width:9%;
height:15px;
width:30px;
border-radius:0 2px 2px 0;
background-image: url("img/pouce_haut.png");
}
 
.boutonOui:hover {
background-image: url("img/pouce_haut_hover.png");
}
 
.boutonNon:hover {
background-image: url("img/pouce_bas_hover.png");
}
 
.boutonNon {
width:9%;
height:15px;
width:30px;
border-radius:2px 0 0 2px;
background-image: url("img/pouce_bas.png");
margin-right:5px;
}
 
.score {
font-size:13px;
color:#DDD;
font-weight:bold;
margin-right:10px;
width:28px;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votes/barrerepartition/InfoBulleAnim.java
New file
0,0 → 1,30
package org.tela_botanica.del.client.composants.votes.barrerepartition;
 
import com.google.gwt.animation.client.Animation;
import com.google.gwt.user.client.ui.Widget;
 
public class InfoBulleAnim extends Animation{
 
private Widget widget;
public InfoBulleAnim(Widget widget) {
this.widget = widget;
widget.setVisible(false);
}
@Override
protected void onStart() {
super.onStart();
widget.setVisible(true);
}
@Override
protected void onUpdate(double progress) {
}
@Override
protected void onComplete() {
super.onComplete();
widget.setVisible(false);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votes/barrerepartition/BarreRepartitionVoteVue.ui.xml
New file
0,0 → 1,16
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
<ui:style src="barreRepartition.css" />
<g:HTMLPanel styleName="{style.conteneurBarre}">
<g:Label styleName="gauche {style.score}" ui:field="score">--</g:Label>
<g:Label ui:field="nomTaxon" styleName="{style.labelTaxon} labelTaxon" />
<g:HTMLPanel styleName="{style.conteneurBarreOuiNon}">
<g:PushButton ui:field="boutonNon" text=" " styleName="{style.boutonNon}"/>
<g:PushButton ui:field="boutonOui" text=" " styleName="{style.boutonOui}"/>
<g:HTMLPanel ui:field="votePrisEnCompte"><g:Label text="{constants.votePrisEnCompte}"></g:Label></g:HTMLPanel>
<g:HTMLPanel ui:field="voteModifie"><g:Label text="{constants.voteModifie}"></g:Label></g:HTMLPanel>
</g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votes/barrerepartition/BarreRepartitionVotePresenteur.java
New file
0,0 → 1,169
package org.tela_botanica.del.client.composants.votes.barrerepartition;
 
import java.util.Date;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.modeles.MoyenneVote;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.modeles.VoteDetermination;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.voteDetermination.EvenementVoteDetermination;
import org.tela_botanica.del.client.services.CalculVoteDeterminationService;
import org.tela_botanica.del.client.services.rest.VoteDeterminationService;
import org.tela_botanica.del.client.services.rest.async.AjoutVoteDeterminationCallback;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class BarreRepartitionVotePresenteur {
 
public interface Vue extends IsWidget {
public void afficherVotes(int pourcentage, String NomTaxon, String auteur, boolean estPropositionInitiale);
public HasClickHandlers getBoutonOui();
public HasClickHandlers getBoutonNon();
public void desactiverBoutons();
public void activerBoutons();
public void setVoteOuiEffectue();
public void setVoteNonEffectue();
public void afficherVotePrisEnCompte(boolean b);
public void afficherVoteModifie(boolean b);
public void toggleNomEspece();
public HasText getScore();
}
 
private Vue vue;
private MoyenneVote moyenneVote;
 
// TODO: classe conteneur qui est passé en paramètre au constructeur
private VoteDeterminationService voteDeterminationService;
 
public BarreRepartitionVotePresenteur(Vue vue, VoteDeterminationService voteDeterminationService) {
this.vue = vue;
this.voteDeterminationService = voteDeterminationService;
gererEvenements();
}
 
public void go(HasWidgets container) {
container.add(vue.asWidget());
}
 
public void afficherVotes(MoyenneVote moyenneVote) {
this.moyenneVote = moyenneVote;
int score = moyenneVote.getScore();
String intitule = moyenneVote.getIntituleAssocie();
PropositionDetermination proposition = moyenneVote.getPropositionAssociee();
boolean estPropositionInitiale = false;
if (proposition != null) {
estPropositionInitiale = moyenneVote.getPropositionAssociee().estPropositionInitiale();
}
vue.afficherVotes(score, intitule, moyenneVote.getPropositionAssociee().getAuteur(), estPropositionInitiale);
afficherValeurVoteUtilisateur();
}
public void afficherValeurVoteUtilisateur() {
String idUtilisateur = CacheClient.getInstance().getUtilisateur().getId();
if(moyenneVote.getPropositionAssociee().utilisateurAVotePourDetermination(idUtilisateur)) {
boolean valeurVote = (moyenneVote.getPropositionAssociee().getVotesDeterminations().get(idUtilisateur).getVote() == 1) ? true : false;
if(valeurVote) {
vue.setVoteOuiEffectue();
} else {
vue.setVoteNonEffectue();
}
}
}
 
public Vue getBarreRepartitionVoteVue() {
return vue;
}
 
public MoyenneVote getMoyenneVote() {
return moyenneVote;
}
 
public void gererEvenements() {
 
vue.getBoutonOui().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
voter(true);
}
});
 
vue.getBoutonNon().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
voter(false);
}
});
}
 
private void surVoteDetermination(final VoteDetermination vd) {
if (vd.getPropositionDetermination().equals(moyenneVote.getPropositionAssociee())) {
AjoutVoteDeterminationCallback vdc = new AjoutVoteDeterminationCallback() {
 
@Override
public void surErreur(String messageErreur) {
Window.alert(messageErreur);
vue.activerBoutons();
}
 
@Override
public void surRetour(Void objetRetour) {
moyenneVote.getPropositionAssociee().ajouterVoteDetermination(vd);
moyenneVote = CalculVoteDeterminationService.calculerVoteDetermination(moyenneVote.getPropositionAssociee());
afficherVotes(moyenneVote);
vue.activerBoutons();
boolean valeurVote = (vd.getVote() == 1) ? true : false;
if(valeurVote) {
vue.setVoteOuiEffectue();
} else {
vue.setVoteNonEffectue();
}
// l'évènement n'est lancé que si le vote est validé
BusEvenementiel.getInstance().fireEvent(new EvenementVoteDetermination(vd));
}
};
 
if (moyenneVote.getPropositionAssociee().utilisateurAVotePourDetermination(vd.getContributeur())) {
voteDeterminationService.modifierVote(vd, vdc);
vue.afficherVoteModifie(vd.getVote()==1);
} else {
voteDeterminationService.ajouterVote(vd, vdc);
vue.afficherVotePrisEnCompte(vd.getVote()==1);
}
}
}
public void toggleNomEspece() {
vue.toggleNomEspece();
}
 
public void voter(boolean oui) {
 
VoteDetermination vd = new VoteDetermination();
vd.setPropositionDetermination(moyenneVote.getPropositionAssociee());
vd.setContributeur(CacheClient.getInstance().getUtilisateur().getId());
vd.setDate(new Date());
 
int valeurVote = oui ? 1 : 0;
vd.setVote(valeurVote);
vd.setId(CacheClient.getInstance().getUtilisateur().getId());
 
if (oui) {
vue.setVoteOuiEffectue();
} else {
vue.setVoteNonEffectue();
}
vue.desactiverBoutons();
surVoteDetermination(vd);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votes/barrerepartition/BarreRepartitionVoteVue.java
New file
0,0 → 1,128
package org.tela_botanica.del.client.composants.votes.barrerepartition;
 
import org.tela_botanica.del.client.i18n.I18n;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.PushButton;
import com.google.gwt.user.client.ui.Widget;
 
public class BarreRepartitionVoteVue extends Composite implements BarreRepartitionVotePresenteur.Vue {
 
interface MyUiBinder extends UiBinder<Widget, BarreRepartitionVoteVue> {
}
 
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
private InfoBulleAnim animerVotePrisEnCompte;
private InfoBulleAnim animerVoteModifie;
 
@UiField
Label nomTaxon, score;
@UiField
Panel votePrisEnCompte, voteModifie;
@UiField
PushButton boutonOui, boutonNon;
 
public BarreRepartitionVoteVue() {
initWidget(uiBinder.createAndBindUi(this));
votePrisEnCompte.setVisible(false);
voteModifie.setVisible(false);
animerVotePrisEnCompte = new InfoBulleAnim(votePrisEnCompte);
animerVoteModifie = new InfoBulleAnim(voteModifie);
boutonOui.setTitle(I18n.getVocabulary().JeSuisDaccord());
boutonNon.setTitle(I18n.getVocabulary().JeNeSuisPasDaccord());
}
 
@Override
public void afficherVotes(int pourcentage, String nomTaxon, String auteur, boolean estPropositionInitiale) {
this.nomTaxon.setText(nomTaxon);
this.nomTaxon.setTitle(nomTaxon + " - " + auteur);
if (pourcentage > 0) {
score.setText(String.valueOf(pourcentage));
}
if (estPropositionInitiale) {
this.nomTaxon.addStyleName("propositionInitiale");
}
}
 
@Override
public HasClickHandlers getBoutonOui() {
return boutonOui;
}
 
@Override
public HasClickHandlers getBoutonNon() {
return boutonNon;
}
 
@Override
public void setVoteOuiEffectue() {
boutonOui.setEnabled(false);
boutonOui.addStyleName("boutonVoteOuiDesactive");
boutonNon.setEnabled(true);
boutonNon.removeStyleName("boutonVoteNonDesactive");
boutonOui.setTitle("");
boutonNon.setTitle(I18n.getVocabulary().JeNeSuisPasDaccord());
}
 
@Override
public void setVoteNonEffectue() {
boutonOui.setEnabled(true);
boutonOui.removeStyleName("boutonVoteOuiDesactive");
boutonNon.setEnabled(false);
boutonNon.addStyleName("boutonVoteNonDesactive");
boutonOui.setTitle(I18n.getVocabulary().JeSuisDaccord());
boutonNon.setTitle("");
}
 
@Override
public void afficherVotePrisEnCompte(boolean voteOui) {
if (voteOui) {
votePrisEnCompte.removeStyleName("votePrisEnCompteNon");
votePrisEnCompte.setStyleName("votePrisEnCompteOui");
} else {
votePrisEnCompte.removeStyleName("votePrisEnCompteOui");
votePrisEnCompte.setStyleName("votePrisEnCompteNon");
}
animerVotePrisEnCompte.run(2000);
}
 
public void afficherVoteModifie(boolean voteOui) {
if (voteOui) {
voteModifie.removeStyleName("votePrisEnCompteNon");
voteModifie.setStyleName("votePrisEnCompteOui");
} else {
voteModifie.removeStyleName("votePrisEnCompteOui");
voteModifie.setStyleName("votePrisEnCompteNon");
}
animerVoteModifie.run(2000);
}
 
@Override
public void desactiverBoutons() {
boutonNon.setEnabled(false);
boutonOui.setEnabled(false);
}
 
@Override
public void activerBoutons() {
boutonNon.setEnabled(true);
boutonOui.setEnabled(true);
}
 
@Override
public void toggleNomEspece() {
nomTaxon.setVisible(!nomTaxon.isVisible());
}
@Override
public HasText getScore() {
return score;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/preferences/preferences.css
New file
0,0 → 1,57
.conteneurPreferences {
z-index: 1500;
padding: 30px;
padding-right: 21px;
padding-top: 20px;
background: white;
width: 370px;
margin: 0 auto;
margin-top: 75px;
padding-bottom:50px;
}
 
.messageTemporaire {
font-style: italic;
}
 
.boutonSauvegarder:hover {
background-color: #AAA
}
 
.colonneGauche,.colonneDroite {
width: 300px;
}
 
.colonneGauche {
padding-right: 30px
}
 
.colonneGauche select {
width: 100%
}
 
.colonneGauche input {
width: 95%
}
 
.boutonSauvegarder {
border: solid 1px #AAA;
cursor: pointer;
float: left;
margin-top: 10px;
margin-bottom: 5px;
margin-right: 5px;
float: right;
background: url(./img/add.png) no-repeat 5px 7px #DDD;
padding: 5px;
padding-left: 25px;
cursor: pointer
}
 
.zoneMailsMesObs {
margin-bottom: 10px;
}
 
.zoneMailsToutesObs {
margin-bottom: 10px;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/preferences/PreferencesVue.ui.xml
New file
0,0 → 1,29
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary"/>
<ui:style src="preferences.css" />
<g:HTMLPanel styleName="{style.conteneurPreferences}">
<g:Label text="{constants.preferences}" styleName="titre"/>
<g:Label styleName="petit {style.messageTemporaire}" text="{constants.messageTemporaireMails}" />
<g:HTML><br /></g:HTML>
<g:VerticalPanel ui:field="panneauChargement">
<g:Image url="./img/wait.gif"></g:Image>
</g:VerticalPanel>
<g:HTMLPanel styleName="{style.colonneGauche}" ui:field="conteneurChamps">
<g:HTMLPanel styleName="{style.zoneMailsMesObs}">
<g:Label text="{constants.recevoirMailsMesObs}" styleName="petit" />
<g:CheckBox ui:field="recevoirMailsMesObs"/>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.zoneMailsToutesObs}">
<g:Label text="{constants.recevoirMailsToutesObs}" styleName="petit" />
<g:CheckBox ui:field="recevoirMailsToutesObs"/>
</g:HTMLPanel>
<g:Button text="{constants.sauvegarder}" ui:field="boutonSauvegarderPreferences" styleName="{style.boutonSauvegarder} arrondi"/>
</g:HTMLPanel>
</g:HTMLPanel>
 
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/preferences/PreferencesPresenteur.java
New file
0,0 → 1,89
package org.tela_botanica.del.client.composants.preferences;
 
import java.util.HashMap;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.changementPreferences.EvenementChangementPreferences;
import org.tela_botanica.del.client.services.rest.PreferencesService;
import org.tela_botanica.del.client.services.rest.async.ListePreferencesCallback;
import org.tela_botanica.del.client.services.rest.async.ModificationPreferencesCallback;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class PreferencesPresenteur extends Presenteur {
private Vue vue;
private PreferencesService preferencesService;
private HashMap<String, String> preferences = null;
public interface Vue extends IsWidget {
public void afficherMessageChargement();
public void cacherMessageChargement();
public String getValeurRecevoirMailsMesObs();
public String getValeurRecevoirMailsToutesObs();
public void setValeurRecevoirMailsMesObs(boolean valeur);
public void setValeurRecevoirMailsToutesObs(boolean valeur);
public HasClickHandlers getBoutonSauvegarder();
}
public PreferencesPresenteur(Vue vue, PreferencesService preferencesService) {
this.vue = vue;
this.preferencesService = preferencesService;
gererEvenements();
}
 
@Override
public void go(HasWidgets composite) {
preferences = CacheClient.getInstance().getUtilisateur().getPreferences();
if (preferences == null) {
preferencesService.chargerPreferences(CacheClient.getInstance().getUtilisateur(), new ListePreferencesCallback() {
@Override
public void surRetour(java.util.HashMap<String, String> objetRetour) {
preferences = objetRetour;
CacheClient.getInstance().getUtilisateur().setPreferences(objetRetour);
affecterValeursChamps(preferences);
vue.cacherMessageChargement();
}
});
} else {
vue.cacherMessageChargement();
affecterValeursChamps(preferences);
}
composite.add(vue.asWidget());
}
private void affecterValeursChamps(HashMap<String, String> preferences) {
vue.setValeurRecevoirMailsMesObs(getPreferenceBool(preferences.get("mail_notification_mes_obs")));
vue.setValeurRecevoirMailsToutesObs(getPreferenceBool(preferences.get("mail_notification_toutes_obs")));
}
private boolean getPreferenceBool(String valeur) {
return (valeur.equals("1")) ? true : false;
}
 
@Override
protected void gererEvenements() {
vue.getBoutonSauvegarder().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
vue.afficherMessageChargement();
preferences.put("mail_notification_mes_obs", vue.getValeurRecevoirMailsMesObs());
preferences.put("mail_notification_toutes_obs", vue.getValeurRecevoirMailsToutesObs());
preferencesService.modifierPreferences(CacheClient.getInstance().getUtilisateur(), preferences, new ModificationPreferencesCallback() {
@Override
public void surRetour(String objetRetour) {
vue.cacherMessageChargement();
BusEvenementiel.getInstance().fireEvent(new EvenementChangementPreferences());
}
});
}
});
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/preferences/PreferencesVue.java
New file
0,0 → 1,73
package org.tela_botanica.del.client.composants.preferences;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class PreferencesVue extends Composite implements PreferencesPresenteur.Vue {
@UiField
Panel panneauChargement, conteneurChamps;
@UiField
public CheckBox recevoirMailsMesObs;
@UiField
public CheckBox recevoirMailsToutesObs;
@UiField
public Button boutonSauvegarderPreferences;
 
interface PreferencesVueUIiBinder extends UiBinder<Widget, PreferencesVue> {
};
 
PreferencesVueUIiBinder uiBinder = GWT.create(PreferencesVueUIiBinder.class);
 
public PreferencesVue() {
initWidget(uiBinder.createAndBindUi(this));
}
@Override
public void afficherMessageChargement() {
panneauChargement.setHeight(this.getOffsetHeight()+"px");
panneauChargement.setVisible(true);
conteneurChamps.setVisible(false);
}
 
@Override
public void cacherMessageChargement() {
panneauChargement.setVisible(false);
conteneurChamps.setVisible(true);
}
@Override
public void setValeurRecevoirMailsMesObs(boolean valeur) {
recevoirMailsMesObs.setValue(valeur);
}
@Override
public void setValeurRecevoirMailsToutesObs(boolean valeur) {
recevoirMailsToutesObs.setValue(valeur);
}
@Override
public String getValeurRecevoirMailsMesObs() {
return (recevoirMailsMesObs.getValue()) ? "1" : "0";
}
@Override
public String getValeurRecevoirMailsToutesObs() {
return (recevoirMailsToutesObs.getValue()) ? "1" : "0";
}
 
@Override
public HasClickHandlers getBoutonSauvegarder() {
return boutonSauvegarderPreferences;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/metadonnees/metadonnees.css
New file
0,0 → 1,97
.metadonnees {
width:180px;
overflow:hidden;
}
 
.metadonnees .donnee {
display: inline-block;
}
 
.labelNomRetenu {
display: none
}
 
.nomRetenu {
display: none;
font-size: 15px;
color: #598000;
width: 170px;
overflow: auto;
white-space: nowrap;
text-overflow: ellipsis;
}
 
.lieuDuReleve {
display: block;
}
 
.zoneFamille {
display: none;
margin-top: 1em;
}
 
.zoneReferentiel {
margin-top: 1em;
}
 
.labelReferentiel {
display: inline;
}
 
.zoneFamille div {
display: inline;
}
 
.zoneLocalite {
margin-top:5px;
}
 
.zoneLocalite div {
}
 
.zoneLieuDit {
display: inline;
}
 
.zoneStation {
display: inline;
}
 
.zoneMilieu {
display: inline;
}
 
.zoneMilieu div {
display: inline
}
 
.zoneCommentaire {
margin-top:5px;
}
 
.zoneCommentaire div {
}
 
.commentaire {
display: block;
height: 94px;
overflow: auto;
text-overflow: ellipsis
}
 
.zoneDateReleve {
}
 
.zoneAuteur {
}
 
.zoneAuteur div {
display: inline
}
 
.zoneDate {
display: none
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/metadonnees/metadonneesEnLigne.css
New file
0,0 → 1,60
.metadonnees {
width:100%;
}
 
.metadonnees div {
float:left;
padding:0 3px 0 0;
}
 
.zoneReferentiel {
margin-top: 1em;
}
 
.famille {
display:none;
}
 
.nomCommun {}
.nomCommun:before {
content:"(";
}
.nomCommun:after {
content:")";
}
 
.metaPart1 {
clear:both;
font-size:15px;
max-width:850px;
}
 
.metaPart2 {
clear:both;
color:#777;
max-width:850px;
}
 
.metaPart3 {
display:none;
max-width:850px;
}
 
.lieuDit:after {
content:", ";
}
 
.zoneLieu:before {
content:" / ";
}
 
.espece {
color: #454341;
font-size: 18px;
margin-top: -3px;
}
 
.label {
font-size:12px;
margin-top:3px;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/metadonnees/MetadonneesVue.ui.xml
New file
0,0 → 1,94
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui' ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
ui:generateLocales="default">
<ui:with field='res'
type='org.tela_botanica.del.client.resources.Ressources' />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
 
<ui:style src="metadonnees.css" />
<g:HTMLPanel styleName="{style.metadonnees}">
<!-- Date du relevé -->
<g:HTMLPanel ui:field="zoneDateReleve" styleName="{style.zoneDateReleve}">
<g:InlineLabel styleName="petit gris" text="{constants.observeLe}" />
<g:InlineLabel ui:field="dateReleve" styleName="{style.donnee}"/>
</g:HTMLPanel>
<!-- Nom retenu -->
<g:HTMLPanel ui:field="zoneNomRetenu">
<g:Label styleName="petit gris {style.labelNomRetenu}" text="{constants.nomRetenu}" />
<g:Label ui:field="nomRetenu" styleName="{style.nomRetenu} gras" />
</g:HTMLPanel>
 
<!-- Nom commun -->
<g:HTMLPanel ui:field="zoneNomCommun">
<g:Label styleName="petit gris" text="{constants.nomCommun}" />
<g:Label ui:field="nomCommun" />
</g:HTMLPanel>
<!-- Référentiel -->
<g:HTMLPanel ui:field="zoneReferentiel" styleName="{style.zoneReferentiel}">
<g:Label styleName="petit gris {style.labelReferentiel}" text="{constants.referentiel}" />
<g:Label ui:field="referentiel" styleName="{style.donnee}"/>
</g:HTMLPanel>
 
<!-- Famille -->
<g:HTMLPanel ui:field="zoneFamille" styleName="{style.zoneFamille}">
<g:Label styleName="petit gris" text="{constants.metadonneeFamille}" />
<g:Label ui:field="famille" styleName="{style.donnee}"/>
</g:HTMLPanel>
 
<!-- Lieu -->
<g:HTMLPanel ui:field="zoneLocalite" styleName="{style.zoneLocalite}">
<g:Label styleName="petit gris {style.lieuDuReleve}" text="{constants.lieuDuReleve}" />
<g:Label ui:field="localite" styleName="{style.donnee}"/>
</g:HTMLPanel>
 
<!-- Lieu-dit -->
<g:HTMLPanel ui:field="zoneLieuDit" styleName="{style.zoneLieuDit}">
<g:HTML ui:field="lieuDit"/>
</g:HTMLPanel>
<!-- Station -->
<g:HTMLPanel ui:field="zoneStation" styleName="{style.zoneStation}">
<g:Label ui:field="station"/>
</g:HTMLPanel>
 
<!-- Milieu -->
<g:HTMLPanel ui:field="zoneMilieu" styleName="{style.zoneMilieu}">
<g:Label ui:field="milieu"/>
</g:HTMLPanel>
 
<!-- Commentaire -->
<g:HTMLPanel ui:field="zoneCommentaire" styleName="{style.zoneCommentaire}">
<g:Label styleName="petit gris" text="{constants.commentaire}" />
<g:Label ui:field="commentaire" styleName="{style.commentaire}"/>
</g:HTMLPanel>
 
 
<!-- Publié par -->
<g:HTMLPanel ui:field="zoneAuteur" styleName="{style.zoneAuteur}">
<g:Label styleName="petit gris" text="{constants.par}" />
<g:Label ui:field="auteur" styleName="{style.donnee}" title="Voir le profil" />
</g:HTMLPanel>
 
<!-- Date de transmission -->
<g:HTMLPanel ui:field="zoneDate" styleName="{style.zoneDate}">
<g:InlineLabel styleName="petit gris" text="{constants.dateTransmission}" />
<g:InlineLabel ui:field="dateTransmission" styleName="{style.donnee}"/>
</g:HTMLPanel>
 
<!-- Mots-clés/Tag -->
<g:HTMLPanel ui:field="zoneMotsClefs">
<g:Label styleName="petit gris" text="{constants.motsClefs}" />
<g:Label ui:field="motsClefs" styleName="{style.donnee}"/>
</g:HTMLPanel>
 
<g:Label ui:field="numNomenclatural" />
<g:Anchor ui:field="lienIdentiplante" text="{constants.signalerIdentification}" styleName="labelLien"/>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/metadonnees/MetadonneesEnLigneVue.ui.xml
New file
0,0 → 1,68
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui' ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
ui:generateLocales="default">
<ui:with field='res'
type='org.tela_botanica.del.client.resources.Ressources' />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
 
<ui:style src="metadonneesEnLigne.css" />
<g:HTMLPanel styleName="{style.metadonnees}">
 
<g:HTMLPanel styleName="{style.metaPart1}">
<g:HTMLPanel styleName="{style.espece}">
<g:Label ui:field="nomRetenu" title="Voir la fiche eFlore" />
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.nomCommun}">
<g:Label ui:field="nomCommun" />
</g:HTMLPanel>
<g:HTMLPanel>
<g:Label text="référentiel" styleName="{style.label}" />
<g:Label ui:field="referentiel" />
</g:HTMLPanel>
<g:HTMLPanel>
<g:Label text="observée à" styleName="{style.label}" />
<g:Label ui:field="localite" />
</g:HTMLPanel>
<g:HTMLPanel>
<g:Label text="par" styleName="{style.label}" />
<g:Label ui:field="auteur" title="Voir le profil" />
</g:HTMLPanel>
<g:HTMLPanel>
<g:Label text="le" styleName="{style.label}" />
<g:InlineLabel ui:field="dateReleve" />
</g:HTMLPanel>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.metaPart2}">
<g:HTMLPanel styleName="{style.zoneLieu}">
<g:Label text="Lieu :" />
<g:HTML ui:field="lieuDit" styleName="{style.lieuDit}" title="{constants.lieuDit}"/>
<g:Label ui:field="station" title="{constants.station}" />
</g:HTMLPanel>
<g:HTMLPanel >
<g:Label text="Milieu :" />
<g:Label ui:field="milieu"/>
</g:HTMLPanel>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.metaPart3}">
<g:HTMLPanel styleName="{style.famille}">
<g:Label ui:field="famille" />
</g:HTMLPanel>
<g:HTMLPanel>
<g:Label ui:field="motsClefs" />
</g:HTMLPanel>
<g:HTMLPanel>
<g:Label ui:field="numNomenclatural" />
</g:HTMLPanel>
 
<g:HTMLPanel>
<g:Label ui:field="commentaire" />
</g:HTMLPanel>
<g:HTMLPanel>
<g:InlineLabel ui:field="dateTransmission" />
</g:HTMLPanel>
</g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/metadonnees/MetadonneesPresenteur.java
New file
0,0 → 1,313
package org.tela_botanica.del.client.composants.metadonnees;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.modeles.InformationsRecherche;
import org.tela_botanica.del.client.modeles.ModeRecherche;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.detailsimage.EvenementRechercheImage;
import org.tela_botanica.del.client.navigation.evenement.rechercheobservation.EvenementRechercheObservation;
import org.tela_botanica.del.client.utils.UtilitairesServiceResultat;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class MetadonneesPresenteur extends Presenteur {
 
public abstract interface Vue extends IsWidget {
public HasText getNomRetenu();
 
public HasClickHandlers getLienNomRetenu();
 
public HasText getNomCommun();
 
public HasText getFamille();
 
public HasText getLocalite();
 
public HasText getLieuDit();
 
public HasText getMilieu();
 
public HasText getCommentaire();
 
public HasText getAuteur();
 
public HasText getDateTransmission();
 
public HasText getMotsClefs();
 
public HasText getNumNomenclatural();
 
public HasText getDateReleve();
 
public HasClickHandlers getLienFamille();
 
public HasClickHandlers getLienAuteur();
 
public HasClickHandlers getLienDateTransmission();
 
public HasClickHandlers getLienDateReleve();
 
public HasClickHandlers getLienLocalite();
 
public HasClickHandlers getLienMotsClefs();
 
public HasClickHandlers getLienNumNomenclatural();
 
public HasClickHandlers getLienNomCommun();
 
public HasClickHandlers getLienMilieu();
 
public HasClickHandlers getLienCommentaire();
public void setStation(String station) ;
public void masquerChampsVides();
public void activerLiens();
public void activerLienAuteur();
public void activerLienNomRetenu();
public void setLienIdentiplante(String id);
 
void desactiverLienAuteur();
 
public HasText getReferentiel();
}
 
private Vue vue;
private Observation observation;
private ModeRecherche modeRecherche;
private boolean avecLiens;
public MetadonneesPresenteur(Vue vue, Observation observation, ModeRecherche modeRecherche, boolean avecLiens) {
this.vue = vue;
this.modeRecherche = modeRecherche;
setObservation(observation);
this.avecLiens = avecLiens;
}
 
public void setObservation(Observation observation) {
this.observation = observation;
}
 
public void chargerMetaDonnees() {
vue.getNomRetenu().setText(observation.getNomRetenu());
vue.getNomCommun().setText(observation.getNomCommun());
vue.getReferentiel().setText(observation.getReferentiel());
vue.getFamille().setText(observation.getFamille());
vue.getLocalite().setText(observation.getLocaliteAvecIdFormatee());
vue.getLieuDit().setText(observation.getLieuDit());
vue.setStation(observation.getStation());
vue.getMilieu().setText(observation.getMilieu());
vue.getCommentaire().setText(observation.getCommentaire());
vue.getAuteur().setText(observation.getAuteur());
vue.getDateTransmission().setText(formaterDate(observation.getDateTransmission()));
vue.getDateReleve().setText(formaterDate(observation.getDateReleve()));
vue.masquerChampsVides();
}
 
public String formaterDate(String dateNonFormatee) {
try {
String dateFormatee = DateTimeFormat.getFormat("dd/MM/yyyy").format(UtilitairesServiceResultat.parserDateObservation(dateNonFormatee));
dateFormatee = (dateFormatee == "01/01/1970") ? "???" : dateFormatee ;
return dateFormatee;
} catch (IllegalArgumentException e) {
return "";
}
}
@Override
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
chargerMetaDonnees();
//if (this.avecLiens) {
gererEvenements();
//}
}
 
@Override
protected void gererEvenements() {
if (this.avecLiens) {
if(!observation.getIdAuteur().equals("0")) {
vue.getLienAuteur().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent arg0) {
InformationsRecherche informationsRecherche = new InformationsRecherche();
informationsRecherche.setAuteur(vue.getAuteur().getText());
setInfosRechercheEnCacheEtLancerEvenement(informationsRecherche);
History.fireCurrentHistoryState();
}
});
}
vue.getLienDateReleve().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent arg0) {
InformationsRecherche informationsRecherche = new InformationsRecherche();
informationsRecherche.setDate(vue.getDateReleve().getText());
setInfosRechercheEnCacheEtLancerEvenement(informationsRecherche);
History.fireCurrentHistoryState();
}
});
vue.getLienDateTransmission().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent arg0) {
InformationsRecherche informationsRecherche = new InformationsRecherche();
informationsRecherche.setDate(vue.getDateReleve().getText());
setInfosRechercheEnCacheEtLancerEvenement(informationsRecherche);
History.fireCurrentHistoryState();
}
});
vue.getLienFamille().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent arg0) {
InformationsRecherche informationsRecherche = new InformationsRecherche();
informationsRecherche.setFamille(vue.getFamille().getText());
setInfosRechercheEnCacheEtLancerEvenement(informationsRecherche);
History.fireCurrentHistoryState();
}
});
vue.getLienLocalite().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent arg0) {
InformationsRecherche informationsRecherche = new InformationsRecherche();
informationsRecherche.setCommune(vue.getLocalite().getText());
setInfosRechercheEnCacheEtLancerEvenement(informationsRecherche);
History.fireCurrentHistoryState();
}
});
vue.getLienMotsClefs().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent arg0) {
InformationsRecherche informationsRecherche = new InformationsRecherche();
informationsRecherche.setMotClef(vue.getMotsClefs().getText());
setInfosRechercheEnCacheEtLancerEvenement(informationsRecherche);
History.fireCurrentHistoryState();
}
});
vue.getLienNomCommun().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent arg0) {
InformationsRecherche informationsRecherche = new InformationsRecherche();
informationsRecherche.setRechercheLibre(vue.getNomCommun().getText());
setInfosRechercheEnCacheEtLancerEvenement(informationsRecherche);
History.fireCurrentHistoryState();
}
});
vue.getLienNomRetenu().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent arg0) {
InformationsRecherche informationsRecherche = new InformationsRecherche();
informationsRecherche.setRechercheLibre(vue.getNomRetenu().getText());
setInfosRechercheEnCacheEtLancerEvenement(informationsRecherche);
History.fireCurrentHistoryState();
}
});
vue.getLienMilieu().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent arg0) {
InformationsRecherche informationsRecherche = new InformationsRecherche();
informationsRecherche.setRechercheLibre(vue.getMilieu().getText());
setInfosRechercheEnCacheEtLancerEvenement(informationsRecherche);
History.fireCurrentHistoryState();
}
});
vue.getLienCommentaire().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent arg0) {
InformationsRecherche informationsRecherche = new InformationsRecherche();
informationsRecherche.setRechercheLibre(vue.getCommentaire().getText());
setInfosRechercheEnCacheEtLancerEvenement(informationsRecherche);
History.fireCurrentHistoryState();
}
});
 
vue.setLienIdentiplante(this.observation.getId());
vue.activerLiens();
if(observation.getIdAuteur().equals("0")) {
vue.desactiverLienAuteur();
}
} else {
if (! observation.getIdAuteur().equals("0")) {
vue.getLienAuteur().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Config config = new Config();
Window.open(config.getUrl("annuaire") + observation.getIdAuteur(), "Consultation de l'annuaire", null);
}
});
vue.activerLienAuteur();
}
 
if (observation.getNumNomenclatural() != null && ! observation.getNumNomenclatural().equals("0") && ! observation.getNumNomenclatural().equals("")) {
vue.activerLienNomRetenu();
vue.getLienNomRetenu().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent arg0) {
Config config = new Config();
String efloreUrlFicheTpl = config.getUrl("efloreTaxon");
String efloreUrlFiche = efloreUrlFicheTpl.replaceAll("referentiel-nn-num_nom", observation.getReferentiel().substring(0,5) + "-nn-" + observation.getNumNomenclatural());
Window.open(efloreUrlFiche, "Fiche eflore", null);
}
});
}
}
}
 
public void setInfosRechercheEnCacheEtLancerEvenement(InformationsRecherche informationsRecherche) {
 
switch (modeRecherche) {
case MODE_IMAGE:
CacheClient.getInstance().setPageCouranteRechercheImages(1);
CacheClient.getInstance().setInformationsRechercheImage(informationsRecherche);
BusEvenementiel.getInstance().fireEvent(new EvenementRechercheImage());
break;
 
case MODE_OBSERVATION:
CacheClient.getInstance().setPageCouranteRechercheObservations(1);
CacheClient.getInstance().setInformationsRechercheObservation(informationsRecherche);
BusEvenementiel.getInstance().fireEvent(new EvenementRechercheObservation());
 
default:
break;
}
 
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/metadonnees/MetadonneesVue.java
New file
0,0 → 1,210
package org.tela_botanica.del.client.composants.metadonnees;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.gestionhistorique.ConstantesNavigation;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class MetadonneesVue extends Composite implements MetadonneesPresenteur.Vue {
// Gestion d'UiBinder
interface Binder extends UiBinder<Widget, MetadonneesVue> {
}
 
private static Binder binder = GWT.create(Binder.class);
 
@UiField
Label nomRetenu, famille, auteur, localite, motsClefs, numNomenclatural, nomCommun, commentaire, milieu, station, referentiel;
 
@UiField
HTML lieuDit;
 
@UiField
Panel zoneStation;
@UiField
InlineLabel dateReleve, dateTransmission;
 
@UiField
Anchor lienIdentiplante;
public MetadonneesVue() {
initWidget(binder.createAndBindUi(this));
//Le lien ne doit être affiché que sur pictoflora
if (!CacheClient.getInstance().getPageCourante().equals(ConstantesNavigation.PAGE_RECHERCHE_IMAGES)) {
lienIdentiplante.setVisible(false);
}
}
 
public HasText getNomRetenu() {
return this.nomRetenu;
}
 
public HasText getFamille() {
return this.famille;
}
 
public HasText getAuteur() {
return this.auteur;
}
 
public HasText getDateTransmission() {
return this.dateTransmission;
}
 
public HasText getDateReleve() {
return this.dateReleve;
}
 
public HasText getLocalite() {
return this.localite;
}
 
public HasText getMotsClefs() {
return this.motsClefs;
}
 
public HasText getNumNomenclatural() {
return this.numNomenclatural;
}
 
public HasText getNomCommun() {
return nomCommun;
}
 
public HasText getLieuDit() {
return lieuDit;
}
 
public HasText getMilieu() {
return milieu;
}
 
public HasText getCommentaire() {
return commentaire;
}
 
@Override
public HasClickHandlers getLienNomRetenu() {
return nomRetenu;
}
 
public HasClickHandlers getLienFamille() {
return this.famille;
}
 
public HasClickHandlers getLienAuteur() {
return this.auteur;
}
 
public HasClickHandlers getLienDateTransmission() {
return this.dateTransmission;
}
 
public HasClickHandlers getLienDateReleve() {
return this.dateReleve;
}
 
public HasClickHandlers getLienLocalite() {
return this.localite;
}
 
public HasClickHandlers getLienMotsClefs() {
return this.motsClefs;
}
 
public HasClickHandlers getLienNumNomenclatural() {
return this.numNomenclatural;
}
 
public HasClickHandlers getLienNomCommun() {
return nomCommun;
}
 
public HasClickHandlers getLienMilieu() {
return milieu;
}
 
public HasClickHandlers getLienCommentaire() {
return commentaire;
}
 
@Override
public void masquerChampsVides() {
HasText[] champs = {nomRetenu, nomCommun, famille, localite, auteur, motsClefs, commentaire, milieu, lieuDit, dateReleve, dateTransmission};
for (int i = 0; i < champs.length; i ++) {
HasText champ = champs[i];
if ("".equals(champ.getText())) {
Widget widget = (Widget) champ;
widget.getParent().setVisible(false);
}
}
}
 
@Override
public void setStation(String station) {
if (station.equals("")) {
this.zoneStation.setVisible(false);
} else {
this.station.setText(station);
}
}
public void activerLiens() {
dateReleve.addStyleName("labelLien");
nomRetenu.addStyleName("labelLien");
famille.addStyleName("labelLien");
auteur.addStyleName("labelLien");
localite.addStyleName("labelLien");
motsClefs.addStyleName("labelLien");
nomCommun.addStyleName("labelLien");
commentaire.addStyleName("labelLien");
milieu.addStyleName("labelLien");
}
 
@Override
public void activerLienAuteur() {
auteur.addStyleName("labelLien");
}
@Override
public void desactiverLienAuteur() {
auteur.removeStyleName("labelLien");
}
 
public void setLienIdentiplante(String id) {
lienIdentiplante.setHref(GWT.getHostPageBaseURL() + GWT.getModuleName() + ".html#page_validation~" + id);
lienIdentiplante.setTarget("_blank");
}
 
@Override
public HasText getReferentiel() {
return referentiel;
}
 
@Override
public void activerLienNomRetenu() {
// TODO Auto-generated method stub
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/metadonnees/MetadonneesEnLigneVue.java
New file
0,0 → 1,177
package org.tela_botanica.del.client.composants.metadonnees;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class MetadonneesEnLigneVue extends Composite implements MetadonneesPresenteur.Vue {
// Gestion d'UiBinder
interface Binder extends UiBinder<Widget, MetadonneesEnLigneVue> {
}
 
private static Binder binder = GWT.create(Binder.class);
 
@UiField
Label nomRetenu, famille, auteur, localite, motsClefs, numNomenclatural, nomCommun, commentaire, milieu, station, referentiel;
@UiField
HTML lieuDit;
@UiField
InlineLabel dateReleve, dateTransmission;
 
public MetadonneesEnLigneVue() {
initWidget(binder.createAndBindUi(this));
}
 
public HasText getNomRetenu() {
return this.nomRetenu;
}
 
public HasText getFamille() {
return this.famille;
}
 
public HasText getAuteur() {
return this.auteur;
}
 
public HasText getDateTransmission() {
return this.dateTransmission;
}
 
public HasText getDateReleve() {
return this.dateReleve;
}
 
public HasText getLocalite() {
return this.localite;
}
 
public HasText getMotsClefs() {
return this.motsClefs;
}
 
public HasText getNumNomenclatural() {
return this.numNomenclatural;
}
 
public HasText getNomCommun() {
return nomCommun;
}
 
public HasText getLieuDit() {
return lieuDit;
}
 
public HasText getMilieu() {
return milieu;
}
 
public HasText getCommentaire() {
return commentaire;
}
 
@Override
public HasClickHandlers getLienNomRetenu() {
return nomRetenu;
}
 
public HasClickHandlers getLienFamille() {
return this.famille;
}
 
public HasClickHandlers getLienAuteur() {
return this.auteur;
}
 
public HasClickHandlers getLienDateTransmission() {
return this.dateTransmission;
}
 
public HasClickHandlers getLienDateReleve() {
return this.dateReleve;
}
 
public HasClickHandlers getLienLocalite() {
return this.localite;
}
 
public HasClickHandlers getLienMotsClefs() {
return this.motsClefs;
}
 
public HasClickHandlers getLienNumNomenclatural() {
return this.numNomenclatural;
}
 
public HasClickHandlers getLienNomCommun() {
return nomCommun;
}
 
public HasClickHandlers getLienMilieu() {
return milieu;
}
 
public HasClickHandlers getLienCommentaire() {
return commentaire;
}
 
@Override
public void masquerChampsVides() {
HasText[] champs = {nomRetenu, nomCommun, famille, localite, auteur, motsClefs, commentaire, milieu, lieuDit, dateReleve, dateTransmission};
for (int i = 0; i < champs.length; i ++) {
HasText champ = champs[i];
if ("".equals(champ.getText())) {
Widget widget = (Widget) champ;
widget.getParent().setVisible(false);
}
}
}
 
@Override
public void setStation(String station) {
if (station.equals("")) {
this.station.setVisible(false);
} else {
this.station.setText(station);
}
}
@Override
public void activerLiens() {
}
 
@Override
public void activerLienAuteur() {
auteur.addStyleName("labelLien");
}
 
@Override
public void activerLienNomRetenu() {
nomRetenu.addStyleName("labelLien");
}
 
@Override
public void desactiverLienAuteur() {
auteur.removeStyleName("labelLien");
}
 
public void setLienIdentiplante(String id) {}
 
@Override
public HasText getReferentiel() {
return referentiel;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/images/detailImage.css
New file
0,0 → 1,8
.detailImage {
z-index:1500;
padding: 5px 5px 50px;
width:600px;
background:white;
margin:0 auto;
margin-top:75px;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/images/DetailImageVue.ui.xml
New file
0,0 → 1,11
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'
ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat' ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator" ui:generateLocales="default">
<ui:with field='res' type='org.tela_botanica.del.client.resources.Ressources'/>
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary"/>
 
<ui:style src="detailImage.css" />
<g:HTMLPanel styleName="{style.detailImage}">
<g:Image ui:field="photoPrincipale" />
<g:HTML ui:field="texteAlternatif"/>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/images/DetailImagePresenteur.java
New file
0,0 → 1,31
package org.tela_botanica.del.client.composants.images;
 
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.modeles.Image;
 
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class DetailImagePresenteur extends Presenteur {
 
public abstract interface Vue extends IsWidget {
public abstract void chargerImage(Image image);
}
public Vue vue;
public DetailImagePresenteur(Image image, Vue vue) {
this.vue = vue;
this.vue.chargerImage(image);
}
 
@Override
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
}
 
@Override
protected void gererEvenements() {
// TODO Auto-generated method stub
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/images/DetailImageVue.java
New file
0,0 → 1,55
package org.tela_botanica.del.client.composants.images;
 
import org.tela_botanica.del.client.i18n.I18n;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.LoadEvent;
import com.google.gwt.event.dom.client.LoadHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
 
public class DetailImageVue extends Composite implements DetailImagePresenteur.Vue {
 
// Gestion d'UiBinder
interface Binder extends UiBinder<Widget, DetailImageVue> {
}
 
private static Binder binder = GWT.create(Binder.class);
 
@UiField
protected Image photoPrincipale;
 
@UiField
protected HTML texteAlternatif;
 
public DetailImageVue() {
initWidget(binder.createAndBindUi(this));
photoPrincipale.addLoadHandler(new LoadHandler() {
@Override
public void onLoad(LoadEvent event) {
setWidth(photoPrincipale.getWidth()+"px");
setHeight(photoPrincipale.getHeight()+"px");
}
});
}
 
public void chargerImage(org.tela_botanica.del.client.modeles.Image imageCourante) {
setUrlImage(imageCourante.getUrlFormat("L"));
setTitle(imageCourante.getUrlFormat("L"));
setTexteAlternatif("<strong> "+I18n.getVocabulary().imageNumero()+""+ imageCourante.getIdImage() +" - "+ imageCourante.getObservation().getNomRetenuFormateReferentiel() + " " + I18n.getVocabulary().par() + " " + imageCourante.getObservation().getAuteur() + "</strong><br />"
+ I18n.getVocabulary().publiee() + " "+ imageCourante.getObservation().getDateReleve() + " - " + imageCourante.getObservation().getLocaliteAvecIdFormatee());
}
 
public void setUrlImage(String urlImage) {
photoPrincipale.setUrl(urlImage);
}
 
public void setTexteAlternatif(String texteAlternatif) {
this.texteAlternatif.setHTML(texteAlternatif);
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/partageurl/partagerUrl.css
New file
0,0 → 1,44
.zonePartageUrl {
display:inline-block;
}
.zonePartage {
background: none repeat scroll 0 0 white;
border: 2px solid #8EB533;
padding: 10px 50px 10px 10px;
position:absolute;
}
 
.titre {
margin-top:0;
}
.partage {
background: none repeat scroll 0 0 #87A4F9;
border: medium none;
border-radius: 10px 10px 10px 10px;
color: white;
cursor: pointer;
font-size: 14px;
padding: 4px 10px;
text-decoration: none;
width:130px;
}
 
.url {
width:90%;
margin-top:5px;
}
 
.fermer {
background: url("./img/close.png") no-repeat scroll 39px -2px transparent;
cursor: pointer;
font-size: 11px;
margin-left: 411px;
margin-top: -99px;
padding-bottom: 8px;
padding-right: 53px;
padding-top: 5px;
position: absolute;
width: 16px;
}
 
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/partageurl/PartageUrlVue.ui.xml
New file
0,0 → 1,21
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui' ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
ui:generateLocales="default">
<ui:with field='res' type='org.tela_botanica.del.client.resources.Ressources' />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
 
<ui:style src="partagerUrl.css" />
<g:HTMLPanel>
<g:HTMLPanel>
<g:Label ui:field="partage" styleName="{style.partage}">Partager cette page</g:Label>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.zonePartage} ombre-faible" ui:field="zonePartage">
<g:Label styleName="titre {style.titre}">Partager cette page</g:Label>
<g:Label>Partager le résultat de votre recherche en copiant l'adresse ci-dessous :</g:Label>
<g:TextBox styleName="{style.url}" ui:field="url"></g:TextBox>
<g:Label ui:field="fermer" styleName="{style.fermer}">Fermer</g:Label>
</g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/partageurl/PartageUrlPresenteur.java
New file
0,0 → 1,56
package org.tela_botanica.del.client.composants.partageurl;
 
import org.tela_botanica.del.client.cache.CacheClient;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class PartageUrlPresenteur {
 
public abstract interface Vue extends IsWidget {
public void ajouterVue(HasWidgets composite);
public void masquerFormulaire();
public void afficherFormulaire();
public HasClickHandlers getBoutonPartage();
public HasClickHandlers getFermer();
public void setUrl(String url);
}
 
private Vue vue;
 
public PartageUrlPresenteur(Vue vue) {
this.vue = vue;
vue.masquerFormulaire();
gererEvenements();
}
 
public void gererEvenements() {
vue.getFermer().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
vue.masquerFormulaire();
}
});
vue.getBoutonPartage().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
String url = CacheClient.getInstance().genererUrlCourante();
vue.setUrl(url);
vue.afficherFormulaire();
}
});
}
public void go(HasWidgets composite) {
vue.ajouterVue(composite);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/partageurl/PartageUrlVue.java
New file
0,0 → 1,58
package org.tela_botanica.del.client.composants.partageurl;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
 
public class PartageUrlVue extends Composite implements PartageUrlPresenteur.Vue{
 
 
@UiField Panel zonePartage;
@UiField Label fermer, partage;
@UiField TextBox url;
interface Binder extends UiBinder<Widget, PartageUrlVue> {
}
private static Binder uiBinder = GWT.create(Binder.class);
public PartageUrlVue() {
initWidget(uiBinder.createAndBindUi(this));
}
 
@Override
public void ajouterVue(HasWidgets composite) {
composite.add(this.asWidget());
}
 
@Override
public void masquerFormulaire() {
zonePartage.setVisible(false);
}
 
@Override
public void afficherFormulaire() {
zonePartage.setVisible(true);
}
public HasClickHandlers getFermer() {
return fermer;
}
 
@Override
public HasClickHandlers getBoutonPartage() {
return partage;
}
public void setUrl(String url) {
this.url.setText(url);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/rss/RssVue.java
New file
0,0 → 1,41
package org.tela_botanica.del.client.composants.rss;
 
import org.tela_botanica.del.client.composants.rss.RssPresenteur.Vue;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Widget;
 
public class RssVue extends Composite implements Vue {
 
// Composants
@UiField
HTML lien;
// Variables
String label = "";
// Interface pour l'association au XML
interface Binder extends UiBinder<Widget, RssVue> {
}
 
private static Binder uiBinder = GWT.create(Binder.class);
// Constructeur de la vue
public RssVue() {
initWidget(uiBinder.createAndBindUi(this));
}
public void setLien(String lien) {
String lienHtml = "<a href=\"" + lien + "\" target=\"_blank\">" + label + "</a>";
this.lien.setHTML(lienHtml);
}
public void setLabelLien(String label) {
this.label = label;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/rss/RssVue.ui.xml
New file
0,0 → 1,11
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
ui:generateLocales="default">
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
 
<g:HTMLPanel>
<g:HTML ui:field="lien" styleName="lienRss"> LIEN RSS ></g:HTML>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/rss/RssPresenteur.java
New file
0,0 → 1,63
package org.tela_botanica.del.client.composants.rss;
 
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.modeles.InformationsRecherche;
import org.tela_botanica.del.client.modeles.Observation;
 
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class RssPresenteur extends Presenteur {
 
// Définition de la vue
public abstract interface Vue extends IsWidget {
void setLien(String lien);
void setLabelLien(String label);
}
// Variables
private Vue vue;
private String lien = "";
private Config config = new Config();
//Constructeur
public RssPresenteur(Vue vue) {
this.vue = vue;
}
public RssPresenteur(Vue vue, InformationsRecherche recherche, String label) {
this.vue = vue;
vue.setLabelLien(label);
genererLien(recherche);
}
public RssPresenteur(Vue vue, Observation observation, String label) {
this.vue = vue;
vue.setLabelLien(label);
genererLien(observation);
}
public void genererLien(InformationsRecherche recherche) {
this.lien = config.getUrl("rss") + recherche.versChaineRequete();
gererEvenements();
}
public void genererLien(Observation observation) {
String idObs = observation.getId();
this.lien = config.getUrl("rss") + "&masque.observation=" + idObs;
}
@Override
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
gererEvenements();
}
 
@Override
protected void gererEvenements() {
vue.setLien(this.lien);
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votefleur/voteFleur.css
New file
0,0 → 1,23
.fleur {
width:28px;
height:27px;
}
 
.ZeroPetales {
background:url(./img/fleurs/fleur0.png);
}
.UnPetale {
background:url(./img/fleurs/fleur1.png);
}
.DeuxPetales {
background:url(./img/fleurs/fleur2.png);
}
.TroisPetales {
background:url(./img/fleurs/fleur3.png);
}
.QuatrePetales {
background:url(./img/fleurs/fleur4.png);
}
.CinqPetales {
background:url(./img/fleurs/fleur5.png);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votefleur/VoteFleurVue.ui.xml
New file
0,0 → 1,16
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui' ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator" ui:generateLocales="default">
 
<ui:with field='res' type='org.tela_botanica.del.client.resources.Ressources'/>
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary"/>
<ui:style src="voteFleur.css" />
 
<g:HTMLPanel>
<g:HTMLPanel ui:field="fleur0" styleName="{style.fleur} {style.ZeroPetales}"></g:HTMLPanel>
<g:HTMLPanel ui:field="fleur1" styleName="{style.fleur} {style.UnPetale}"></g:HTMLPanel>
<g:HTMLPanel ui:field="fleur2" styleName="{style.fleur} {style.DeuxPetales}"></g:HTMLPanel>
<g:HTMLPanel ui:field="fleur3" styleName="{style.fleur} {style.TroisPetales}"></g:HTMLPanel>
<g:HTMLPanel ui:field="fleur4" styleName="{style.fleur} {style.QuatrePetales}"></g:HTMLPanel>
<g:HTMLPanel ui:field="fleur5" styleName="{style.fleur} {style.CinqPetales}"></g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votefleur/VoteFleurPresenteur.java
New file
0,0 → 1,33
package org.tela_botanica.del.client.composants.votefleur;
 
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class VoteFleurPresenteur extends Presenteur {
 
public interface Vue extends IsWidget {
public void setNote(int note);
}
 
private Vue vue;
 
public VoteFleurPresenteur(Vue vue) {
this.vue = vue;
}
 
public void go(HasWidgets composite) {
composite.clear();
composite.add(vue.asWidget());
}
public void setNote(int note) {
vue.setNote(note);
}
 
@Override
protected void gererEvenements() {
// TODO Auto-generated method stub
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/votefleur/VoteFleurVue.java
New file
0,0 → 1,56
package org.tela_botanica.del.client.composants.votefleur;
 
 
import org.tela_botanica.del.client.composants.votefleur.VoteFleurPresenteur.Vue;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;
 
public class VoteFleurVue extends Composite implements Vue {
 
// Annotation can be used to change the name of the associated xml file
// @UiTemplate("ObservationVue.ui.xml")
interface MyUiBinder extends UiBinder<Widget, VoteFleurVue> {
}
 
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
@UiField
protected HTMLPanel fleur0, fleur1, fleur2, fleur3, fleur4, fleur5;
 
public VoteFleurVue() {
// sets listBox
initWidget(uiBinder.createAndBindUi(this));
initialiserVue();
}
public void initialiserVue() {
this.fleur0.setVisible(false);
this.fleur1.setVisible(false);
this.fleur2.setVisible(false);
this.fleur3.setVisible(false);
this.fleur4.setVisible(false);
this.fleur5.setVisible(false);
}
 
public void setNote(int note) {
switch (note) {
case 0 : this.fleur0.setVisible(true);
break;
case 1 : this.fleur1.setVisible(true);
break;
case 2 : this.fleur2.setVisible(true);
break;
case 3 : this.fleur3.setVisible(true);
break;
case 4 : this.fleur4.setVisible(true);
break;
default : this.fleur5.setVisible(true);
break;
}
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulairerechercheeflore/FormulaireRechercheEflorePresenteur.java
New file
0,0 → 1,80
package org.tela_botanica.del.client.composants.formulairerechercheeflore;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.formulaires.autocompletion.AutoCompletionComboBoxPresenteur;
import org.tela_botanica.del.client.composants.formulaires.autocompletion.AutoCompletionComboBoxVue;
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.i18n.I18n;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.comparaisoneflore.EvenementComparaisonEflore;
import org.tela_botanica.del.client.utils.UtilitairesAutoCompletionService;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.http.client.Response;
import com.google.gwt.user.client.ui.HasWidgets;
 
public class FormulaireRechercheEflorePresenteur {
 
private FormulaireRechercheEfloreVue formulaireRechercheEfloreVue = new FormulaireRechercheEfloreVue();
 
private AutoCompletionComboBoxPresenteur autoCompletionNomTaxonsPresenteur;
 
public FormulaireRechercheEflorePresenteur() {
creerCompletionTaxons();
}
public void go(HasWidgets composite) {
autoCompletionNomTaxonsPresenteur.go(formulaireRechercheEfloreVue.getPropositionTaxon());
composite.add(formulaireRechercheEfloreVue);
gererEvenements();
}
 
private void gererEvenements() {
formulaireRechercheEfloreVue.getBoutonValidationRechercheObservation().addClickHandler(new ClickHandler() {
 
@Override
public void onClick(ClickEvent event) {
lancerRechercheEflore();
}
});
autoCompletionNomTaxonsPresenteur.getAutoCompletionComboBoxVue().getSuggestBoxHasKeyPressHandlers().addKeyPressHandler(new KeyPressHandler() {
@Override
public void onKeyPress(KeyPressEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
lancerRechercheEflore();
}
}
});
}
 
private void creerCompletionTaxons() {
String url = new Config().getServiceBaseUrl() + "nomstaxons";
autoCompletionNomTaxonsPresenteur = new AutoCompletionComboBoxPresenteur(new AutoCompletionComboBoxVue(), url) {
protected String effectuerPreTraitementChaineRequete(String requete) {
requete = "?masque.nom=" + requete;
return UtilitairesAutoCompletionService.effectuerPreTraitementChaineRequeteGenreEspeceSlash(requete);
}
 
@Override
protected String[] parserResultatRequete(Response response) {
return UtilitairesAutoCompletionService.parserResultatRetourSimple(response);
}
};
}
 
private void lancerRechercheEflore() {
CacheClient.getInstance().setTaxonPourRechercheEflore(autoCompletionNomTaxonsPresenteur.getValeur());
EvenementComparaisonEflore evenementComparaisonEflore = new EvenementComparaisonEflore(autoCompletionNomTaxonsPresenteur.getValeur());
BusEvenementiel.getInstance().fireEvent(evenementComparaisonEflore);
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulairerechercheeflore/FormulaireRechercheEfloreVue.java
New file
0,0 → 1,38
package org.tela_botanica.del.client.composants.formulairerechercheeflore;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class FormulaireRechercheEfloreVue extends Composite {
 
@UiField(provided = true)
public Button boutonValidationRechercheObservation = new Button();
 
@UiField
public Panel propositionTaxon;
 
interface FormulaireRechercheEfloreUIiBinder extends UiBinder<Widget, FormulaireRechercheEfloreVue> {
};
 
FormulaireRechercheEfloreUIiBinder uiBinder = GWT.create(FormulaireRechercheEfloreUIiBinder.class);
 
public FormulaireRechercheEfloreVue() {
initWidget(uiBinder.createAndBindUi(this));
}
 
public Button getBoutonValidationRechercheObservation() {
return boutonValidationRechercheObservation;
}
public Panel getPropositionTaxon() {
return propositionTaxon;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulairerechercheeflore/formulaireRechercheEflore.css
New file
0,0 → 1,4
.propositionTaxon {
width: 150px;
height: 30px;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/formulairerechercheeflore/FormulaireRechercheEfloreVue.ui.xml
New file
0,0 → 1,18
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary"/>
<ui:style src="formulaireRechercheEflore.css" />
<g:VerticalPanel>
<g:Label text="{constants.comparer}" styleName="sousTitre"/>
<g:Label text="{constants.infoComparer}" styleName="petit"/>
<g:HTML><br /></g:HTML>
<g:HorizontalPanel >
<g:HTMLPanel ui:field="propositionTaxon" styleName="{style.propositionTaxon}" />
<g:Button text="{constants.ok}" ui:field="boutonValidationRechercheObservation" />
</g:HorizontalPanel>
</g:VerticalPanel>
 
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/observations/observationimages.css
New file
0,0 → 1,21
.zonePhotos {
}
 
.photoPrincipale {
height: 250px;
float: left;
cursor: pointer
}
 
.photos {
float: left
}
 
.photos img {
display: block;
height: 40px;
width: 40px;
padding: 0 5px 5px 5px;
cursor: pointer
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/observations/ObservationImagesVue.ui.xml
New file
0,0 → 1,13
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui' ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
ui:generateLocales="default">
<ui:with field='res' type='org.tela_botanica.del.client.resources.Ressources' />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
<ui:style src="observationimages.css" />
<g:HTMLPanel styleName="{style.zonePhotos}">
<g:Image ui:field="photoPrincipale" styleName="{style.photoPrincipale}"/>
<g:HTMLPanel ui:field="photos" styleName="{style.photos}"></g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/observations/ObservationImagesPresenteur.java
New file
0,0 → 1,150
package org.tela_botanica.del.client.composants.observations;
 
import java.util.List;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlayDefilantePresenteur;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlayDefilanteVue;
import org.tela_botanica.del.client.composants.images.DetailImagePresenteur;
import org.tela_botanica.del.client.composants.images.DetailImageVue;
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.gestionhistorique.ConstantesNavigation;
import org.tela_botanica.del.client.modeles.Image;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.changementimagevalidation.EvenementChangementImageValidation;
import org.tela_botanica.del.client.navigation.evenement.changementimagevalidation.GestionnaireEvenementChangementImageValidation;
import org.tela_botanica.del.client.navigation.evenement.validationobservation.EvenementValidation;
import org.tela_botanica.del.client.navigation.evenement.validationobservationpictoflora.EvenementValidationPictoflora;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class ObservationImagesPresenteur extends Presenteur {
 
public abstract interface Vue extends IsWidget {
public HasClickHandlers getPhotoPrincipale();
 
public HasWidgets getPhotos();
 
public void chargerImagePrincipale(org.tela_botanica.del.client.modeles.Image image);
 
public void ajouterPhoto(Image image, ClickHandler gestionnaireClic);
 
public void afficherLienPlateformeValidation();
 
public HTML getLienPlateforme();
}
 
private Vue vue;
 
private Observation observation;
 
private Image imagePrincipale;
 
private List<Image> listeImages;
 
private String page;
public ObservationImagesPresenteur(Vue vue, Observation observation, Image imagePrincipale, String page) {
this.observation = observation;
this.vue = vue;
this.imagePrincipale = imagePrincipale;
this.page = page;
}
 
public void chargerImagesObservation() {
 
listeImages = observation.getImages();
if (imagePrincipale != null) {
vue.chargerImagePrincipale(imagePrincipale);
vue.getPhotoPrincipale().addClickHandler(creerGestionnaireClicGalerieImages(0, imagePrincipale));
}
 
int nbImage = 0;
for (Image imageCourante : listeImages) {
vue.ajouterPhoto(imageCourante, creerGestionnaireClicChangementImagePrincipale(imageCourante));
nbImage++;
 
if (page.equals(ConstantesNavigation.PAGE_RECHERCHE_OBSERVATIONS) && nbImage >= 5) {
vue.afficherLienPlateformeValidation();
break;
}
}
}
 
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
chargerImagesObservation();
gererEvenements();
}
 
protected void gererEvenements() {
vue.getLienPlateforme().addClickHandler(new ClickHandler() {
 
@Override
public void onClick(ClickEvent arg0) {
BusEvenementiel.getInstance().fireEvent(new EvenementValidation(observation));
}
 
});
 
BusEvenementiel.getInstance().addHandler(EvenementChangementImageValidation.TYPE, new GestionnaireEvenementChangementImageValidation() {
 
@Override
public void onChangementImage(EvenementChangementImageValidation event) {
if (CacheClient.getInstance().getImageCourante().getObservation().getId().equals(observation.getId())) {
vue.chargerImagePrincipale(CacheClient.getInstance().getImageCourante());
}
}
});
 
}
 
protected ClickHandler creerGestionnaireClicGalerieImages(final int indexImage, final Image imageCourante) {
ClickHandler gestionnaireClic = new ClickHandler() {
public void onClick(ClickEvent event) {
FenetreOverlayDefilantePresenteur presenteurGalerie = new FenetreOverlayDefilantePresenteur(indexImage, new FenetreOverlayDefilanteVue()) {
 
@Override
public void surClicBoutonSuivant() {
int index = getIndexElementAffiche() + 1;
if (index >= listeImages.size()) {
index = 0;
}
setContenuFenetreModale(index, new DetailImagePresenteur(listeImages.get(index), new DetailImageVue()));
}
 
@Override
public void surClicBoutonPrecedent() {
int index = getIndexElementAffiche() - 1;
if (index < 0) {
index = listeImages.size() - 1;
}
setContenuFenetreModale(index, new DetailImagePresenteur(listeImages.get(index), new DetailImageVue()));
}
};
presenteurGalerie.ouvrirFenetreModaleDefilante(indexImage, new DetailImagePresenteur(imageCourante, new DetailImageVue()));
presenteurGalerie.afficherBoutonsSuivantsPrecedents((listeImages.size() > 1));
}
};
return gestionnaireClic;
}
 
protected ClickHandler creerGestionnaireClicChangementImagePrincipale(final Image imageCourante) {
ClickHandler gestionnaireClic = new ClickHandler() {
public void onClick(ClickEvent event) {
CacheClient.getInstance().setImageCourante(imageCourante);
BusEvenementiel.getInstance().fireEvent(new EvenementChangementImageValidation());
}
};
return gestionnaireClic;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/observations/ObservationImagesVue.java
New file
0,0 → 1,91
package org.tela_botanica.del.client.composants.observations;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class ObservationImagesVue extends Composite implements ObservationImagesPresenteur.Vue {
 
// Gestion d'UiBinder
interface Binder extends UiBinder<Widget, ObservationImagesVue> {
}
 
private static Binder binder = GWT.create(Binder.class);
 
@UiField
protected Image photoPrincipale;
 
@UiField
protected Panel photos;
protected HTML lienPlateforme = new HTML(">>>");
 
 
public ObservationImagesVue() {
initWidget(binder.createAndBindUi(this));
}
 
public void chargerImagePrincipale(org.tela_botanica.del.client.modeles.Image image) {
setUrlImagePrincipale(image.getUrlFormat("CRS"));
setTitreImagePrincipale(image.getUrlFormat("L"));
setAltTextImagePrincipale(image.getObservation().getAuteur() + " - " + image.getObservation().getNomRetenuFormateReferentiel());
}
 
@Override
public void ajouterPhoto(org.tela_botanica.del.client.modeles.Image imageCourante, ClickHandler gestionnaireClic) {
Image photo = new Image();
photo.setUrl(imageCourante.getUrlFormat("CRX2S"));
photo.setTitle(imageCourante.getUrlFormat("L"));
photo.setAltText("");
photo.addClickHandler(gestionnaireClic);
getPhotos().add(photo);
}
public void afficherLienPlateformeValidation(){
getPhotos().add(lienPlateforme);
lienPlateforme.setStyleName("suiteImages");
}
 
public void setUrlImagePrincipale(String url) {
photoPrincipale.setUrl(url);
}
 
public void setTitreImagePrincipale(String titre) {
photoPrincipale.setTitle(titre);
}
 
public void setAltTextImagePrincipale(String altText) {
photoPrincipale.setAltText(altText);
}
 
public String getUrlImagePrincipale() {
return photoPrincipale.getUrl();
}
 
public String getTitreImagePrincipale() {
return photoPrincipale.getTitle();
}
 
public String getAltTextImagePrincipale() {
return photoPrincipale.getAltText();
}
 
public Image getPhotoPrincipale() {
return photoPrincipale;
}
 
public Panel getPhotos() {
return photos;
}
 
public HTML getLienPlateforme() {
return lienPlateforme;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/motsclesimages/propositions/MotClePropositionVue.java
New file
0,0 → 1,61
package org.tela_botanica.del.client.composants.motsclesimages.propositions;
 
import org.tela_botanica.del.client.config.Config;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class MotClePropositionVue extends Composite implements MotClePropositionPresenteur.Vue {
@UiField
CheckBox ajouterMotCle;
@UiField
Image iconeTag;
@UiField
FocusPanel lienMotCle;
interface MyUiBinder extends UiBinder<Widget, MotClePropositionVue> {}
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
 
public MotClePropositionVue() {
// sets listBox
initWidget(uiBinder.createAndBindUi(this));
}
 
@Override
public void setMotCle(String motcle) {
ajouterMotCle.setText(motcle);
iconeTag.setUrl((new Config()).getUrl("iconeBaseUrl") + motcle + ".png");
}
public HasClickHandlers getLienMotCle() {
return lienMotCle;
}
public void toggleCb() {
boolean val = ajouterMotCle.getValue();
ajouterMotCle.setValue(!ajouterMotCle.getValue());
}
public boolean estAAjouter() {
return ajouterMotCle.getValue();
}
public void setEstAAjouter() {
ajouterMotCle.setValue(true);
}
public HasClickHandlers getAjouterMotCle() {
return ajouterMotCle;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/motsclesimages/propositions/MotCleProposition.css
New file
0,0 → 1,24
.logoTag {
width:30px;
height:30px;
margin:0 5px;
float:right;
}
 
.motCle {
width:80px;
margin:5px;
}
 
.lienMotCle {
background: none repeat scroll 0 0 #DDDDDD;
border-radius: 9px 9px 9px 9px;
height: 40px;
margin: 2px;
padding: 3px;
width: 163px;
}
 
.lienMotCle:hover {
background: #AAA;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/motsclesimages/propositions/MotClePropositionVue.ui.xml
New file
0,0 → 1,14
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateLocales="default">
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
 
<ui:style src="MotCleProposition.css" />
<g:FocusPanel styleName="{style.lienMotCle} gauche" ui:field="lienMotCle">
<g:HTMLPanel>
<g:CheckBox ui:field="ajouterMotCle" text="motcle" styleName=" {style.motCle}"></g:CheckBox>
<g:Image styleName="{style.logoTag}" ui:field="iconeTag"/>
</g:HTMLPanel>
</g:FocusPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/motsclesimages/propositions/MotClePropositionPresenteur.java
New file
0,0 → 1,79
package org.tela_botanica.del.client.composants.motsclesimages.propositions;
 
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class MotClePropositionPresenteur extends Presenteur{
 
public interface Vue extends IsWidget {
public void setMotCle(String motcle);
public HasClickHandlers getLienMotCle();
public void toggleCb();
public boolean estAAjouter();
public void setEstAAjouter();
public HasClickHandlers getAjouterMotCle();
}
private Vue vue;
private String motcle;
public MotClePropositionPresenteur(Vue vue, String motCle) {
this.vue = vue;
this.motcle = motCle;
vue.setMotCle(motCle);
}
@Override
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
gererEvenements();
}
 
@Override
protected void gererEvenements() {
/* Attention : dans la gestion des évènements, comme la case à cocher est contenu dans
* le lien Mot Cle, lorsque je clique sur la case directement, l'application :
* - change la valeur de la case suite à l'évènement sur la case
* - rechange la valeur de la case suite à l'évènement sur le lien
* Il est donc impossible de changer la valeur de la case !
*
* La solution consiste à ajouter un changement de valeur lorsqu'on clique sur la case :
*/
vue.getAjouterMotCle().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
vue.toggleCb();
}
});
// Ajout du changement de valeur de la case lors du clic sur la case
vue.getLienMotCle().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
vue.toggleCb();
}
});
}
 
public boolean estAAjouter() {
return vue.estAAjouter();
}
public void setEstAAjouter() {
vue.setEstAAjouter();
}
public String getTag() {
return this.motcle;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/motsclesimages/MotsClesImagePresenteur.java
New file
0,0 → 1,255
package org.tela_botanica.del.client.composants.motsclesimages;
 
import java.util.ArrayList;
import java.util.List;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.motsclesimages.formulairesaisiemotclesimages.FormulaireSaisieMotsClesImagePresenteur;
import org.tela_botanica.del.client.composants.motsclesimages.motcle.MotClePresenteur;
import org.tela_botanica.del.client.composants.motsclesimages.motcle.MotCleVue;
import org.tela_botanica.del.client.composants.motsclesimages.propositions.MotClePropositionPresenteur;
import org.tela_botanica.del.client.composants.motsclesimages.propositions.MotClePropositionVue;
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.i18n.I18n;
import org.tela_botanica.del.client.modeles.Image;
import org.tela_botanica.del.client.modeles.MotCle;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.ajoutmotcleimage.EvenementAjoutMotCleImage;
import org.tela_botanica.del.client.navigation.evenement.ajoutmotcleimage.GestionnaireEvenementAjoutMotCleImage;
import org.tela_botanica.del.client.navigation.evenement.fermermotcleimage.EvenementFermerMotCleImage;
import org.tela_botanica.del.client.navigation.evenement.supressionmotcleimage.EvenementSuppressionMotCleImage;
import org.tela_botanica.del.client.navigation.evenement.supressionmotcleimage.GestionnaireEvenementSuppressionMotCleImage;
import org.tela_botanica.del.client.services.rest.MotsClesService;
import org.tela_botanica.del.client.services.rest.MotsClesServiceConcret;
import org.tela_botanica.del.client.services.rest.async.AjoutMotsClesImageCallback;
import org.tela_botanica.del.client.services.rest.async.ListeMotsClesImageCallBack;
import org.tela_botanica.del.client.services.rest.async.SuppressionMotCleImageCallback;
import org.tela_botanica.del.client.utils.StringUtils;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class MotsClesImagePresenteur extends Presenteur {
 
Image image;
List<MotCle> motsCles;
List<String> motClesProtocoleAFiltrer = new ArrayList<String>();
FormulaireSaisieMotsClesImagePresenteur formulaireSaisieMotsClesPresenteur;
final List<MotClePropositionPresenteur> presenteursMotsCles = new ArrayList<MotClePropositionPresenteur>();
MotsClesService motsClesService;
int nbRetours = 0;
int retourCourant = 0;
int nb = 0;
//Déclaration de la vue
public interface Vue extends IsWidget {
public HasWidgets getZoneMotsCles();
 
HasWidgets getZoneSaisieMotsCles();
 
void viderZoneMotsCles();
 
HasWidgets getZoneMotsClesCel();
 
public void afficherMotsClesProtocole(List<String> motsClesCelImages, List<String> motClesCelAFiltrer);
 
public void setImage(String url);
 
public HasWidgets getZoneIconesMotsCles();
 
public HasClickHandlers getValiderMotCles();
}
 
private Vue vue;
 
// Constructeur de l'application
public MotsClesImagePresenteur(Image image, MotsClesService motsClesService, FormulaireSaisieMotsClesImagePresenteur formulaireSaisieMotsClesPresenteur, Vue vue) {
this.formulaireSaisieMotsClesPresenteur = formulaireSaisieMotsClesPresenteur;
this.vue = vue;
this.motsClesService = motsClesService;
this.image = image;
vue.setImage(image.getUrl());
initialiserMotsClesProtocoleAFiltrer();
afficherMotsClesProtocole();
gererEvenements();
}
 
//Afficher la vue
public void go(HasWidgets composite) {
formulaireSaisieMotsClesPresenteur.go(vue.getZoneSaisieMotsCles());
composite.add(vue.asWidget());
}
 
protected boolean cocherMotClePropositionPresenteur(String motcle) {
boolean motCleCoche = false;
for (MotClePropositionPresenteur presenteurCourant : presenteursMotsCles) {
String tagCourant = presenteurCourant.getTag();
if (tagCourant.equals(motcle)) {
presenteurCourant.setEstAAjouter();
motCleCoche = true;
}
}
return motCleCoche;
}
//Charger les mots clés à l'aide du service
public void chargerMotsCles() {
if (motsCles == null) {
vue.viderZoneMotsCles();
MotsClesService motsClesService = new MotsClesServiceConcret();
motsClesService.getMotsClesImage(image.getIdImage(),
new ListeMotsClesImageCallBack() {
@Override
public void surRetour(List<MotCle> objetRetour) {
motsCles = objetRetour;
afficherMotsCles(objetRetour);
}
});
}
}
 
 
protected void afficherMotsCles(List<MotCle> listeMotsCles) {
this.motsCles = listeMotsCles;
nbRetours = listeMotsCles.size();
Object[] tabMotsCles = motsCles.toArray();
for (int i = 0; i < motsCles.toArray().length; i++) {
MotCle motCleEnCours = (MotCle) tabMotsCles[i];
if (!cocherMotClePropositionPresenteur(motCleEnCours.getMotCle())) {
MotClePresenteur mcP = new MotClePresenteur(new MotCleVue(motCleEnCours.getMotCle()), motCleEnCours.getMotCle(), motCleEnCours.getIdMotCle()) {
public void surSuppression(String idMotCle) {
if (Window.confirm(I18n.getVocabulary().indiceSupprimerMotCle() + " ?")) {
motsClesService.supprimerMotCleImage(idMotCle, new SuppressionMotCleImageCallback() {
@Override
public void surRetour(String objetRetour) {
motsCles = null;
chargerMotsCles();
}
});
}
};
};
mcP.go(vue.getZoneMotsCles());
}
}
}
 
protected void afficherMotsClesProtocole() {
List<String> motsClesCelImages = image.getMotsClefs();
vue.afficherMotsClesProtocole(motsClesCelImages, motClesProtocoleAFiltrer);
}
 
// Mettre le focus sur le champ de saisie, appelé par le module pictoflora
public void focuserChampsSaisie() {
formulaireSaisieMotsClesPresenteur.focuserChampSaisie();
}
 
protected void initialiserMotsClesProtocoleAFiltrer() {
//TODO voir si le cache client est bien approprié plutot que passer les infos
// de protocole dans le constructeur
String chaineMotsClesCelAFiltrer = CacheClient.getInstance().getProtocoleCourant().getMotsClesProtocole();
this.motClesProtocoleAFiltrer = new ArrayList<String>();
String[] tabMotsClesCelAFiltrer = chaineMotsClesCelAFiltrer.split(",");
if(tabMotsClesCelAFiltrer.length > 0 && !tabMotsClesCelAFiltrer[0].trim().isEmpty()) {
for (int i = 0; i < tabMotsClesCelAFiltrer.length; i++) {
String motCle = StringUtils.normaliser(tabMotsClesCelAFiltrer[i]);
this.motClesProtocoleAFiltrer.add(motCle);
// ajouter à la vue
MotClePropositionPresenteur presenteurMotCle = new MotClePropositionPresenteur(new MotClePropositionVue(), motCle);
presenteurMotCle.go(vue.getZoneIconesMotsCles());
presenteursMotsCles.add(presenteurMotCle);
}
}
}
/***
* trouver le mot cle dans les mots clés d'origine
* @param String motcle le mot à chercher
* @return MotCle l'objet trouvé
**/
protected MotCle trouverMotCleDorigine(String motCle) {
MotCle motCleRetour = null;
for (MotCle motCleCourant : motsCles) {
String tagCourant = motCleCourant.getMotCle();
if (tagCourant.equals(motCle)) {
motCleRetour = motCleCourant;
}
}
return motCleRetour;
}
//Gérer les évènements
protected void gererEvenements() {
BusEvenementiel.getInstance().addHandler(EvenementAjoutMotCleImage.TYPE, new GestionnaireEvenementAjoutMotCleImage() {
@Override
public void onAjoutMotCleImage(EvenementAjoutMotCleImage event) {
if (image != null && image.getIdImage() != null && image.getIdImage().equals(event.getIdImage())) {
motsCles = null;
chargerMotsCles();
formulaireSaisieMotsClesPresenteur.viderChampSaisie();
}
}
});
 
BusEvenementiel.getInstance().addHandler(EvenementSuppressionMotCleImage.TYPE, new GestionnaireEvenementSuppressionMotCleImage() {
@Override
public void onSuppressionMotCleImage(
EvenementSuppressionMotCleImage event) {
if (image != null && image.getIdImage() != null && image.getIdImage().equals(event.getIdImage())) {
motsCles = null;
chargerMotsCles();
}
}
});
vue.getValiderMotCles().addClickHandler(new ClickHandler() {
 
@Override
public void onClick(ClickEvent event) {
 
MotsClesService motsClesService = new MotsClesServiceConcret();
// récupérer les valeur de toutes les cases à cocher
for (MotClePropositionPresenteur presenteur : presenteursMotsCles) {
if (presenteur.estAAjouter()) {
String tag = presenteur.getTag();
MotCle motcle = trouverMotCleDorigine(tag);
if (motcle == null) {
motsClesService.ajouterMotCleImage(image.getIdImage(), tag, new AjoutMotsClesImageCallback() {
@Override
public void surRetour(Void objetRetour) {
}
});
}
} else {
// il faut vérifier que le mot clé est à supprimer
String tag = presenteur.getTag();
MotCle motcle = trouverMotCleDorigine(tag);
if (motcle != null) {
motsClesService.supprimerMotCleImage(motcle.getIdMotCle(), new SuppressionMotCleImageCallback() {
@Override
public void surRetour(String objetRetour) {
}
});
}
}
}
if (nb == 0) {
BusEvenementiel.getInstance().fireEvent(new EvenementFermerMotCleImage(image.getIdImage()));
nb++;
}
 
}
});
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/motsclesimages/MotsClesImageVue.java
New file
0,0 → 1,91
package org.tela_botanica.del.client.composants.motsclesimages;
 
import java.util.Iterator;
import java.util.List;
 
import org.tela_botanica.del.client.utils.StringUtils;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class MotsClesImageVue extends Composite implements MotsClesImagePresenteur.Vue {
@UiField
Panel motsCles, motsClesCel, saisieMotsCles, zoneIconesMotsCles;
 
@UiField
Image image;
@UiField
Button validerMotsCles;
interface MyUiBinder extends UiBinder<Widget, MotsClesImageVue> {
}
 
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
 
public MotsClesImageVue() {
// sets listBox
initWidget(uiBinder.createAndBindUi(this));
}
@Override
public void viderZoneMotsCles() {
motsCles.clear();
}
 
@Override
public HasWidgets getZoneMotsCles() {
return motsCles;
}
@Override
public HasWidgets getZoneMotsClesCel() {
return motsClesCel;
}
@Override
public HasWidgets getZoneSaisieMotsCles() {
return saisieMotsCles;
}
 
@Override
public void afficherMotsClesProtocole(List<String> motsClesCelImages, List<String> motsClesCelAFiltrer) {
for (Iterator<String> iterator = motsClesCelImages.iterator(); iterator
.hasNext();) {
String mot = (String) iterator.next();
String motNormalise = StringUtils.normaliser(mot);
if(!mot.trim().isEmpty() && motsClesCelAFiltrer.contains(StringUtils.normaliser(motNormalise))) {
HTML motCle = new InlineHTML(mot);
motCle.setStyleName("motCleCel");
motsClesCel.add(motCle);
}
}
}
 
@Override
public void setImage(String url) {
image.setUrl(url);
}
@Override
public HasWidgets getZoneIconesMotsCles() {
return zoneIconesMotsCles;
}
public HasClickHandlers getValiderMotCles() {
return validerMotsCles;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/motsclesimages/formulairesaisiemotclesimages/FormulaireMotsClesImage.css
New file
0,0 → 1,16
.espece {
font-size: 12px;
font-weight: bold;
color: white;
padding-left: 5px;
padding-right: 1px;
}
 
.aideSaisie p {
padding: 0px;
margin: 0px;
overflow: hidden;
text-overflow: ellipsis;
white-space: pre;
min-height: 13px;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/motsclesimages/formulairesaisiemotclesimages/FormulaireSaisieMotsClesImageVue.ui.xml
New file
0,0 → 1,15
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
ui:generateLocales="default">
<ui:with field='res' type='org.tela_botanica.del.client.resources.Ressources' />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
 
<ui:style src="FormulaireMotsClesImage.css" />
<g:HTMLPanel>
<g:HTML styleName="petit {style.aideSaisie}" text="{constants.aideSaisieMotCle}"></g:HTML>
<g:TextBox ui:field="saisieMotsCles"></g:TextBox>
<g:Button text="{constants.ok}" ui:field="valider"></g:Button>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/motsclesimages/formulairesaisiemotclesimages/FormulaireSaisieMotsClesImagePresenteur.java
New file
0,0 → 1,81
package org.tela_botanica.del.client.composants.motsclesimages.formulairesaisiemotclesimages;
 
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.ajoutmotcleimage.EvenementAjoutMotCleImage;
import org.tela_botanica.del.client.services.rest.MotsClesService;
import org.tela_botanica.del.client.services.rest.async.AjoutMotsClesImageCallback;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasKeyPressHandlers;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class FormulaireSaisieMotsClesImagePresenteur {
private MotsClesService motsClesService;
private String idImage;
 
public interface Vue extends IsWidget {
public HasClickHandlers getBoutonValider();
public HasText getSaisieMotsCles();
public HasKeyPressHandlers getSaisieMotsClesHasKeyPressHandlers();
public void focuserChampSaisie();
}
 
private Vue vue;
public FormulaireSaisieMotsClesImagePresenteur(String idImage, MotsClesService motsClesService, Vue vue) {
this.vue = vue;
this.motsClesService = motsClesService;
this.idImage = idImage;
gererEvenements();
}
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
}
private void gererEvenements() {
vue.getBoutonValider().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
validerSaisie();
}
});
vue.getSaisieMotsClesHasKeyPressHandlers().addKeyPressHandler(new KeyPressHandler() {
public void onKeyPress(KeyPressEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
validerSaisie();
}
}
});
}
private void validerSaisie() {
String texte = vue.getSaisieMotsCles().getText();
if(texte != null && !texte.isEmpty()) {
motsClesService.ajouterMotCleImage(idImage, vue.getSaisieMotsCles().getText(), new AjoutMotsClesImageCallback() {
@Override
public void surRetour(Void objetRetour) {
EvenementAjoutMotCleImage event = new EvenementAjoutMotCleImage(idImage);
BusEvenementiel.getInstance().fireEvent(event);
}
});
}
}
 
public void viderChampSaisie() {
vue.getSaisieMotsCles().setText("");
}
 
public void focuserChampSaisie() {
vue.focuserChampSaisie();
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/motsclesimages/formulairesaisiemotclesimages/FormulaireSaisieMotsClesImageVue.java
New file
0,0 → 1,52
package org.tela_botanica.del.client.composants.motsclesimages.formulairesaisiemotclesimages;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasKeyPressHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
 
public class FormulaireSaisieMotsClesImageVue extends Composite implements FormulaireSaisieMotsClesImagePresenteur.Vue {
@UiField
public TextBox saisieMotsCles;
@UiField
public Button valider;
 
interface MyUiBinder extends UiBinder<Widget, FormulaireSaisieMotsClesImageVue> {
}
 
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
 
public FormulaireSaisieMotsClesImageVue() {
// sets listBox
initWidget(uiBinder.createAndBindUi(this));
}
 
@Override
public HasClickHandlers getBoutonValider() {
return valider;
}
@Override
public HasText getSaisieMotsCles() {
return saisieMotsCles;
}
@Override
public HasKeyPressHandlers getSaisieMotsClesHasKeyPressHandlers() {
return saisieMotsCles;
}
 
@Override
public void focuserChampSaisie() {
saisieMotsCles.setFocus(true);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/motsclesimages/MotsClesImage.css
New file
0,0 → 1,43
.titrePanneau p {
padding: 0px;
margin: 0px;
overflow: hidden;
text-overflow: ellipsis;
white-space: pre;
min-height: 13px;
}
 
.titrePanneau {
font-size: 12px;
font-weight: bold;
color: white;
padding-left: 5px;
padding-right: 1px;
}
 
.panneauSaisieMotsCles {
margin-bottom: 3px;
padding-top:30px;
}
 
.fenetreMotsCles {
z-index:1500;
padding: 5px 10px 10px 30px;
width:850px;
background:white;
margin:0 auto;
margin-top:75px;
}
 
.colonneDroite {
margin-left:20px;
}
 
.zoneIconesMotsCles {
padding:5px;
width:519px;
}
 
.listeMotsClesExistants {
max-width:350px;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/motsclesimages/motcle/MotCleVue.java
New file
0,0 → 1,69
package org.tela_botanica.del.client.composants.motsclesimages.motcle;
 
import org.tela_botanica.del.client.i18n.I18n;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasBlurHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasFocusHandlers;
import com.google.gwt.event.dom.client.HasMouseOutHandlers;
import com.google.gwt.event.dom.client.HasMouseOverHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class MotCleVue extends Composite implements MotClePresenteur.Vue {
@UiField
public InlineHTML motCle;
@UiField
public FocusPanel suppressionMotCle;
@UiField
public FocusPanel conteneurMotCle;
 
interface MyUiBinder extends UiBinder<Widget, MotCleVue> {
}
 
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
 
public MotCleVue(String mot) {
initWidget(uiBinder.createAndBindUi(this));
motCle.setText(mot);
suppressionMotCle.setTitle(I18n.getVocabulary().indiceSupprimerMotCle());
}
@Override
public HasClickHandlers getZoneSuppressionMotCle() {
return suppressionMotCle;
}
 
@Override
public void afficherZoneSuppression() {
suppressionMotCle.removeStyleName("invisible");
}
 
@Override
public void cacherZoneSuppression() {
suppressionMotCle.addStyleName("invisible");
}
 
@Override
public HasMouseOverHandlers getZoneMotCleMouseHover() {
return conteneurMotCle;
}
 
@Override
public HasMouseOutHandlers getZoneMotCleMouseOut() {
return conteneurMotCle;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/motsclesimages/motcle/MotCle.css
New file
0,0 → 1,31
.conteneurMotCle {
display: inline-block;
margin-right: 3px;
}
 
.motCle {
border: 1px solid grey;
background-color: #DDD;
padding: 2px;
line-height: 25px;
border-radius:5px;
}
 
.suppressionMotCle {
display: inline;
border: 1px solid grey;
border-left: none;
background-color: #555;
padding: 2px;
padding-left: 4px;
margin-left: -3px;
line-height: 25px;
cursor: pointer;
color: red;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
 
.suppressionMotCle:hover {
background-color: #888;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/motsclesimages/motcle/MotCleVue.ui.xml
New file
0,0 → 1,11
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
ui:generateLocales="default">
<ui:with field='res' type='org.tela_botanica.del.client.resources.Ressources' />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
 
<ui:style src="MotCle.css" />
<g:FocusPanel styleName="{style.conteneurMotCle}" ui:field="conteneurMotCle"><g:HTMLPanel><g:InlineHTML styleName="{style.motCle}" ui:field="motCle" /><g:FocusPanel styleName="invisible {style.suppressionMotCle}" ui:field="suppressionMotCle" ><g:InlineHTML>X</g:InlineHTML></g:FocusPanel></g:HTMLPanel></g:FocusPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/motsclesimages/motcle/MotClePresenteur.java
New file
0,0 → 1,71
package org.tela_botanica.del.client.composants.motsclesimages.motcle;
 
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.HasBlurHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasFocusHandlers;
import com.google.gwt.event.dom.client.HasMouseOutHandlers;
import com.google.gwt.event.dom.client.HasMouseOverHandlers;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public abstract class MotClePresenteur {
String motCle;
String idMotCle;
public interface Vue extends IsWidget {
HasClickHandlers getZoneSuppressionMotCle();
void afficherZoneSuppression();
void cacherZoneSuppression();
HasMouseOverHandlers getZoneMotCleMouseHover();
HasMouseOutHandlers getZoneMotCleMouseOut();
}
 
private Vue vue;
public MotClePresenteur(Vue vue, String motCleText, String motCleId) {
this.vue = vue;
this.idMotCle = motCleId;
}
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
gererEvenements();
}
public void gererEvenements() {
vue.getZoneSuppressionMotCle().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
surSuppression(idMotCle);
}
});
vue.getZoneMotCleMouseHover().addMouseOverHandler(new MouseOverHandler() {
@Override
public void onMouseOver(MouseOverEvent event) {
vue.afficherZoneSuppression();
}
});
vue.getZoneMotCleMouseOut().addMouseOutHandler(new MouseOutHandler() {
@Override
public void onMouseOut(MouseOutEvent event) {
vue.cacherZoneSuppression();
}
});
}
 
public abstract void surSuppression(String idMotCle);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/composants/motsclesimages/MotsClesImageVue.ui.xml
New file
0,0 → 1,31
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<ui:with field='res' type='org.tela_botanica.del.client.resources.Ressources' />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
 
<ui:style src="MotsClesImage.css" />
<g:HTMLPanel styleName="{style.fenetreMotsCles}">
<g:Label text="Saisir des mots clés" styleName="titre"/>
<g:Image ui:field="image" styleName="gauche" />
<g:HTMLPanel styleName="gauche {style.colonneDroite}">
<g:HTML styleName="{style.titrePanneau}" text="{constants.motsCles}"></g:HTML>
<g:HTMLPanel ui:field="zoneIconesMotsCles" styleName="{style.zoneIconesMotsCles}">
</g:HTMLPanel>
<g:HTMLPanel styleName="nettoyage">
<g:HTMLPanel styleName="{style.panneauSaisieMotsCles}" ui:field="saisieMotsCles"></g:HTMLPanel>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.listeMotsClesExistants}">
<g:HTMLPanel>
<g:HTMLPanel styleName="gwt-HTML" ui:field="motsClesCel"></g:HTMLPanel>
</g:HTMLPanel>
<g:HTMLPanel>
<g:HTMLPanel styleName="gwt-HTML" ui:field="motsCles"></g:HTMLPanel>
</g:HTMLPanel>
</g:HTMLPanel>
<g:Button ui:field="validerMotsCles">Valider l'ajout des mots clés et fermer la fenetre</g:Button>
</g:HTMLPanel>
<g:HTMLPanel styleName="nettoyage"></g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/ModeRecherche.java
New file
0,0 → 1,5
package org.tela_botanica.del.client.modeles;
 
public enum ModeRecherche {
MODE_OBSERVATION, MODE_IMAGE
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/InterventionForum.java
New file
0,0 → 1,133
package org.tela_botanica.del.client.modeles;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
public class InterventionForum {
private Contributeur contributeur;
private Date date;
private String id, idParent;
private InterventionForum parent;
private Observation observation;
public List<Commentaire> listeCommentaires = new ArrayList<Commentaire>();
boolean estAffichee;
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public String getIdParent() {
return idParent;
}
 
public void afficher() {
this.estAffichee = true;
}
public boolean estAffichee() {
return this.estAffichee;
}
public void setIdParent(String idParent) {
this.idParent = idParent;
}
public void setParent(InterventionForum parent) {
this.parent = parent;
}
public boolean estFils() {
return (this.parent != null);
}
public InterventionForum getParent() {
return parent;
}
public void setObservation(Observation observation) {
this.observation = observation;
}
public Observation getObservation() {
return observation;
}
public String getAuteur() {
return contributeur.getNomComplet();
}
 
public void setContributeur(Contributeur contributeur) {
this.contributeur = contributeur;
}
public Contributeur getContributeur() {
return contributeur;
}
public Date getDate() {
return date;
}
 
public void setDate(Date date) {
this.date = date;
}
 
public List<Commentaire> getListeCommentaires() {
return listeCommentaires;
}
 
public void setListeCommentaires(List<Commentaire> listeCommentaires) {
this.listeCommentaires = listeCommentaires;
}
 
public void ajouterCommentaire(Commentaire commentaire) {
listeCommentaires.add(commentaire);
}
public boolean aDesCommentaires() {
return (listeCommentaires.size() != 0);
}
public void supprimerIntervention(InterventionForum intervention) {
if(listeCommentaires.contains(intervention)) {
listeCommentaires.remove(intervention);
} else {
for (Iterator<Commentaire> iterator = listeCommentaires.iterator(); iterator.hasNext();) {
iterator.next().supprimerIntervention(intervention);
}
}
}
public PropositionDetermination getPropositionParenteOuNulle() {
InterventionForum parent = getParent();
PropositionDetermination proposition = null;
while(parent != null && !(parent instanceof PropositionDetermination)) {
parent = parent.getParent();
}
if(parent != null) {
proposition = (PropositionDetermination)parent;
}
return proposition;
}
public int getTotalCommentaires() {
int nbCommentaires = 0;
for (Commentaire commentaire : listeCommentaires) {
chargerNbCommentairesRecursivement(nbCommentaires, commentaire);
}
return nbCommentaires;
}
 
private void chargerNbCommentairesRecursivement(int nbCommentaires, Commentaire commentaire) {
nbCommentaires ++;
for (Commentaire commentaireFils: commentaire.getListeCommentaires()) {
chargerNbCommentairesRecursivement(nbCommentaires, commentaireFils);
}
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/TypeInterventionForum.java
New file
0,0 → 1,14
package org.tela_botanica.del.client.modeles;
 
public enum TypeInterventionForum {
TYPE_COMMENTAIRE {
public String toString() {
return "type_commentaire";
};
},
TYPE_PROPOSITION_DETERMINATION {
public String toString() {
return "type_proposition_determination";
};
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/ObservationServiceResultat.java
New file
0,0 → 1,26
package org.tela_botanica.del.client.modeles;
 
import java.util.List;
 
public class ObservationServiceResultat {
 
private List<Observation> observations;
 
private int nbTotalObservationsPourLaRecherche;
 
public List<Observation> getObservations() {
return observations;
}
 
public void setObservations(List<Observation> observations) {
this.observations = observations;
}
 
public int getNbTotalObservationsPourLaRecherche() {
return nbTotalObservationsPourLaRecherche;
}
 
public void setNbTotalObservationsPourLaRecherche(int nbTotalObservationsPourLaRecherche) {
this.nbTotalObservationsPourLaRecherche = nbTotalObservationsPourLaRecherche;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/VoteDetermination.java
New file
0,0 → 1,18
package org.tela_botanica.del.client.modeles;
 
 
public class VoteDetermination extends Vote {
 
private static final long serialVersionUID = -1017065180398557172L;
private PropositionDetermination propositionDetermination;
 
public PropositionDetermination getPropositionDetermination() {
return propositionDetermination;
}
 
public void setPropositionDetermination(
PropositionDetermination propositionDetermination) {
this.propositionDetermination = propositionDetermination;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/Commentaire.java
New file
0,0 → 1,23
package org.tela_botanica.del.client.modeles;
 
import java.util.Date;
 
public class Commentaire extends InterventionForum {
 
private String commentaire;
 
public Commentaire(Contributeur contributeur, Date date, String commentaire) {
setContributeur(contributeur);
setDate(date);
this.commentaire = commentaire;
}
 
public String getCommentaire() {
return commentaire;
}
 
public void setCommentaire(String commentaire) {
this.commentaire = commentaire;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/ModeTri.java
New file
0,0 → 1,19
package org.tela_botanica.del.client.modeles;
 
public enum ModeTri {
TRI_ASCENDANT {
public String toString() {
return "asc";
};
},
TRI_DESCENDANT {
public String toString() {
return "desc";
};
},
PAS_DE_TRI {
public String toString() {
return "naturel";
};
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/VoteProtocole.java
New file
0,0 → 1,22
package org.tela_botanica.del.client.modeles;
 
import java.io.Serializable;
 
public class VoteProtocole extends Vote implements Serializable {
 
private static final long serialVersionUID = -1017065180398557172L;
 
private Protocole protocole;
 
public Protocole getProtocole() {
return protocole;
}
public void setProtocole(Protocole protocole) {
this.protocole = protocole;
}
public int getIdProtocole() {
return getProtocole().getId();
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/Protocole.java
New file
0,0 → 1,51
package org.tela_botanica.del.client.modeles;
 
public class Protocole {
 
private int id;
private String nom;
private String description;
private String tag;
private String motsClesProtocoles;
 
public int getId() {
return id;
}
 
public void setId(int id) {
this.id = id;
}
 
public String getNom() {
return nom;
}
 
public void setNom(String nom) {
this.nom = nom;
}
public String getDescription() {
return description;
}
 
public void setDescription(String description) {
this.description = description;
}
public String getTag() {
return tag;
}
 
public void setTag(String tag) {
this.tag = tag;
}
public void setMotsClesProtocole(String motsClesProtocole) {
this.motsClesProtocoles = motsClesProtocole;
}
public String getMotsClesProtocole() {
return motsClesProtocoles;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/MoyenneVote.java
New file
0,0 → 1,52
package org.tela_botanica.del.client.modeles;
 
public class MoyenneVote implements Comparable<MoyenneVote> {
 
/**
* Pourcentage de personne ayant voté pour la propostion, un score de -1
* indique qu'aucun vote n'a été effectué;
*/
private int score = -1;
private String intituleAssocie;
private PropositionDetermination propositionAssociee;
 
public MoyenneVote(int score, PropositionDetermination propositionAssociee) {
this.score = score;
this.intituleAssocie = propositionAssociee.getEspece();
this.propositionAssociee = propositionAssociee;
}
 
public int getScore() {
return score;
}
 
public void setScore(int score) {
this.score = score;
}
 
public String getIntituleAssocie() {
return intituleAssocie;
}
 
public void setIntituleAssocie(String intituleAssocie) {
this.intituleAssocie = intituleAssocie;
}
 
public void setPropositionAssociee(PropositionDetermination propositionDetermination) {
this.propositionAssociee = propositionDetermination;
}
 
public PropositionDetermination getPropositionAssociee() {
return this.propositionAssociee;
}
 
@Override
public int compareTo(MoyenneVote mv) {
if (mv.getScore() > this.score)
return 1;
else if (mv.getScore() == this.score)
return 0;
else
return -1;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/PropositionDetermination.java
New file
0,0 → 1,125
package org.tela_botanica.del.client.modeles;
 
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
 
public class PropositionDetermination extends InterventionForum implements Serializable {
 
private static final long serialVersionUID = 840032625524143547L;
private String id, espece, commentaire, numNomenclatural, referentiel;
private int nbCommentaires = 0;
private boolean estPropositionInitiale = false;
 
public boolean estPropositionInitiale() {
return estPropositionInitiale;
}
 
public void setEstPropositionInitiale(boolean estPropositionInitiale) {
this.estPropositionInitiale = estPropositionInitiale;
}
 
private Map<String, VoteDetermination> votesDeterminations = new HashMap<String, VoteDetermination>();
private Observation observation;
 
public PropositionDetermination(String id, Contributeur contributeur, String texte) {
setId(id);
setContributeur(contributeur);
setCommentaire(texte);
}
 
public PropositionDetermination(Observation observation) {
this.observation = observation;
}
 
public boolean estPropositionRetenue() {
return (this.espece.equals(this.observation.getNomRetenu()));
}
public void ajouterVoteDetermination(VoteDetermination vd) {
votesDeterminations.put(vd.getContributeur(), vd);
}
 
public String getId() {
return id;
}
 
public void setId(String id) {
this.id = id;
}
 
public String getEspece() {
return espece;
}
 
public void setEspece(String espece) {
this.espece = espece;
}
 
public Map<String, VoteDetermination> getVotesDeterminations() {
return votesDeterminations;
}
 
public void setVotesDeterminations(Map<String, VoteDetermination> votesDeterminations) {
this.votesDeterminations = votesDeterminations;
}
 
public boolean utilisateurAVotePourDetermination(String idContributeur) {
return votesDeterminations.containsKey(idContributeur);
}
 
public Observation getObservation() {
return observation;
}
 
public void setObservation(Observation observation) {
this.observation = observation;
}
 
public void setCommentaire(String commentaire) {
this.commentaire = commentaire;
}
 
public String getCommentaire() {
return commentaire;
}
 
public void setNbCommentaires(int nbCommentaires) {
this.nbCommentaires = nbCommentaires;
}
 
public int getTotalCommentaires() {
// le nombre de commentaire peut avoir été renvoyé par le web service
// sans que l'on possède la liste des commentaires elle même, auquel cas, il sera différent de 0
// et ne doit pas être recalculé
if (nbCommentaires == 0 && this.listeCommentaires.size() != 0) {
nbCommentaires = super.getTotalCommentaires();
if (this.getCommentaire() != null&&this.getCommentaire()!="") {
nbCommentaires += 1;
}
}
if (this.commentaire != null && !this.commentaire.equals("")) {
nbCommentaires ++;
}
 
return nbCommentaires;
}
public String getNumNomenclatural() {
return numNomenclatural;
}
 
public void setNumNomenclatural(String numNomenclatural) {
this.numNomenclatural = numNomenclatural;
}
public String getReferentiel() {
return referentiel;
}
 
public void setReferentiel(String referentiel) {
this.referentiel = referentiel;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/Utilisateur.java
New file
0,0 → 1,83
package org.tela_botanica.del.client.modeles;
 
import java.util.HashMap;
 
import org.tela_botanica.del.client.i18n.I18n;
 
 
public class Utilisateur {
 
private String nom = "";
private String prenom = "";
private String courriel = "";
private String motDePasseHash = "";
private String id = "0";
private String sessionId = "";
private boolean identifie = false;
private HashMap<String, String> preferences = null;
public Utilisateur(String sessionId, String id) {
this.id = id;
this.sessionId = sessionId;
}
public Utilisateur(String sessionId, String id, String prenom, String nom, String courriel, String motDePasseHash) {
this(sessionId, id);
this.prenom = prenom;
this.nom = nom;
this.courriel = courriel;
this.motDePasseHash = motDePasseHash;
identifie = true;
}
public String getMotDePasseHash() {
return motDePasseHash;
}
public void setMotDePasseHash(String motDePasseHash) {
this.motDePasseHash = motDePasseHash;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public String getPrenom() {
return prenom;
}
public void setPrenom(String prenom) {
this.prenom = prenom;
}
public String getCourriel() {
return courriel;
}
public void setCourriel(String courriel) {
this.courriel = courriel;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public boolean estIdentifie() {
return identifie;
}
public void setIdentifie(boolean identifie) {
this.identifie = identifie;
}
public String getNomPrenomFormate() {
return identifie ? prenom+" "+nom : I18n.getVocabulary().anonyme();
}
public HashMap<String, String> getPreferences() {
return preferences;
}
public void setPreferences(HashMap<String, String> preferences) {
this.preferences = preferences;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/ProtocoleServiceResultat.java
New file
0,0 → 1,21
package org.tela_botanica.del.client.modeles;
 
import java.util.List;
 
public class ProtocoleServiceResultat {
private List<Protocole> protocoles;
 
public ProtocoleServiceResultat(List<Protocole> protocoles) {
// constructeur utilisable plus tard quand on aura implenté un systeme
// de cache
this.protocoles = protocoles;
}
 
public List<Protocole> getProtocoles() {
return protocoles;
}
 
public void setProtocoles(List<Protocole> protocoles) {
this.protocoles = protocoles;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/Vote.java
New file
0,0 → 1,55
package org.tela_botanica.del.client.modeles;
 
import java.util.Date;
 
public class Vote {
 
private String id;
private int vote;
private String contributeur;
private Date date;
private Contributeur auteur;
 
public Vote() {
}
 
public String getId() {
return id;
}
 
public void setId(String id) {
this.id = id;
}
 
public int getVote() {
return vote;
}
 
public void setVote(int vote) {
this.vote = vote;
}
 
public String getContributeur() {
return contributeur;
}
 
public void setContributeur(String contributeur) {
this.contributeur = contributeur;
}
 
public Date getDate() {
return date;
}
 
public void setDate(Date date) {
this.date = date;
}
 
public Contributeur getAuteur() {
return auteur;
}
 
public void setAuteur(Contributeur auteur) {
this.auteur = auteur;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/InformationsRecherche.java
New file
0,0 → 1,237
package org.tela_botanica.del.client.modeles;
 
import com.google.gwt.http.client.URL;
 
public class InformationsRecherche {
 
private String rechercheLibre;
 
private String departement;
private String referentiel;
 
private String taxon;
 
private String genre;
 
// gardé pour ancienne comptabilité
private String motClef;
// mots clés publics de del
private String motClefDel;
// mots clés privés du cel
private String motClefCel;
 
private String date;
 
private String commune;
 
private String famille;
 
private String tag;
 
private String auteur;
 
private String idProtocoleSelectionne = null;
 
private ModeTri triParNbVotes = ModeTri.PAS_DE_TRI;
 
private ModeTri triParDate = ModeTri.PAS_DE_TRI;
private ModeTri triParNbTag = ModeTri.PAS_DE_TRI;
 
public String getRechercheLibre() {
return rechercheLibre;
}
 
public void setRechercheLibre(String rechercheLibre) {
if (rechercheLibre != null) {
this.rechercheLibre = rechercheLibre;
}
}
 
public String getDepartement() {
return departement;
}
 
public void setDepartement(String departement) {
if (departement != null) {
this.departement = departement;
}
}
public String getReferentiel() {
return referentiel;
}
 
public void setReferentiel(String referentiel) {
this.referentiel = referentiel;
}
 
public String getTaxon() {
return taxon;
}
 
public void setTaxon(String taxon) {
if (taxon != null) {
this.taxon = taxon;
}
}
 
public String getGenre() {
return genre;
}
 
public void setGenre(String genre) {
if (genre != null) {
this.genre = genre;
}
}
 
public String getMotClef() {
return motClef;
}
 
public void setMotClef(String motClef) {
if (motClef != null) {
this.motClef = motClef;
}
}
 
public String getDate() {
return date;
}
 
public void setDate(String date) {
if (date != null) {
this.date = date;
}
}
 
public String getCommune() {
return commune;
}
 
public void setCommune(String commune) {
if (commune != null) {
String[] tableauCommuneDpt = commune.split(" ");
if (tableauCommuneDpt.length == 2) {
String dpt = tableauCommuneDpt[1].replaceAll("\\(", "").replaceAll("\\)", "");
setDepartement(dpt);
this.commune = tableauCommuneDpt[0];
} else {
this.commune = commune;
}
}
}
 
public String getFamille() {
return famille;
}
 
public void setFamille(String famille) {
if (famille != null) {
this.famille = famille;
}
}
 
public String getTag() {
return tag;
}
 
public void setTag(String tag) {
if (tag != null) {
this.tag = tag;
}
}
 
public String getAuteur() {
return auteur;
}
 
public void setAuteur(String auteur) {
if (auteur != null) {
this.auteur = auteur;
}
}
 
public ModeTri getTriParNbVotes() {
return triParNbVotes;
}
 
public void setTriParNbVotes(ModeTri triParNbVotes) {
this.triParNbVotes = triParNbVotes;
}
 
public void setIdProtocoleSelectionne(String idProtocoleSelectionne) {
this.idProtocoleSelectionne = idProtocoleSelectionne;
}
 
public String getIdProtocoleSelectionne() {
return idProtocoleSelectionne;
}
 
public ModeTri getTriParDate() {
return triParDate;
}
 
public void setTriParDate(ModeTri triParDate) {
this.triParDate = triParDate;
}
 
public void setTriParNbTags(ModeTri triParTag) {
this.triParNbTag = triParTag;
}
public ModeTri getTriParNbTags() {
return this.triParNbTag;
}
 
public String versChaineRequete() {
String chaine = "";
chaine += estNonNull(rechercheLibre) ? "&masque=" + URL.encodeQueryString(rechercheLibre) : "";
chaine += estNonNull(departement) ? "&masque.departement=" + URL.encodeQueryString(departement) : "";
chaine += estNonNull(referentiel) && !referentiel.equals("tous") ? "&masque.referentiel=" + URL.encodeQueryString(referentiel) : "";
chaine += estNonNull(taxon) ? "&masque.ns=" + URL.encodeQueryString(taxon) : "";
chaine += estNonNull(genre) ? "&masque.genre=" + URL.encodeQueryString(genre) : "";
chaine += estNonNull(motClef) ? "&masque.tag=" + URL.encodeQueryString(motClef) : "";
chaine += estNonNull(motClefCel) ? "&masque.tag_cel=" + URL.encodeQueryString(motClefCel) : "";
chaine += estNonNull(motClefDel) ? "&masque.tag_pictoflora=" + URL.encodeQueryString(motClefDel) : "";
chaine += estNonNull(date) ? "&masque.date=" + URL.encodeQueryString(date) : "";
chaine += estNonNull(commune) ? "&masque.commune=" + URL.encodeQueryString(commune) : "";
chaine += estNonNull(famille) ? "&masque.famille=" + URL.encodeQueryString(famille) : "";
chaine += estNonNull(auteur) ? "&masque.auteur=" + URL.encodeQueryString(auteur) : "";
//TODO: réadapter les web services pour que ceux-ci prennent en compte un tri
chaine += triParDate != ModeTri.PAS_DE_TRI ? "&tri=date_observation" : "";
chaine += triParNbVotes != ModeTri.PAS_DE_TRI ? "&tri=votes" : "";
chaine += triParDate != ModeTri.PAS_DE_TRI ? "&ordre=" + triParDate : "";
chaine += triParNbVotes != ModeTri.PAS_DE_TRI ? "&ordre=" + triParNbVotes : "";
chaine += triParNbTag != ModeTri.PAS_DE_TRI ? "&tri=tags" : "";
chaine += triParNbTag != ModeTri.PAS_DE_TRI ? "&ordre=" + triParNbTag : "";
chaine += estNonNull(idProtocoleSelectionne) ? "&protocole=" + idProtocoleSelectionne : "";
 
return chaine;
}
 
private boolean estNonNull(String critere) {
return critere != null && !critere.trim().isEmpty();
}
 
public String getMotClefDel() {
return motClefDel;
}
 
public void setMotClefDel(String motClefDel) {
this.motClefDel = motClefDel;
}
 
public String getMotClefCel() {
return motClefCel;
}
 
public void setMotClefCel(String motClefCel) {
this.motClefCel = motClefCel;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/Image.java
New file
0,0 → 1,122
package org.tela_botanica.del.client.modeles;
 
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import com.google.gwt.user.client.Window;
 
public class Image {
 
private String idImage;
private Observation observation;
private String url;
private String urlFormat;
private String miniature;
private List<String> motsClefs;
 
public String getUrl() {
return url;
}
 
public String getMiniature() {
return miniature;
}
 
public String getUrlFormat(String format) {
return urlFormat.replaceAll("%s%", format);
}
 
public void setUrlFormat(String urlFormat) {
this.urlFormat = urlFormat;
}
 
public void setUrl(String url) {
this.url = url;
}
 
public void setMiniature(String url) {
miniature = url;
}
 
public String getIdImage() {
return idImage;
}
 
public void setIdImage(String idImage) {
this.idImage = idImage;
}
 
// Impossible d'utiliser le type générique Map ici, pourquoi ? je ne sais pas !
private HashMap<String, HashMap<String, VoteProtocole>> votesProtocoles = new HashMap<String, HashMap<String, VoteProtocole>>();
 
public void ajouterVoteProtocole(VoteProtocole voteProcotole) {
getVotesProtocoles(voteProcotole.getIdProtocole()).put(voteProcotole.getContributeur(), voteProcotole);
}
public void supprimerVoteProtocole(String idProtocole, String idContributeur) {
if(utilisateurAVotePourProtocole(idProtocole, idContributeur)) {
votesProtocoles.get(idProtocole).remove(idContributeur);
}
}
public boolean utilisateurAVotePourProtocole(String idProtocole, String idContributeur) {
boolean aVote = false;
if (votesProtocoles.containsKey(idProtocole) && votesProtocoles.get(idProtocole).containsKey(idContributeur)) {
aVote = true;
}
return aVote;
}
public HashMap<String, VoteProtocole> getVotesProtocoles(String id_protocole) {
if(!votesProtocoles.containsKey(""+id_protocole) || votesProtocoles.get(""+id_protocole) == null) {
votesProtocoles.put(""+id_protocole, new HashMap<String, VoteProtocole>());
}
return votesProtocoles.get(id_protocole+"");
}
public HashMap<String, VoteProtocole> getVotesProtocoles(int id_protocole) {
return getVotesProtocoles(id_protocole+"");
}
public HashMap<String, HashMap<String, VoteProtocole>> getListeVotesProtocoles() {
return votesProtocoles;
}
public void setVoteProtocoles(HashMap<String, HashMap<String, VoteProtocole>> voteProtocoles) {
this.votesProtocoles = voteProtocoles;
}
 
public void setVoteProtocoles(String id_protocole, HashMap<String, VoteProtocole> voteProtocoles) {
this.votesProtocoles.put(id_protocole, voteProtocoles);
}
 
public Observation getObservation() {
return observation;
}
 
public void setObservation(Observation observation) {
this.observation = observation;
}
public List<String> getMotsClefs() {
return motsClefs;
}
 
public void setMotsClefs(List<String> motsClefs) {
this.motsClefs = motsClefs;
}
 
public void ajouterMotsClef(String motsClefs) {
if (this.motsClefs == null) {
this.motsClefs = new ArrayList<String>();
}
this.motsClefs.add(motsClefs);
}
public boolean estADeterminer() {
return observation == null || observation.estADeterminer() || motsClefs.contains("aDeterminer");
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/MotCle.java
New file
0,0 → 1,27
package org.tela_botanica.del.client.modeles;
 
public class MotCle {
private String idMotCle;
private String idImage;
private String motCle;
public MotCle(String idMotCle, String idImage, String motCle) {
super();
this.idMotCle = idMotCle;
this.idImage = idImage;
this.motCle = motCle;
}
 
public String getIdMotCle() {
return idMotCle;
}
 
public String getIdImage() {
return idImage;
}
 
public String getMotCle() {
return motCle;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/Contributeur.java
New file
0,0 → 1,51
package org.tela_botanica.del.client.modeles;
 
import com.google.gwt.user.client.Window;
 
public class Contributeur {
private String id, nom, prenom, adresseEmail;
public Contributeur(String id, String nom, String prenom, String adresseEmail) {
this.id = id;
this.nom = nom;
this.prenom = prenom;
this.adresseEmail = adresseEmail;
}
 
public String getNom() {
return nom;
}
 
public void setNom(String nom) {
this.nom = nom;
}
 
public String getPrenom() {
return prenom;
}
 
public void setPrenom(String prenom) {
this.prenom = prenom;
}
 
public String getAdresseEmail() {
return adresseEmail;
}
 
public void setAdresseEmail(String adresseEmail) {
this.adresseEmail = adresseEmail;
}
public String getNomComplet() {
return this.prenom + " " + this.nom;
}
public void setId(String id) {
this.id = id;
}
 
public String getId() {
return id;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/ImageServiceResultat.java
New file
0,0 → 1,26
package org.tela_botanica.del.client.modeles;
 
import java.util.List;
 
public class ImageServiceResultat {
 
private List<Image> images;
 
private int nbTotalImagesPourLaRecherche;
 
public List<Image> getImages() {
return images;
}
 
public void setImages(List<Image> images) {
this.images = images;
}
 
public int getNbTotalImagesPourLaRecherche() {
return nbTotalImagesPourLaRecherche;
}
 
public void setNbTotalImagesPourLaRecherche(int nbTotalImagesPourLaRecherche) {
this.nbTotalImagesPourLaRecherche = nbTotalImagesPourLaRecherche;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/modeles/Observation.java
New file
0,0 → 1,289
package org.tela_botanica.del.client.modeles;
 
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
 
public class Observation implements Serializable {
 
private static final long serialVersionUID = 840032625524143547L;
private String id, auteur, idAuteur, nomAuteur, prenomAuteur, courrielAuteur, nomRetenu, famille, localite, idLocalite,
dateTransmission, numNomenclatural, nomCommun, lieuDit,
milieu, commentaire, dateReleve, station, referentiel;
 
private List<String> motsClefs = new ArrayList<String>();
 
// les propositions sont une liste ordonnée qui contient soit des
// proposition de determinations, soit des commentaires
private List<InterventionForum> propositions = new ArrayList<InterventionForum>();
private List<Image> images = new ArrayList<Image>();
 
public String getAuteur() {
return auteur;
}
 
public void setAuteur(String auteur) {
this.auteur = auteur;
}
 
public String getNomRetenu() {
return nomRetenu;
}
 
public void setNomRetenu(String commonName) {
this.nomRetenu = commonName;
}
 
public String getNomCommun() {
return nomCommun;
}
 
public void setNomCommun(String nomCommun) {
this.nomCommun = nomCommun;
}
 
public String getStation() {
return this.station;
}
public void setStation(String station) {
this.station = station;
}
public String getLieuDit() {
return this.lieuDit;
}
 
public void setLieuDit(String lieuDit) {
this.lieuDit = lieuDit;
}
 
public String getMilieu() {
return milieu;
}
 
public void setMilieu(String milieu) {
this.milieu = milieu;
}
 
public String getCommentaire() {
return commentaire;
}
 
public void setCommentaire(String commentaire) {
this.commentaire = commentaire;
}
 
public String getFamille() {
return famille;
}
 
public void setFamille(String famille) {
this.famille = famille;
}
 
public String getIdLocalite() {
return idLocalite;
}
 
public void setIdLocalite(String idlocalite) {
this.idLocalite = idlocalite;
}
 
public String getLocalite() {
return localite;
}
 
public String getLocaliteAvecIdFormatee() {
String localiteFormatee = this.localite;
if (idLocalite != null && idLocalite.length() >= 5 && idLocalite.substring(0, 5).equals("INSEE")) {
String[] tableaulocalite = idLocalite.split(":");
String idLocaliteFormatee = (tableaulocalite.length == 2) ? tableaulocalite[1] : localiteFormatee;
localiteFormatee += " (" + idLocaliteFormatee + ")";
} else if (idLocalite != null && idLocalite.length() >= 2) {
localiteFormatee += " (" + idLocalite.substring(0, 2) + ")";
}
 
return localiteFormatee;
}
 
public void setLocalite(String localite) {
this.localite = localite;
}
 
public String getDateTransmission() {
return dateTransmission;
}
 
public void setDateTransmission(String date) {
this.dateTransmission = date;
}
 
public String getDateReleve() {
return dateReleve;
}
 
public void setDateReleve(String dateReleve) {
this.dateReleve = dateReleve;
}
 
public String getNumNomenclatural() {
return numNomenclatural;
}
 
public void setNumNomenclatural(String numNomenclatural) {
this.numNomenclatural = numNomenclatural;
}
 
public List<InterventionForum> getInterventionsForum() {
return propositions;
}
 
public void setInterventionsForum(List<InterventionForum> propositions) {
this.propositions = propositions;
}
 
public List<String> getMotsClefs() {
return motsClefs;
}
 
public void setMotsClefs(List<String> motsClefs) {
this.motsClefs = motsClefs;
}
 
public void ajouterMotsClef(String motsClefs) {
if (this.motsClefs == null) {
this.motsClefs = new ArrayList<String>();
}
this.motsClefs.add(motsClefs);
}
 
public void ajouterPropositionDetermination(PropositionDetermination observationValidation) {
propositions.add(observationValidation);
}
 
public ArrayList<String> getPropositionsTaxonsData() {
 
ArrayList<String> propositionsTaxonDatas = new ArrayList<String>();
for (InterventionForum proposition : propositions) {
if (proposition instanceof PropositionDetermination) {
String espece = ((PropositionDetermination) proposition).getEspece();
if (espece != "" && !propositionsTaxonDatas.contains(espece)) {
propositionsTaxonDatas.add(espece);
}
}
}
 
return propositionsTaxonDatas;
}
 
public List<PropositionDetermination> getPropositionDeterminations() {
List<PropositionDetermination> determinations = new ArrayList<PropositionDetermination>();
for (InterventionForum proposition : getInterventionsForum()) {
if (proposition instanceof PropositionDetermination) {
determinations.add((PropositionDetermination) proposition);
}
}
return determinations;
}
public List<Commentaire> getCommentairesForum() {
List<Commentaire> commentaires = new ArrayList<Commentaire>();
for (InterventionForum proposition : getInterventionsForum()) {
if (proposition instanceof Commentaire) {
commentaires.add((Commentaire) proposition);
}
}
return commentaires;
}
public void supprimerIntervention(InterventionForum intervention) {
if(propositions.contains(intervention)) {
propositions.remove(intervention);
} else {
for (Iterator<InterventionForum> iterator = propositions.iterator(); iterator.hasNext();) {
iterator.next().supprimerIntervention(intervention);
}
}
}
 
public List<Image> getImages() {
return images;
}
 
public void setImages(List<Image> images) {
this.images = images;
}
 
public String getId() {
return id;
}
 
public void setId(String id) {
this.id = id;
}
public void setIdAuteur(String idAuteur) {
this.idAuteur = idAuteur;
}
 
public String getIdAuteur() {
return idAuteur;
}
public String getNomAuteur() {
return nomAuteur;
}
 
public void setNomAuteur(String nomAuteur) {
this.nomAuteur = nomAuteur;
}
 
public String getPrenomAuteur() {
return prenomAuteur;
}
 
public void setPrenomAuteur(String prenomAuteur) {
this.prenomAuteur = prenomAuteur;
}
 
public String getCourrielAuteur() {
return courrielAuteur;
}
 
public void setCourrielAuteur(String courrielAuteur) {
this.courrielAuteur = courrielAuteur;
}
public boolean estADeterminer() {
return nomRetenu == null || nomRetenu.isEmpty() || motsClefs.contains("aDeterminer");
}
public String getReferentiel() {
String refFmt = "";
// on ne renvoie que le code du référentiel, sans version, et seulement également si l'on possède
// un numéro nomenclatural associé (ce qui nous assure une certaine cohérence)
if(referentiel.length() >= 5 && numNomenclatural != null && !numNomenclatural.equals("0")) {
refFmt = referentiel.substring(0, 5);
}
return refFmt;
}
public void setReferentiel(String referentiel) {
this.referentiel = referentiel;
}
public String getNomRetenuFormateReferentiel() {
String nomRetenuFmt = "";
if(nomRetenu != null && !nomRetenu.equals("")) {
nomRetenuFmt += nomRetenu;
}
String referentiel = getReferentiel();
if(!nomRetenuFmt.equals("") && !referentiel.equals("")) {
nomRetenuFmt += " ("+referentiel+")";
}
return nomRetenuFmt;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/resources/Ressources.java
New file
0,0 → 1,21
package org.tela_botanica.del.client.resources;
 
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.ImageResource;
 
/**
* Resources used by the entire application.
*/
public interface Ressources extends ClientBundle {
 
@Source("logo.jpg")
ImageResource logo();
 
@Source("flecheGauche.png")
ImageResource arrowLeft();
 
@Source("flecheDroite.png")
ImageResource arrowRight();
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/resources/logo.jpg
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/src/org/tela_botanica/del/client/resources/logo.jpg
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/src/org/tela_botanica/del/client/resources/flecheDroite.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/src/org/tela_botanica/del/client/resources/flecheDroite.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/src/org/tela_botanica/del/client/resources/flecheGauche.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/src/org/tela_botanica/del/client/resources/flecheGauche.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/src/org/tela_botanica/del/client/i18n/Messages.properties
New file
0,0 → 1,11
rechercher_taxon=Rechercher le taxon {0}
 
#composant pagination
parmi_nb_pages = sur {0}
identificationRefus = Identification refusée
saisirLogin = Vous devez saisir un login et un mot de passe
 
#formulaire proposition determination
propositionDejaEffectuee = Le taxon {0} a deja été proposé. Vous pouvez voter pour cette determination si vous êtes d accord avec cette proposition.
etVotesAnonymes = Et {0} votes anonymes
greetings = salut
/tags/v1.1-helium/src/org/tela_botanica/del/client/i18n/Vocabulary.properties
New file
0,0 → 1,195
###########################################################################################
# ATTENTION : le fichier doit être en UTF-8 ! #
# Pour la nomenclature, nommer comme en JAVA puisque ça devient des méthodes : #
# Ex : #
# monLabelPerso = Ma définition #
###########################################################################################
 
# COMMUN
lienAppliSaisie = http://www.tela-botanica.org/widget:cel:saisie?tag-img=aDeterminer&tag-obs=aDeterminer&titre=&titre=Ajouter%20une%20photo%20%26agrave%3B%20d%26eacute%3Bterminer
lienAppliSaisieProjetUrl = http://www.tela-botanica.org/widget:cel:saisie?tag-img={projet}&tag-obs={projet}
oui = oui
non = non
accepter = Valider
annuler = Annuler
chargement = Chargement
ok = ok
fermer = Fermer
vider = Vider
moyenne = Moyenne
nombreVotes = Nb votes
observateur = Observateur
nomRetenu = Nom retenu
date = Date
famille = Famille
metadonneeFamille = Famille
localite = Localite
nom = Nom
auteur = Publié par
protocole = Protocole
protocoleDefaut = Protocole par défaut
labelProtocole = Choisir un protocole
vous = Vous
contributeur= Contributeur
commentaire = Commentaire
commentaires= Commentaires
autre = Autre
nomCommun = Nom commun
lieuDit = Lieu-dit
station = Station
milieu = Milieu
dateReleve = Le
observeLe = Observée le
lieuDuReleve = Lieu du relevé
dateTransmission = Transmis le
motdepasse = Mot de passe :
login = Courriel :
texteConnexion = texte de connexion
titreSeConnecter = Identifiez-vous
titreEstIdentifie = Bienvenue
seDeconnecter = Se déconnecter
aucunResultat = Aucun resultat trouvé
par = par
publiee = Publiée le
supprimerVote = Supprimer votre vote
votePrisEnCompte = Vote pris en compte
voteModifie = Vote modifié
voteSupprime = Vote supprimé
ajouterObservation = Proposez une observation à déterminer
ajouterImage = Ajouter une image
legendeAjouterObservation = Soumettez au réseau une observation à déterminer \n Si vous avez déjà un carnet en ligne, ajoutez votre observation dans le projet "aDeterminer"
legendeAjouterImage = Ajoutez une image pour participer à ce projet
voirCommentaires = Voir tous les commentaires
titrePlateformeDetermination = Synthèse de l'observation et des images associées
imageNumero = Image n°
 
#ecran recherche image
rechercherImage = Rechercher et voter
entrerMotClef = Recherchez par espèce, genre, famille, numéro ou nom de département, commune, auteur ou mot-clé.
rechercherTaxon = Rechercher le taxon
tri = Tri :
triParNbVotes = Votes
triParDate = Date
triParNbTags = Tags
triParNbVotesAscendant = Tri par nombre de votes du maximum au minimum
triParDateAscendant = Tri par date du plus ancien au plus récent
triParNbVotesDescendant = Tri par nombre de votes du minimum au maximum
triParDateDescendant = Tri par date du plus récent au plus ancien
triParNbTagsAscendant = Tri par nombre de tags ascendant
triParNbTagsDescendant = Tri par nombre de tags descendant
introRechercheImages = Cette galerie vous permet de rechercher les illustrations des membres du réseau issues du Carnet en ligne... et de voter pour la qualité des images selon un protocole défini.
indicationActionClicImage = Cliquez sur l'image pour l'agrandir ou sur le bandeau contenant le nom pour accéder à la fiche de l'observation
voirMetadonnees = Voir la date, le lieu et l'auteur de l'image
voirMotsCles = Voir et modifier les mots clés associés à l'image
motsCles = Mots Clés
aideSaisieMotCle = Saisissez des mots clés pour décrire l'image
indiceSupprimerMotCle = Supprimer ce mot clé
accesAide = Aide
lienAidePictoflora = http://www.tela-botanica.org/page:liste_projets?id_projet=112&act=wikini
lienAideIdentiplante = http://www.tela-botanica.org/page:liste_projets?id_projet=95&act=wikini
signalerIdentification = Signaler une mauvaise identification
#ecran recherche observation
rechercherObservation = Identifier une plante
introRechercheObservations = Cet espace vous permet d'échanger sur la détermination d'espèces. <br />Vous ne parvenez pas à déterminer une plante ? Soumettez-la aux membres du réseau. <br /> Vous avez relevé des erreurs dans les images soumises par le réseau ? Postez un commentaire ou proposez une nouvelle détermination.
voirFicheIndividu = Voir la fiche
voirDetailVotes = Voir le détail des utilisateurs qui ont voté
voirDetailCommentaires = Voir les commentaires liés à cette proposition
 
 
#ecran determination
proposerSaDetermination = Proposer une détermination
infoProposerDetermination = Pour proposer une détermination, remplissez les champs ci-dessous et cliquez sur le bouton Proposer !
infoProposerCommentaire = Pour proposer un commentaire, remplissez les champs ci-dessous et cliquez sur le bouton Valider !
boutonProposer = Valider
infoVous = Vos nom et prénom
fiabilite = Fiabilité
infoFiabilite = Indiquez votre niveau de certitude vis-à-vis de votre proposition.
autresInformations = Autres informations
choisirUnTaxon = Proposer un nom de plante
infoTaxon = Tapez les premières lettres d'un nom latin pour voir apparaître des propositions.
autreProposition = Autre Proposition
confianceSimpleSuggestion = Simple Suggestion
confianceProbable = Probable
confianceSurCent = Sûr à 100%
comparer = Comparer cette image
infoComparer = Saisissez un nom de plante à comparer avec l'image
lesPropositions = Propositions
infoPropositions = D'autres utilisateurs ont laissé une détermination
titreDetermination = Détermination / confirmation
metadonnees = Métadonnées
ajouterCommentaire = Ajouter un commentaire
determinationPlusProbable = Détermination la plus probable :
proposePar = proposé par
EtesVousDaccord = Etes-vous d'accord ?
JeSuisDaccord = Je suis d'accord
JeNeSuisPasDaccord = Je ne suis pas d'accord
confirmationSuppressionCommentaire = Êtes vous sur de vouloir supprimer ce commentaire ?
confirmationSuppressionDetermination = Êtes vous sur de vouloir supprimer cette détermination ?
confirmationValidationDetermination = Êtes vous sur de vouloir modifier votre observation pour le nom indiqué par cette proposition ?
 
#ecran comparaison
dateObservation = Date de la prise de vue
taxonADeterminer = Taxon à déterminer
imageEflore = Photos du Carnet en Ligne
metadonneesPhoto = Meta-donnees de la photo
motsClefs = Mots-clés
validePar = Validé par
dateValidation = Date de dernière validation
transmisLe = Transmis le
 
#ecran votes protcoles
votes = Moyenne des votes
votesMoyennePrecise = Moyenne précise des votes :
infoVotes = Voici la moyenne des votes en fonction du protocole choisi :
protocoleEsthetisme = Esthétisme
protocoleIdentificationAuto = Identification automatique
monVote = Mon vote
nbVotes = vote
votez = Votez
 
#ecran detail de votes détermination
aucunVoteEffectue = Aucun vote n'a été effectué sur cette détermination, soyez le premier a voter !
aucunCommentaireEffectue = Aucun commentaire n'a été effectué sur cette détermination
valeurVote = Vote
 
#composant recherche simple
rechercher = Rechercher
rechercheLibre=Recherche libre
 
#composant recherche avancee
rechercheAvancee= Recherche avancée
contientMots = Contient les mots
departement = Département (numéro ou nom)
taxon = Espèce
genre = Genre
mot_clef= Mot-clé
date= Date
formatDate = (jj/mm/aaaa ou aaaa)
commune = Commune
famille = Famille (Latin)
tag = Tag
tagDel = Tag pictoflora
tagCel = Tag cel
referentiel = Référentiel
referentielTous = Tous les référentiels
referentielBdtfx = Trachéophytes de France métropolitaine
referentielBdtxa = Trachéophytes des Antilles françaises
 
 
#composant pagination
afficher = Afficher
elements_par_page = éléments par page
 
#utilisateur
nom = Nom
prenom = Prénom
courriel = Courriel
anonyme = Anonyme
identifie = Identifié
 
#preferences utilisateur
messageTemporaireMails = Identiplante permettra bientôt de recevoir des courriels journaliers récapitulant les propositions, commentaires et observations nouvellement ajoutés. En cochant ces cases vous avez la possibilité de recevoir ces courriels dès qu'il seront mis en service (vous pouvez changer cela à tout moment en revenant sur cette interface)
recevoirMailsMesObs = Recevoir le mail récapitulant les commentaires et propositions faits sur mes observations (1 fois par jour)
recevoirMailsToutesObs = Recevoir le mail récapitulant les nouvelles observations proposées à la détermination (1 fois par jour)
sauvegarder = Sauvegarder
preferences = Préférences
/tags/v1.1-helium/src/org/tela_botanica/del/client/i18n/VocabularyConsumer.java
New file
0,0 → 1,18
package org.tela_botanica.del.client.i18n;
 
import com.google.gwt.core.client.GWT;
 
public class VocabularyConsumer {
public VocabularyConsumer() {
}
 
public static Vocabulary getVocabulary() {
return (Vocabulary) GWT.create(Vocabulary.class);
}
 
public static Messages getMessages() {
return (Messages) GWT.create(Messages.class);
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/i18n/LocalizableResource.properties
New file
0,0 → 1,5
# Generated from org.tela_botanica.del.client.composants.formulaires.identification.FormulaireIdentificationVueBinderImplGenMessages
# for locale default
 
# Description: Greeting
greetings=Hello, worldTRTRTR.
/tags/v1.1-helium/src/org/tela_botanica/del/client/i18n/Messages_en.properties
--- v1.1-helium/src/org/tela_botanica/del/client/i18n/Vocabulary_en.properties (revision 0)
+++ v1.1-helium/src/org/tela_botanica/del/client/i18n/Vocabulary_en.properties (revision 1535)
@@ -0,0 +1,3 @@
+#sample constant property to be translated in language specific versions of this property file
+
+
/tags/v1.1-helium/src/org/tela_botanica/del/client/i18n/Messages.java
New file
0,0 → 1,21
package org.tela_botanica.del.client.i18n;
 
/**
* Interface to represent the constants contained in resource bundle:
* 'D:/dev/svn/del/src/org/tela_botanica/del/client/i18n/Messages.properties'.
*/
public interface Messages extends com.google.gwt.i18n.client.Messages {
 
String rechercher_taxon(String nomTaxon);
 
String parmi_nb_pages(int nbPages);
String saisirLogin();
String identificationRefus();
String propositionDejaEffectuee(String taxon);
String etVotesAnonymes(String nbVotes);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/i18n/Vocabulary.java
New file
0,0 → 1,1457
package org.tela_botanica.del.client.i18n;
 
/**
* Interface to represent the constants contained in resource bundle:
* '/home/aurelien/web/del/src/org/tela_botanica/del/client/i18n/Vocabulary.properties'.
*/
public interface Vocabulary extends com.google.gwt.i18n.client.Constants {
/**
* Translated "Etes-vous d'accord ? ".
*
* @return translated "Etes-vous d'accord ? "
*/
@DefaultStringValue("Etes-vous d'accord ? ")
@Key("EtesVousDaccord")
String EtesVousDaccord();
 
/**
* Translated "Je ne suis pas d'accord".
*
* @return translated "Je ne suis pas d'accord"
*/
@DefaultStringValue("Je ne suis pas d'accord")
@Key("JeNeSuisPasDaccord")
String JeNeSuisPasDaccord();
 
/**
* Translated "Je suis d'accord".
*
* @return translated "Je suis d'accord"
*/
@DefaultStringValue("Je suis d'accord")
@Key("JeSuisDaccord")
String JeSuisDaccord();
 
/**
* Translated "Valider".
*
* @return translated "Valider"
*/
@DefaultStringValue("Valider")
@Key("accepter")
String accepter();
 
/**
* Translated "Aide".
*
* @return translated "Aide"
*/
@DefaultStringValue("Aide")
@Key("accesAide")
String accesAide();
 
/**
* Translated "Afficher".
*
* @return translated "Afficher"
*/
@DefaultStringValue("Afficher")
@Key("afficher")
String afficher();
 
/**
* Translated "Saisissez des mots clés pour décrire l'image".
*
* @return translated "Saisissez des mots clés pour décrire l'image"
*/
@DefaultStringValue("Saisissez des mots clés pour décrire l'image")
@Key("aideSaisieMotCle")
String aideSaisieMotCle();
 
/**
* Translated "Ajouter un commentaire".
*
* @return translated "Ajouter un commentaire"
*/
@DefaultStringValue("Ajouter un commentaire")
@Key("ajouterCommentaire")
String ajouterCommentaire();
 
/**
* Translated "Ajouter une image".
*
* @return translated "Ajouter une image"
*/
@DefaultStringValue("Ajouter une image")
@Key("ajouterImage")
String ajouterImage();
 
/**
* Translated "Proposez une observation à déterminer".
*
* @return translated "Proposez une observation à déterminer"
*/
@DefaultStringValue("Proposez une observation à déterminer")
@Key("ajouterObservation")
String ajouterObservation();
 
/**
* Translated "Annuler".
*
* @return translated "Annuler"
*/
@DefaultStringValue("Annuler")
@Key("annuler")
String annuler();
 
/**
* Translated "Anonyme".
*
* @return translated "Anonyme"
*/
@DefaultStringValue("Anonyme")
@Key("anonyme")
String anonyme();
 
/**
* Translated "Aucun commentaire n'a été effectué sur cette détermination".
*
* @return translated "Aucun commentaire n'a été effectué sur cette détermination"
*/
@DefaultStringValue("Aucun commentaire n'a été effectué sur cette détermination")
@Key("aucunCommentaireEffectue")
String aucunCommentaireEffectue();
 
/**
* Translated "Aucun resultat trouvé".
*
* @return translated "Aucun resultat trouvé"
*/
@DefaultStringValue("Aucun resultat trouvé")
@Key("aucunResultat")
String aucunResultat();
 
/**
* Translated "Aucun vote n'a été effectué sur cette détermination, soyez le premier a voter !".
*
* @return translated "Aucun vote n'a été effectué sur cette détermination, soyez le premier a voter !"
*/
@DefaultStringValue("Aucun vote n'a été effectué sur cette détermination, soyez le premier a voter !")
@Key("aucunVoteEffectue")
String aucunVoteEffectue();
 
/**
* Translated "Publié par".
*
* @return translated "Publié par"
*/
@DefaultStringValue("Publié par")
@Key("auteur")
String auteur();
 
/**
* Translated "Autre".
*
* @return translated "Autre"
*/
@DefaultStringValue("Autre")
@Key("autre")
String autre();
 
/**
* Translated "Autre Proposition".
*
* @return translated "Autre Proposition"
*/
@DefaultStringValue("Autre Proposition")
@Key("autreProposition")
String autreProposition();
 
/**
* Translated "Autres informations ".
*
* @return translated "Autres informations "
*/
@DefaultStringValue("Autres informations ")
@Key("autresInformations")
String autresInformations();
 
/**
* Translated "Valider".
*
* @return translated "Valider"
*/
@DefaultStringValue("Valider")
@Key("boutonProposer")
String boutonProposer();
 
/**
* Translated "Chargement".
*
* @return translated "Chargement"
*/
@DefaultStringValue("Chargement")
@Key("chargement")
String chargement();
 
/**
* Translated "Proposer un nom de plante".
*
* @return translated "Proposer un nom de plante"
*/
@DefaultStringValue("Proposer un nom de plante")
@Key("choisirUnTaxon")
String choisirUnTaxon();
 
/**
* Translated "Commentaire".
*
* @return translated "Commentaire"
*/
@DefaultStringValue("Commentaire")
@Key("commentaire")
String commentaire();
 
/**
* Translated "Commentaires".
*
* @return translated "Commentaires"
*/
@DefaultStringValue("Commentaires")
@Key("commentaires")
String commentaires();
 
/**
* Translated "Commune".
*
* @return translated "Commune"
*/
@DefaultStringValue("Commune")
@Key("commune")
String commune();
 
/**
* Translated "Comparer cette image".
*
* @return translated "Comparer cette image"
*/
@DefaultStringValue("Comparer cette image")
@Key("comparer")
String comparer();
 
/**
* Translated "Probable".
*
* @return translated "Probable"
*/
@DefaultStringValue("Probable")
@Key("confianceProbable")
String confianceProbable();
 
/**
* Translated "Simple Suggestion".
*
* @return translated "Simple Suggestion"
*/
@DefaultStringValue("Simple Suggestion")
@Key("confianceSimpleSuggestion")
String confianceSimpleSuggestion();
 
/**
* Translated "Sûr à 100%".
*
* @return translated "Sûr à 100%"
*/
@DefaultStringValue("Sûr à 100%")
@Key("confianceSurCent")
String confianceSurCent();
 
/**
* Translated "Êtes vous sur de vouloir supprimer ce commentaire ?".
*
* @return translated "Êtes vous sur de vouloir supprimer ce commentaire ?"
*/
@DefaultStringValue("Êtes vous sur de vouloir supprimer ce commentaire ?")
@Key("confirmationSuppressionCommentaire")
String confirmationSuppressionCommentaire();
 
/**
* Translated "Êtes vous sur de vouloir supprimer cette détermination ?".
*
* @return translated "Êtes vous sur de vouloir supprimer cette détermination ?"
*/
@DefaultStringValue("Êtes vous sur de vouloir supprimer cette détermination ?")
@Key("confirmationSuppressionDetermination")
String confirmationSuppressionDetermination();
 
/**
* Translated "Êtes vous sur de vouloir modifier votre observation pour le nom indiqué par cette proposition ?".
*
* @return translated "Êtes vous sur de vouloir modifier votre observation pour le nom indiqué par cette proposition ?"
*/
@DefaultStringValue("Êtes vous sur de vouloir modifier votre observation pour le nom indiqué par cette proposition ?")
@Key("confirmationValidationDetermination")
String confirmationValidationDetermination();
 
/**
* Translated "Contient les mots".
*
* @return translated "Contient les mots"
*/
@DefaultStringValue("Contient les mots")
@Key("contientMots")
String contientMots();
 
/**
* Translated "Contributeur".
*
* @return translated "Contributeur"
*/
@DefaultStringValue("Contributeur")
@Key("contributeur")
String contributeur();
 
/**
* Translated "Courriel".
*
* @return translated "Courriel"
*/
@DefaultStringValue("Courriel")
@Key("courriel")
String courriel();
 
/**
* Translated "Date".
*
* @return translated "Date"
*/
@DefaultStringValue("Date")
@Key("date")
String date();
 
/**
* Translated "Date de la prise de vue".
*
* @return translated "Date de la prise de vue"
*/
@DefaultStringValue("Date de la prise de vue")
@Key("dateObservation")
String dateObservation();
 
/**
* Translated "Le".
*
* @return translated "Le"
*/
@DefaultStringValue("Le")
@Key("dateReleve")
String dateReleve();
 
/**
* Translated "Transmis le".
*
* @return translated "Transmis le"
*/
@DefaultStringValue("Transmis le")
@Key("dateTransmission")
String dateTransmission();
 
/**
* Translated "Date de dernière validation".
*
* @return translated "Date de dernière validation"
*/
@DefaultStringValue("Date de dernière validation")
@Key("dateValidation")
String dateValidation();
 
/**
* Translated "Département (numéro ou nom)".
*
* @return translated "Département (numéro ou nom)"
*/
@DefaultStringValue("Département (numéro ou nom)")
@Key("departement")
String departement();
 
/**
* Translated "Détermination la plus probable : ".
*
* @return translated "Détermination la plus probable : "
*/
@DefaultStringValue("Détermination la plus probable : ")
@Key("determinationPlusProbable")
String determinationPlusProbable();
 
/**
* Translated "éléments par page".
*
* @return translated "éléments par page"
*/
@DefaultStringValue("éléments par page")
@Key("elements_par_page")
String elements_par_page();
 
/**
* Translated "Recherchez par espèce, genre, famille, numéro ou nom de département, commune, auteur ou mot-clé.".
*
* @return translated "Recherchez par espèce, genre, famille, numéro ou nom de département, commune, auteur ou mot-clé."
*/
@DefaultStringValue("Recherchez par espèce, genre, famille, numéro ou nom de département, commune, auteur ou mot-clé.")
@Key("entrerMotClef")
String entrerMotClef();
 
/**
* Translated "Famille (Latin)".
*
* @return translated "Famille (Latin)"
*/
@DefaultStringValue("Famille (Latin)")
@Key("famille")
String famille();
 
/**
* Translated "Fermer".
*
* @return translated "Fermer"
*/
@DefaultStringValue("Fermer")
@Key("fermer")
String fermer();
 
/**
* Translated "Fiabilité".
*
* @return translated "Fiabilité"
*/
@DefaultStringValue("Fiabilité")
@Key("fiabilite")
String fiabilite();
 
/**
* Translated "(jj/mm/aaaa ou aaaa)".
*
* @return translated "(jj/mm/aaaa ou aaaa)"
*/
@DefaultStringValue("(jj/mm/aaaa ou aaaa)")
@Key("formatDate")
String formatDate();
 
/**
* Translated "Genre".
*
* @return translated "Genre"
*/
@DefaultStringValue("Genre")
@Key("genre")
String genre();
 
/**
* Translated "Identifié".
*
* @return translated "Identifié"
*/
@DefaultStringValue("Identifié")
@Key("identifie")
String identifie();
 
/**
* Translated "Photos du Carnet en Ligne".
*
* @return translated "Photos du Carnet en Ligne"
*/
@DefaultStringValue("Photos du Carnet en Ligne")
@Key("imageEflore")
String imageEflore();
 
/**
* Translated "Image n°".
*
* @return translated "Image n°"
*/
@DefaultStringValue("Image n°")
@Key("imageNumero")
String imageNumero();
 
/**
* Translated "Cliquez sur l'image pour l'agrandir ou sur le bandeau contenant le nom pour accéder à la fiche de l'observation".
*
* @return translated "Cliquez sur l'image pour l'agrandir ou sur le bandeau contenant le nom pour accéder à la fiche de l'observation"
*/
@DefaultStringValue("Cliquez sur l'image pour l'agrandir ou sur le bandeau contenant le nom pour accéder à la fiche de l'observation")
@Key("indicationActionClicImage")
String indicationActionClicImage();
 
/**
* Translated "Supprimer ce mot clé".
*
* @return translated "Supprimer ce mot clé"
*/
@DefaultStringValue("Supprimer ce mot clé")
@Key("indiceSupprimerMotCle")
String indiceSupprimerMotCle();
 
/**
* Translated "Saisissez un nom de plante à comparer avec l'image".
*
* @return translated "Saisissez un nom de plante à comparer avec l'image"
*/
@DefaultStringValue("Saisissez un nom de plante à comparer avec l'image")
@Key("infoComparer")
String infoComparer();
 
/**
* Translated "Indiquez votre niveau de certitude vis-à-vis de votre proposition.".
*
* @return translated "Indiquez votre niveau de certitude vis-à-vis de votre proposition."
*/
@DefaultStringValue("Indiquez votre niveau de certitude vis-à-vis de votre proposition.")
@Key("infoFiabilite")
String infoFiabilite();
 
/**
* Translated "Pour proposer un commentaire, remplissez les champs ci-dessous et cliquez sur le bouton Valider !".
*
* @return translated "Pour proposer un commentaire, remplissez les champs ci-dessous et cliquez sur le bouton Valider !"
*/
@DefaultStringValue("Pour proposer un commentaire, remplissez les champs ci-dessous et cliquez sur le bouton Valider !")
@Key("infoProposerCommentaire")
String infoProposerCommentaire();
 
/**
* Translated "Pour proposer une détermination, remplissez les champs ci-dessous et cliquez sur le bouton Proposer !".
*
* @return translated "Pour proposer une détermination, remplissez les champs ci-dessous et cliquez sur le bouton Proposer !"
*/
@DefaultStringValue("Pour proposer une détermination, remplissez les champs ci-dessous et cliquez sur le bouton Proposer !")
@Key("infoProposerDetermination")
String infoProposerDetermination();
 
/**
* Translated "D'autres utilisateurs ont laissé une détermination".
*
* @return translated "D'autres utilisateurs ont laissé une détermination"
*/
@DefaultStringValue("D'autres utilisateurs ont laissé une détermination")
@Key("infoPropositions")
String infoPropositions();
 
/**
* Translated "Tapez les premières lettres d'un nom latin pour voir apparaître des propositions.".
*
* @return translated "Tapez les premières lettres d'un nom latin pour voir apparaître des propositions."
*/
@DefaultStringValue("Tapez les premières lettres d'un nom latin pour voir apparaître des propositions.")
@Key("infoTaxon")
String infoTaxon();
 
/**
* Translated "Voici la moyenne des votes en fonction du protocole choisi :".
*
* @return translated "Voici la moyenne des votes en fonction du protocole choisi :"
*/
@DefaultStringValue("Voici la moyenne des votes en fonction du protocole choisi :")
@Key("infoVotes")
String infoVotes();
 
/**
* Translated "Vos nom et prénom".
*
* @return translated "Vos nom et prénom"
*/
@DefaultStringValue("Vos nom et prénom")
@Key("infoVous")
String infoVous();
 
/**
* Translated "Cette galerie vous permet de rechercher les illustrations des membres du réseau issues du Carnet en ligne... et de voter pour la qualité des images selon un protocole défini.".
*
* @return translated "Cette galerie vous permet de rechercher les illustrations des membres du réseau issues du Carnet en ligne... et de voter pour la qualité des images selon un protocole défini."
*/
@DefaultStringValue("Cette galerie vous permet de rechercher les illustrations des membres du réseau issues du Carnet en ligne... et de voter pour la qualité des images selon un protocole défini.")
@Key("introRechercheImages")
String introRechercheImages();
 
/**
* Translated "Cet espace vous permet d'échanger sur la détermination d'espèces. <br />Vous ne parvenez pas à déterminer une plante ? Soumettez-la aux membres du réseau. <br /> Vous avez relevé des erreurs dans les images soumises par le réseau ? Postez un commentaire ou proposez une nouvelle détermination.".
*
* @return translated "Cet espace vous permet d'échanger sur la détermination d'espèces. <br />Vous ne parvenez pas à déterminer une plante ? Soumettez-la aux membres du réseau. <br /> Vous avez relevé des erreurs dans les images soumises par le réseau ? Postez un commentaire ou proposez une nouvelle détermination."
*/
@DefaultStringValue("Cet espace vous permet d'échanger sur la détermination d'espèces. <br />Vous ne parvenez pas à déterminer une plante ? Soumettez-la aux membres du réseau. <br /> Vous avez relevé des erreurs dans les images soumises par le réseau ? Postez un commentaire ou proposez une nouvelle détermination.")
@Key("introRechercheObservations")
String introRechercheObservations();
 
/**
* Translated "Choisir un protocole".
*
* @return translated "Choisir un protocole"
*/
@DefaultStringValue("Choisir un protocole")
@Key("labelProtocole")
String labelProtocole();
 
/**
* Translated "Ajoutez une image pour participer à ce projet".
*
* @return translated "Ajoutez une image pour participer à ce projet"
*/
@DefaultStringValue("Ajoutez une image pour participer à ce projet")
@Key("legendeAjouterImage")
String legendeAjouterImage();
 
/**
* Translated "Soumettez au réseau une observation à déterminer \n Si vous avez déjà un carnet en ligne, ajoutez votre observation dans le projet \"aDeterminer\"".
*
* @return translated "Soumettez au réseau une observation à déterminer \n Si vous avez déjà un carnet en ligne, ajoutez votre observation dans le projet \"aDeterminer\""
*/
@DefaultStringValue("Soumettez au réseau une observation à déterminer \n Si vous avez déjà un carnet en ligne, ajoutez votre observation dans le projet \"aDeterminer\"")
@Key("legendeAjouterObservation")
String legendeAjouterObservation();
 
/**
* Translated "Propositions ".
*
* @return translated "Propositions "
*/
@DefaultStringValue("Propositions ")
@Key("lesPropositions")
String lesPropositions();
 
/**
* Translated "http://www.tela-botanica.org/page:liste_projets?id_projet=95&act=wikini".
*
* @return translated "http://www.tela-botanica.org/page:liste_projets?id_projet=95&act=wikini"
*/
@DefaultStringValue("http://www.tela-botanica.org/page:liste_projets?id_projet=95&act=wikini")
@Key("lienAideIdentiplante")
String lienAideIdentiplante();
 
/**
* Translated "http://www.tela-botanica.org/page:liste_projets?id_projet=112&act=wikini ".
*
* @return translated "http://www.tela-botanica.org/page:liste_projets?id_projet=112&act=wikini "
*/
@DefaultStringValue("http://www.tela-botanica.org/page:liste_projets?id_projet=112&act=wikini ")
@Key("lienAidePictoflora")
String lienAidePictoflora();
 
/**
* Translated "http://www.tela-botanica.org/widget:cel:saisie?tag-img=aDeterminer&tag-obs=aDeterminer&titre=&titre=Ajouter%20une%20photo%20%26agrave%3B%20d%26eacute%3Bterminer".
*
* @return translated "http://www.tela-botanica.org/widget:cel:saisie?tag-img=aDeterminer&tag-obs=aDeterminer&titre=&titre=Ajouter%20une%20photo%20%26agrave%3B%20d%26eacute%3Bterminer"
*/
@DefaultStringValue("http://www.tela-botanica.org/widget:cel:saisie?tag-img=aDeterminer&tag-obs=aDeterminer&titre=&titre=Ajouter%20une%20photo%20%26agrave%3B%20d%26eacute%3Bterminer")
@Key("lienAppliSaisie")
String lienAppliSaisie();
 
/**
* Translated "http://www.tela-botanica.org/widget:cel:saisie?tag-img={projet}&tag-obs={projet}".
*
* @return translated "http://www.tela-botanica.org/widget:cel:saisie?tag-img={projet}&tag-obs={projet}"
*/
@DefaultStringValue("http://www.tela-botanica.org/widget:cel:saisie?tag-img={projet}&tag-obs={projet}")
@Key("lienAppliSaisieProjetUrl")
String lienAppliSaisieProjetUrl();
 
/**
* Translated "Lieu-dit".
*
* @return translated "Lieu-dit"
*/
@DefaultStringValue("Lieu-dit")
@Key("lieuDit")
String lieuDit();
 
/**
* Translated "Lieu du relevé".
*
* @return translated "Lieu du relevé"
*/
@DefaultStringValue("Lieu du relevé")
@Key("lieuDuReleve")
String lieuDuReleve();
 
/**
* Translated "Localite".
*
* @return translated "Localite"
*/
@DefaultStringValue("Localite")
@Key("localite")
String localite();
 
/**
* Translated "Courriel :".
*
* @return translated "Courriel :"
*/
@DefaultStringValue("Courriel :")
@Key("login")
String login();
 
/**
* Translated "Identiplante permettra bientôt de recevoir des courriels journaliers récapitulant les propositions, commentaires et observations nouvellement ajoutés. En cochant ces cases vous avez la possibilité de recevoir ces courriels dès qu'il seront mis en service (vous pouvez changer cela à tout moment en revenant sur cette interface)".
*
* @return translated "Identiplante permettra bientôt de recevoir des courriels journaliers récapitulant les propositions, commentaires et observations nouvellement ajoutés. En cochant ces cases vous avez la possibilité de recevoir ces courriels dès qu'il seront mis en service (vous pouvez changer cela à tout moment en revenant sur cette interface)"
*/
@DefaultStringValue("Identiplante permettra bientôt de recevoir des courriels journaliers récapitulant les propositions, commentaires et observations nouvellement ajoutés. En cochant ces cases vous avez la possibilité de recevoir ces courriels dès qu'il seront mis en service (vous pouvez changer cela à tout moment en revenant sur cette interface)")
@Key("messageTemporaireMails")
String messageTemporaireMails();
 
/**
* Translated "Famille".
*
* @return translated "Famille"
*/
@DefaultStringValue("Famille")
@Key("metadonneeFamille")
String metadonneeFamille();
 
/**
* Translated "Métadonnées".
*
* @return translated "Métadonnées"
*/
@DefaultStringValue("Métadonnées")
@Key("metadonnees")
String metadonnees();
 
/**
* Translated "Meta-donnees de la photo".
*
* @return translated "Meta-donnees de la photo"
*/
@DefaultStringValue("Meta-donnees de la photo")
@Key("metadonneesPhoto")
String metadonneesPhoto();
 
/**
* Translated "Milieu".
*
* @return translated "Milieu"
*/
@DefaultStringValue("Milieu")
@Key("milieu")
String milieu();
 
/**
* Translated "Mon vote".
*
* @return translated "Mon vote"
*/
@DefaultStringValue("Mon vote")
@Key("monVote")
String monVote();
 
/**
* Translated "Mot-clé".
*
* @return translated "Mot-clé"
*/
@DefaultStringValue("Mot-clé")
@Key("mot_clef")
String mot_clef();
 
/**
* Translated "Mot de passe :".
*
* @return translated "Mot de passe :"
*/
@DefaultStringValue("Mot de passe :")
@Key("motdepasse")
String motdepasse();
 
/**
* Translated "Mots-clés".
*
* @return translated "Mots-clés"
*/
@DefaultStringValue("Mots-clés")
@Key("motsClefs")
String motsClefs();
 
/**
* Translated "Mots Clés".
*
* @return translated "Mots Clés"
*/
@DefaultStringValue("Mots Clés")
@Key("motsCles")
String motsCles();
 
/**
* Translated "Moyenne".
*
* @return translated "Moyenne"
*/
@DefaultStringValue("Moyenne")
@Key("moyenne")
String moyenne();
 
/**
* Translated "vote".
*
* @return translated "vote"
*/
@DefaultStringValue("vote")
@Key("nbVotes")
String nbVotes();
 
/**
* Translated "Nom".
*
* @return translated "Nom"
*/
@DefaultStringValue("Nom")
@Key("nom")
String nom();
 
/**
* Translated "Nom commun".
*
* @return translated "Nom commun"
*/
@DefaultStringValue("Nom commun")
@Key("nomCommun")
String nomCommun();
 
/**
* Translated "Nom retenu".
*
* @return translated "Nom retenu"
*/
@DefaultStringValue("Nom retenu")
@Key("nomRetenu")
String nomRetenu();
 
/**
* Translated "Nb votes".
*
* @return translated "Nb votes"
*/
@DefaultStringValue("Nb votes")
@Key("nombreVotes")
String nombreVotes();
 
/**
* Translated "non".
*
* @return translated "non"
*/
@DefaultStringValue("non")
@Key("non")
String non();
 
/**
* Translated "Observateur".
*
* @return translated "Observateur"
*/
@DefaultStringValue("Observateur")
@Key("observateur")
String observateur();
 
/**
* Translated "Observée le".
*
* @return translated "Observée le"
*/
@DefaultStringValue("Observée le")
@Key("observeLe")
String observeLe();
 
/**
* Translated "ok".
*
* @return translated "ok"
*/
@DefaultStringValue("ok")
@Key("ok")
String ok();
 
/**
* Translated "oui".
*
* @return translated "oui"
*/
@DefaultStringValue("oui")
@Key("oui")
String oui();
 
/**
* Translated "par".
*
* @return translated "par"
*/
@DefaultStringValue("par")
@Key("par")
String par();
 
/**
* Translated "Préférences".
*
* @return translated "Préférences"
*/
@DefaultStringValue("Préférences")
@Key("preferences")
String preferences();
 
/**
* Translated "Prénom".
*
* @return translated "Prénom"
*/
@DefaultStringValue("Prénom")
@Key("prenom")
String prenom();
 
/**
* Translated "proposé par ".
*
* @return translated "proposé par "
*/
@DefaultStringValue("proposé par ")
@Key("proposePar")
String proposePar();
 
/**
* Translated "Proposer une détermination".
*
* @return translated "Proposer une détermination"
*/
@DefaultStringValue("Proposer une détermination")
@Key("proposerSaDetermination")
String proposerSaDetermination();
 
/**
* Translated "Protocole".
*
* @return translated "Protocole"
*/
@DefaultStringValue("Protocole")
@Key("protocole")
String protocole();
 
/**
* Translated "Protocole par défaut".
*
* @return translated "Protocole par défaut"
*/
@DefaultStringValue("Protocole par défaut")
@Key("protocoleDefaut")
String protocoleDefaut();
 
/**
* Translated "Esthétisme".
*
* @return translated "Esthétisme"
*/
@DefaultStringValue("Esthétisme")
@Key("protocoleEsthetisme")
String protocoleEsthetisme();
 
/**
* Translated "Identification automatique".
*
* @return translated "Identification automatique"
*/
@DefaultStringValue("Identification automatique")
@Key("protocoleIdentificationAuto")
String protocoleIdentificationAuto();
 
/**
* Translated "Publiée le".
*
* @return translated "Publiée le"
*/
@DefaultStringValue("Publiée le")
@Key("publiee")
String publiee();
 
/**
* Translated "Recevoir le mail récapitulant les commentaires et propositions faits sur mes observations (1 fois par jour)".
*
* @return translated "Recevoir le mail récapitulant les commentaires et propositions faits sur mes observations (1 fois par jour)"
*/
@DefaultStringValue("Recevoir le mail récapitulant les commentaires et propositions faits sur mes observations (1 fois par jour)")
@Key("recevoirMailsMesObs")
String recevoirMailsMesObs();
 
/**
* Translated "Recevoir le mail récapitulant les nouvelles observations proposées à la détermination (1 fois par jour)".
*
* @return translated "Recevoir le mail récapitulant les nouvelles observations proposées à la détermination (1 fois par jour)"
*/
@DefaultStringValue("Recevoir le mail récapitulant les nouvelles observations proposées à la détermination (1 fois par jour)")
@Key("recevoirMailsToutesObs")
String recevoirMailsToutesObs();
 
/**
* Translated "Recherche avancée".
*
* @return translated "Recherche avancée"
*/
@DefaultStringValue("Recherche avancée")
@Key("rechercheAvancee")
String rechercheAvancee();
 
/**
* Translated "Recherche libre".
*
* @return translated "Recherche libre"
*/
@DefaultStringValue("Recherche libre")
@Key("rechercheLibre")
String rechercheLibre();
 
/**
* Translated "Rechercher".
*
* @return translated "Rechercher"
*/
@DefaultStringValue("Rechercher")
@Key("rechercher")
String rechercher();
 
/**
* Translated "Rechercher et voter".
*
* @return translated "Rechercher et voter"
*/
@DefaultStringValue("Rechercher et voter")
@Key("rechercherImage")
String rechercherImage();
 
/**
* Translated "Identifier une plante".
*
* @return translated "Identifier une plante"
*/
@DefaultStringValue("Identifier une plante")
@Key("rechercherObservation")
String rechercherObservation();
 
/**
* Translated "Rechercher le taxon".
*
* @return translated "Rechercher le taxon"
*/
@DefaultStringValue("Rechercher le taxon")
@Key("rechercherTaxon")
String rechercherTaxon();
 
/**
* Translated "Référentiel".
*
* @return translated "Référentiel"
*/
@DefaultStringValue("Référentiel")
@Key("referentiel")
String referentiel();
 
/**
* Translated "Trachéophytes de France métropolitaine ".
*
* @return translated "Trachéophytes de France métropolitaine "
*/
@DefaultStringValue("Trachéophytes de France métropolitaine ")
@Key("referentielBdtfx")
String referentielBdtfx();
 
/**
* Translated "Trachéophytes des Antilles françaises".
*
* @return translated "Trachéophytes des Antilles françaises"
*/
@DefaultStringValue("Trachéophytes des Antilles françaises")
@Key("referentielBdtxa")
String referentielBdtxa();
 
/**
* Translated "Tous les référentiels".
*
* @return translated "Tous les référentiels"
*/
@DefaultStringValue("Tous les référentiels")
@Key("referentielTous")
String referentielTous();
 
/**
* Translated "Sauvegarder".
*
* @return translated "Sauvegarder"
*/
@DefaultStringValue("Sauvegarder")
@Key("sauvegarder")
String sauvegarder();
 
/**
* Translated "Se déconnecter".
*
* @return translated "Se déconnecter"
*/
@DefaultStringValue("Se déconnecter")
@Key("seDeconnecter")
String seDeconnecter();
 
/**
* Translated "Signaler une mauvaise identification".
*
* @return translated "Signaler une mauvaise identification"
*/
@DefaultStringValue("Signaler une mauvaise identification")
@Key("signalerIdentification")
String signalerIdentification();
 
/**
* Translated "Station".
*
* @return translated "Station"
*/
@DefaultStringValue("Station")
@Key("station")
String station();
 
/**
* Translated "Supprimer votre vote".
*
* @return translated "Supprimer votre vote"
*/
@DefaultStringValue("Supprimer votre vote")
@Key("supprimerVote")
String supprimerVote();
 
/**
* Translated "Tag".
*
* @return translated "Tag"
*/
@DefaultStringValue("Tag")
@Key("tag")
String tag();
 
/**
* Translated "Tag cel".
*
* @return translated "Tag cel"
*/
@DefaultStringValue("Tag cel")
@Key("tagCel")
String tagCel();
 
/**
* Translated "Tag pictoflora".
*
* @return translated "Tag pictoflora"
*/
@DefaultStringValue("Tag pictoflora")
@Key("tagDel")
String tagDel();
 
/**
* Translated "Espèce".
*
* @return translated "Espèce"
*/
@DefaultStringValue("Espèce")
@Key("taxon")
String taxon();
 
/**
* Translated "Taxon à déterminer".
*
* @return translated "Taxon à déterminer"
*/
@DefaultStringValue("Taxon à déterminer")
@Key("taxonADeterminer")
String taxonADeterminer();
 
/**
* Translated "texte de connexion".
*
* @return translated "texte de connexion"
*/
@DefaultStringValue("texte de connexion")
@Key("texteConnexion")
String texteConnexion();
 
/**
* Translated "Détermination / confirmation".
*
* @return translated "Détermination / confirmation"
*/
@DefaultStringValue("Détermination / confirmation")
@Key("titreDetermination")
String titreDetermination();
 
/**
* Translated "Bienvenue".
*
* @return translated "Bienvenue"
*/
@DefaultStringValue("Bienvenue")
@Key("titreEstIdentifie")
String titreEstIdentifie();
 
/**
* Translated "Synthèse de l'observation et des images associées".
*
* @return translated "Synthèse de l'observation et des images associées"
*/
@DefaultStringValue("Synthèse de l'observation et des images associées")
@Key("titrePlateformeDetermination")
String titrePlateformeDetermination();
 
/**
* Translated "Identifiez-vous".
*
* @return translated "Identifiez-vous"
*/
@DefaultStringValue("Identifiez-vous")
@Key("titreSeConnecter")
String titreSeConnecter();
 
/**
* Translated "Transmis le".
*
* @return translated "Transmis le"
*/
@DefaultStringValue("Transmis le")
@Key("transmisLe")
String transmisLe();
 
/**
* Translated "Tri : ".
*
* @return translated "Tri : "
*/
@DefaultStringValue("Tri : ")
@Key("tri")
String tri();
 
/**
* Translated "Date".
*
* @return translated "Date"
*/
@DefaultStringValue("Date")
@Key("triParDate")
String triParDate();
 
/**
* Translated "Tri par date du plus ancien au plus récent".
*
* @return translated "Tri par date du plus ancien au plus récent"
*/
@DefaultStringValue("Tri par date du plus ancien au plus récent")
@Key("triParDateAscendant")
String triParDateAscendant();
 
/**
* Translated "Tri par date du plus récent au plus ancien".
*
* @return translated "Tri par date du plus récent au plus ancien"
*/
@DefaultStringValue("Tri par date du plus récent au plus ancien")
@Key("triParDateDescendant")
String triParDateDescendant();
 
/**
* Translated "Tags".
*
* @return translated "Tags"
*/
@DefaultStringValue("Tags")
@Key("triParNbTags")
String triParNbTags();
 
/**
* Translated "Tri par nombre de tags ascendant".
*
* @return translated "Tri par nombre de tags ascendant"
*/
@DefaultStringValue("Tri par nombre de tags ascendant")
@Key("triParNbTagsAscendant")
String triParNbTagsAscendant();
 
/**
* Translated "Tri par nombre de tags descendant".
*
* @return translated "Tri par nombre de tags descendant"
*/
@DefaultStringValue("Tri par nombre de tags descendant")
@Key("triParNbTagsDescendant")
String triParNbTagsDescendant();
 
/**
* Translated "Votes".
*
* @return translated "Votes"
*/
@DefaultStringValue("Votes")
@Key("triParNbVotes")
String triParNbVotes();
 
/**
* Translated "Tri par nombre de votes du maximum au minimum".
*
* @return translated "Tri par nombre de votes du maximum au minimum"
*/
@DefaultStringValue("Tri par nombre de votes du maximum au minimum")
@Key("triParNbVotesAscendant")
String triParNbVotesAscendant();
 
/**
* Translated "Tri par nombre de votes du minimum au maximum".
*
* @return translated "Tri par nombre de votes du minimum au maximum"
*/
@DefaultStringValue("Tri par nombre de votes du minimum au maximum")
@Key("triParNbVotesDescendant")
String triParNbVotesDescendant();
 
/**
* Translated "Vote".
*
* @return translated "Vote"
*/
@DefaultStringValue("Vote")
@Key("valeurVote")
String valeurVote();
 
/**
* Translated "Validé par".
*
* @return translated "Validé par"
*/
@DefaultStringValue("Validé par")
@Key("validePar")
String validePar();
 
/**
* Translated "Vider".
*
* @return translated "Vider"
*/
@DefaultStringValue("Vider")
@Key("vider")
String vider();
 
/**
* Translated "Voir tous les commentaires ".
*
* @return translated "Voir tous les commentaires "
*/
@DefaultStringValue("Voir tous les commentaires ")
@Key("voirCommentaires")
String voirCommentaires();
 
/**
* Translated "Voir les commentaires liés à cette proposition".
*
* @return translated "Voir les commentaires liés à cette proposition"
*/
@DefaultStringValue("Voir les commentaires liés à cette proposition")
@Key("voirDetailCommentaires")
String voirDetailCommentaires();
 
/**
* Translated "Voir le détail des utilisateurs qui ont voté".
*
* @return translated "Voir le détail des utilisateurs qui ont voté"
*/
@DefaultStringValue("Voir le détail des utilisateurs qui ont voté")
@Key("voirDetailVotes")
String voirDetailVotes();
 
/**
* Translated "Voir la fiche".
*
* @return translated "Voir la fiche"
*/
@DefaultStringValue("Voir la fiche")
@Key("voirFicheIndividu")
String voirFicheIndividu();
 
/**
* Translated "Voir la date, le lieu et l'auteur de l'image".
*
* @return translated "Voir la date, le lieu et l'auteur de l'image"
*/
@DefaultStringValue("Voir la date, le lieu et l'auteur de l'image")
@Key("voirMetadonnees")
String voirMetadonnees();
 
/**
* Translated "Voir et modifier les mots clés associés à l'image".
*
* @return translated "Voir et modifier les mots clés associés à l'image"
*/
@DefaultStringValue("Voir et modifier les mots clés associés à l'image")
@Key("voirMotsCles")
String voirMotsCles();
 
/**
* Translated "Vote modifié".
*
* @return translated "Vote modifié"
*/
@DefaultStringValue("Vote modifié")
@Key("voteModifie")
String voteModifie();
 
/**
* Translated "Vote pris en compte".
*
* @return translated "Vote pris en compte"
*/
@DefaultStringValue("Vote pris en compte")
@Key("votePrisEnCompte")
String votePrisEnCompte();
 
/**
* Translated "Vote supprimé".
*
* @return translated "Vote supprimé"
*/
@DefaultStringValue("Vote supprimé")
@Key("voteSupprime")
String voteSupprime();
 
/**
* Translated "Moyenne des votes".
*
* @return translated "Moyenne des votes"
*/
@DefaultStringValue("Moyenne des votes")
@Key("votes")
String votes();
 
/**
* Translated "Moyenne précise des votes : ".
*
* @return translated "Moyenne précise des votes : "
*/
@DefaultStringValue("Moyenne précise des votes : ")
@Key("votesMoyennePrecise")
String votesMoyennePrecise();
 
/**
* Translated "Votez".
*
* @return translated "Votez"
*/
@DefaultStringValue("Votez")
@Key("votez")
String votez();
 
/**
* Translated "Vous".
*
* @return translated "Vous"
*/
@DefaultStringValue("Vous")
@Key("vous")
String vous();
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/i18n/I18n.java
New file
0,0 → 1,18
package org.tela_botanica.del.client.i18n;
 
import com.google.gwt.core.client.GWT;
 
public class I18n {
public I18n() {
}
 
public static Vocabulary getVocabulary() {
return (Vocabulary) GWT.create(Vocabulary.class);
}
 
public static Messages getMessages() {
return (Messages) GWT.create(Messages.class);
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/supressionmotcleimage/EvenementSuppressionMotCleImage.java
New file
0,0 → 1,45
package org.tela_botanica.del.client.navigation.evenement.supressionmotcleimage;
 
import java.util.ArrayList;
import java.util.List;
 
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementSuppressionMotCleImage extends GwtEvent<GestionnaireEvenementSuppressionMotCleImage> {
 
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementSuppressionMotCleImage> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementSuppressionMotCleImage>();
private String idImage;
private List<String> motsCles;
 
public EvenementSuppressionMotCleImage(String idImage, String motCle) {
this.idImage = idImage;
if(motCle.indexOf(",") != -1) {
String[] motsClesTab = motCle.split(",");
motsCles = new ArrayList<String>(motsClesTab.length);
for (int i = 0; i < motsClesTab.length; i++) {
motsCles.add(motsClesTab[i]);
}
} else {
motsCles = new ArrayList<String>(1);
motsCles.add(motCle);
}
}
 
@Override
protected void dispatch(GestionnaireEvenementSuppressionMotCleImage handler) {
handler.onSuppressionMotCleImage(this);
}
 
public String getIdImage() {
return idImage;
}
public List<String> getMotsCles() {
return motsCles;
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementSuppressionMotCleImage> getAssociatedType() {
return TYPE;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/supressionmotcleimage/GestionnaireEvenementSuppressionMotCleImage.java
New file
0,0 → 1,7
package org.tela_botanica.del.client.navigation.evenement.supressionmotcleimage;
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementSuppressionMotCleImage extends EventHandler {
public void onSuppressionMotCleImage(EvenementSuppressionMotCleImage evenementSuppressionMotCleImage);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/changementEtatUtilisateur/EvenementChangementEtatUtilisateur.java
New file
0,0 → 1,33
package org.tela_botanica.del.client.navigation.evenement.changementEtatUtilisateur;
 
import org.tela_botanica.del.client.modeles.Utilisateur;
 
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementChangementEtatUtilisateur extends GwtEvent<GestionnaireEvenementChangementEtatUtilisateur> {
 
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementChangementEtatUtilisateur> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementChangementEtatUtilisateur>();
private Utilisateur utilisateur;
 
public EvenementChangementEtatUtilisateur(Utilisateur utilisateur) {
this.utilisateur = utilisateur;
}
 
@Override
protected void dispatch(GestionnaireEvenementChangementEtatUtilisateur handler) {
handler.onModificationEtatUtilisateur(this);
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementChangementEtatUtilisateur> getAssociatedType() {
return TYPE;
}
 
public Utilisateur getUtilisateur() {
return utilisateur;
}
 
public void setUtilisateur(Utilisateur utilisateur) {
this.utilisateur = utilisateur;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/changementEtatUtilisateur/GestionnaireEvenementChangementEtatUtilisateur.java
New file
0,0 → 1,7
package org.tela_botanica.del.client.navigation.evenement.changementEtatUtilisateur;
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementChangementEtatUtilisateur extends EventHandler {
 
public void onModificationEtatUtilisateur(EvenementChangementEtatUtilisateur evenementChangementEtatUtilisateur);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/changementimagevalidation/EvenementChangementImageValidation.java
New file
0,0 → 1,23
package org.tela_botanica.del.client.navigation.evenement.changementimagevalidation;
 
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementChangementImageValidation extends GwtEvent<GestionnaireEvenementChangementImageValidation> {
 
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementChangementImageValidation> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementChangementImageValidation>();
 
public EvenementChangementImageValidation() {
 
}
 
@Override
protected void dispatch(GestionnaireEvenementChangementImageValidation handler) {
handler.onChangementImage(this);
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementChangementImageValidation> getAssociatedType() {
return TYPE;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/changementimagevalidation/GestionnaireEvenementChangementImageValidation.java
New file
0,0 → 1,8
package org.tela_botanica.del.client.navigation.evenement.changementimagevalidation;
 
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementChangementImageValidation extends EventHandler {
public void onChangementImage(EvenementChangementImageValidation event);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/fermermotcleimage/GestionnaireEvenementFermerMotCleImage.java
New file
0,0 → 1,7
package org.tela_botanica.del.client.navigation.evenement.fermermotcleimage;
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementFermerMotCleImage extends EventHandler {
public void onFermerMotCleImage(EvenementFermerMotCleImage evenementFermerMotCleImage);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/fermermotcleimage/EvenementFermerMotCleImage.java
New file
0,0 → 1,27
package org.tela_botanica.del.client.navigation.evenement.fermermotcleimage;
 
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementFermerMotCleImage extends GwtEvent<GestionnaireEvenementFermerMotCleImage> {
 
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementFermerMotCleImage> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementFermerMotCleImage>();
private String idImage;
 
public EvenementFermerMotCleImage(String idImage) {
this.idImage = idImage;
}
 
@Override
protected void dispatch(GestionnaireEvenementFermerMotCleImage handler) {
handler.onFermerMotCleImage(this);
}
 
public String getIdImage() {
return idImage;
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementFermerMotCleImage> getAssociatedType() {
return TYPE;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/detailsimage/GestionnaireEvenementRechercheImage.java
New file
0,0 → 1,8
package org.tela_botanica.del.client.navigation.evenement.detailsimage;
 
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementRechercheImage extends EventHandler {
public void onRechercheImage(EvenementRechercheImage event);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/detailsimage/EvenementRechercheImage.java
New file
0,0 → 1,22
package org.tela_botanica.del.client.navigation.evenement.detailsimage;
 
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementRechercheImage extends GwtEvent<GestionnaireEvenementRechercheImage> {
 
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementRechercheImage> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementRechercheImage>();
 
public EvenementRechercheImage() {
}
 
@Override
protected void dispatch(GestionnaireEvenementRechercheImage handler) {
handler.onRechercheImage(this);
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementRechercheImage> getAssociatedType() {
return TYPE;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/validationobservationpictoflora/GestionnaireEvenementValidationPictoflora.java
New file
0,0 → 1,8
package org.tela_botanica.del.client.navigation.evenement.validationobservationpictoflora;
 
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementValidationPictoflora extends EventHandler {
public void onValidationObservation(EvenementValidationPictoflora event);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/validationobservationpictoflora/EvenementValidationPictoflora.java
New file
0,0 → 1,30
package org.tela_botanica.del.client.navigation.evenement.validationobservationpictoflora;
 
import org.tela_botanica.del.client.modeles.Observation;
 
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementValidationPictoflora extends GwtEvent<GestionnaireEvenementValidationPictoflora> {
 
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementValidationPictoflora> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementValidationPictoflora>();
private final Observation observation;
 
public EvenementValidationPictoflora(Observation observation) {
this.observation = observation;
}
@Override
protected void dispatch(GestionnaireEvenementValidationPictoflora handler) {
handler.onValidationObservation(this);
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementValidationPictoflora> getAssociatedType() {
return TYPE;
}
 
public Observation getObservation() {
return observation;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/ajoutmotcleimage/EvenementAjoutMotCleImage.java
New file
0,0 → 1,32
package org.tela_botanica.del.client.navigation.evenement.ajoutmotcleimage;
 
import java.util.ArrayList;
import java.util.List;
 
import org.tela_botanica.del.client.modeles.MotCle;
 
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementAjoutMotCleImage extends GwtEvent<GestionnaireEvenementAjoutMotCleImage> {
 
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementAjoutMotCleImage> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementAjoutMotCleImage>();
private String idImage;
 
public EvenementAjoutMotCleImage(String idImage) {
this.idImage = idImage;
}
 
@Override
protected void dispatch(GestionnaireEvenementAjoutMotCleImage handler) {
handler.onAjoutMotCleImage(this);
}
 
public String getIdImage() {
return idImage;
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementAjoutMotCleImage> getAssociatedType() {
return TYPE;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/ajoutmotcleimage/GestionnaireEvenementAjoutMotCleImage.java
New file
0,0 → 1,7
package org.tela_botanica.del.client.navigation.evenement.ajoutmotcleimage;
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementAjoutMotCleImage extends EventHandler {
public void onAjoutMotCleImage(EvenementAjoutMotCleImage evenementAjoutMotCleImage);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/pagination/EvenementChangementPas.java
New file
0,0 → 1,47
package org.tela_botanica.del.client.navigation.evenement.pagination;
 
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementChangementPas extends GwtEvent<GestionnaireEvenementChangementPas> {
 
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementChangementPas> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementChangementPas>();
 
private int pas;
private String groupePagination = null;
 
public EvenementChangementPas(int pas) {
this.pas = pas;
}
public EvenementChangementPas(int pas, String groupePagination) {
this.pas = pas;
this.groupePagination = groupePagination;
}
 
@Override
protected void dispatch(GestionnaireEvenementChangementPas handler) {
handler.onChangementPas(this);
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementChangementPas> getAssociatedType() {
return TYPE;
}
 
public int getPas() {
return pas;
}
 
public void setPas(int pas) {
this.pas = pas;
}
public String getGroupePagination() {
return groupePagination;
}
 
public void setGroupePagination(String groupePagination) {
this.groupePagination = groupePagination;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/pagination/GestionnaireEvenementChangementPage.java
New file
0,0 → 1,7
package org.tela_botanica.del.client.navigation.evenement.pagination;
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementChangementPage extends EventHandler {
public void onChangementPage(EvenementChangementPage event);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/pagination/GestionnaireEvenementChangementPas.java
New file
0,0 → 1,7
package org.tela_botanica.del.client.navigation.evenement.pagination;
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementChangementPas extends EventHandler {
public void onChangementPas(EvenementChangementPas event);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/pagination/EvenementChangementPage.java
New file
0,0 → 1,46
package org.tela_botanica.del.client.navigation.evenement.pagination;
 
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementChangementPage extends GwtEvent<GestionnaireEvenementChangementPage> {
 
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementChangementPage> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementChangementPage>();
 
private int pageAAfficher;
private String groupePagination = null;
 
public EvenementChangementPage(int pageAAfficher) {
this.pageAAfficher = pageAAfficher;
}
public EvenementChangementPage(int pageAAfficher, String groupePagination) {
this.pageAAfficher = pageAAfficher;
this.groupePagination = groupePagination;
}
 
@Override
protected void dispatch(GestionnaireEvenementChangementPage handler) {
handler.onChangementPage(this);
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementChangementPage> getAssociatedType() {
return TYPE;
}
 
public int getPageAAfficher() {
return pageAAfficher;
}
 
public void setPageAAfficher(int pageAAfficher) {
this.pageAAfficher = pageAAfficher;
}
public String getGroupePagination() {
return groupePagination;
}
 
public void setGroupePagination(String groupePagination) {
this.groupePagination = groupePagination;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/changementPreferences/EvenementChangementPreferences.java
New file
0,0 → 1,22
package org.tela_botanica.del.client.navigation.evenement.changementPreferences;
 
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementChangementPreferences extends GwtEvent<GestionnaireEvenementChangementPreferences> {
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementChangementPreferences> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementChangementPreferences>();
 
public EvenementChangementPreferences() {
 
}
 
@Override
protected void dispatch(GestionnaireEvenementChangementPreferences handler) {
handler.onChangementPreferences(this);
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementChangementPreferences> getAssociatedType() {
return TYPE;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/changementPreferences/GestionnaireEvenementChangementPreferences.java
New file
0,0 → 1,7
package org.tela_botanica.del.client.navigation.evenement.changementPreferences;
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementChangementPreferences extends EventHandler {
public void onChangementPreferences(EvenementChangementPreferences event);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/rechercheimage/GestionnaireEvenementVoirDetailsImage.java
New file
0,0 → 1,8
package org.tela_botanica.del.client.navigation.evenement.rechercheimage;
 
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementVoirDetailsImage extends EventHandler {
public void onVoirDetailsImage(EvenementVoirDetailsImage event);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/rechercheimage/EvenementVoirDetailsImage.java
New file
0,0 → 1,35
package org.tela_botanica.del.client.navigation.evenement.rechercheimage;
 
import org.tela_botanica.del.client.modeles.Image;
 
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementVoirDetailsImage extends GwtEvent<GestionnaireEvenementVoirDetailsImage> {
 
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementVoirDetailsImage> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementVoirDetailsImage>();
 
private Image image;
public EvenementVoirDetailsImage(Image image) {
this.image=image;
}
 
@Override
protected void dispatch(GestionnaireEvenementVoirDetailsImage handler) {
handler.onVoirDetailsImage(this);
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementVoirDetailsImage> getAssociatedType() {
return TYPE;
}
 
public Image getImage() {
return image;
}
 
public void setImage(Image image) {
this.image = image;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/voteDetermination/EvenementVoteDetermination.java
New file
0,0 → 1,33
package org.tela_botanica.del.client.navigation.evenement.voteDetermination;
 
import org.tela_botanica.del.client.modeles.VoteDetermination;
 
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementVoteDetermination extends GwtEvent<GestionnaireEvenementVoteDetermination> {
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementVoteDetermination> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementVoteDetermination>();
private VoteDetermination voteDetermination;
 
public EvenementVoteDetermination(VoteDetermination voteDetermination) {
this.voteDetermination = voteDetermination;
}
 
@Override
protected void dispatch(GestionnaireEvenementVoteDetermination handler) {
handler.onVoteDetermination(this.getVoteDetermination());
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementVoteDetermination> getAssociatedType() {
return TYPE;
}
 
public VoteDetermination getVoteDetermination() {
return voteDetermination;
}
 
public void setVoteDetermination(VoteDetermination voteDetermination) {
this.voteDetermination = voteDetermination;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/voteDetermination/GestionnaireEvenementVoteDetermination.java
New file
0,0 → 1,9
package org.tela_botanica.del.client.navigation.evenement.voteDetermination;
 
import org.tela_botanica.del.client.modeles.VoteDetermination;
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementVoteDetermination extends EventHandler {
public void onVoteDetermination(VoteDetermination event);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/changementprotocole/EvenementChangementProtocole.java
New file
0,0 → 1,34
package org.tela_botanica.del.client.navigation.evenement.changementprotocole;
 
import org.tela_botanica.del.client.modeles.Protocole;
 
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementChangementProtocole extends GwtEvent<GestionnaireEvenementChangementProtocole> {
 
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementChangementProtocole> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementChangementProtocole>();
private Protocole protocole;
 
public EvenementChangementProtocole(Protocole protocole) {
this.protocole = protocole;
}
 
@Override
protected void dispatch(GestionnaireEvenementChangementProtocole handler) {
handler.onChangementProtocole(this);
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementChangementProtocole> getAssociatedType() {
return TYPE;
}
 
public Protocole getProtocole() {
return protocole;
}
 
public void setProtocole(Protocole protocole) {
this.protocole = protocole;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/changementprotocole/GestionnaireEvenementChangementProtocole.java
New file
0,0 → 1,8
package org.tela_botanica.del.client.navigation.evenement.changementprotocole;
 
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementChangementProtocole extends EventHandler {
public void onChangementProtocole(EvenementChangementProtocole event);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/rechercheobservation/GestionnaireEvenementRechercheObservation.java
New file
0,0 → 1,8
package org.tela_botanica.del.client.navigation.evenement.rechercheobservation;
 
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementRechercheObservation extends EventHandler {
public void onRechercheObservation(EvenementRechercheObservation event);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/rechercheobservation/EvenementRechercheObservation.java
New file
0,0 → 1,22
package org.tela_botanica.del.client.navigation.evenement.rechercheobservation;
 
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementRechercheObservation extends GwtEvent<GestionnaireEvenementRechercheObservation> {
 
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementRechercheObservation> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementRechercheObservation>();
 
public EvenementRechercheObservation() {
}
 
@Override
protected void dispatch(GestionnaireEvenementRechercheObservation handler) {
handler.onRechercheObservation(this);
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementRechercheObservation> getAssociatedType() {
return TYPE;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/ajoutdetermination/EvenementAjoutDetermination.java
New file
0,0 → 1,34
package org.tela_botanica.del.client.navigation.evenement.ajoutdetermination;
 
import org.tela_botanica.del.client.modeles.PropositionDetermination;
 
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementAjoutDetermination extends GwtEvent<GestionnaireEvenementAjoutDetermination> {
 
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementAjoutDetermination> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementAjoutDetermination>();
private PropositionDetermination propositionDetermination;
 
public EvenementAjoutDetermination(PropositionDetermination propositionDetermination) {
this.propositionDetermination = propositionDetermination;
}
 
@Override
protected void dispatch(GestionnaireEvenementAjoutDetermination handler) {
handler.onAjoutDetermination(this);
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementAjoutDetermination> getAssociatedType() {
return TYPE;
}
 
public PropositionDetermination getPropositionDetermination() {
return propositionDetermination;
}
 
public void setPropositionDetermination(PropositionDetermination propositionDetermination) {
this.propositionDetermination = propositionDetermination;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/ajoutdetermination/GestionnaireEvenementAjoutDetermination.java
New file
0,0 → 1,8
package org.tela_botanica.del.client.navigation.evenement.ajoutdetermination;
 
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementAjoutDetermination extends EventHandler {
public void onAjoutDetermination(EvenementAjoutDetermination event);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/ajoutcommentaire/GestionnaireEvenementAjoutCommentaire.java
New file
0,0 → 1,8
package org.tela_botanica.del.client.navigation.evenement.ajoutcommentaire;
 
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementAjoutCommentaire extends EventHandler {
public void onAjoutCommentaire(EvenementAjoutCommentaire event);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/ajoutcommentaire/EvenementAjoutCommentaire.java
New file
0,0 → 1,33
package org.tela_botanica.del.client.navigation.evenement.ajoutcommentaire;
 
import org.tela_botanica.del.client.modeles.Commentaire;
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementAjoutCommentaire extends GwtEvent<GestionnaireEvenementAjoutCommentaire> {
 
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementAjoutCommentaire> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementAjoutCommentaire>();
private Commentaire commentaire;
 
public EvenementAjoutCommentaire(Commentaire commentaire) {
this.commentaire = commentaire;
}
 
@Override
protected void dispatch(GestionnaireEvenementAjoutCommentaire handler) {
handler.onAjoutCommentaire(this);
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementAjoutCommentaire> getAssociatedType() {
return TYPE;
}
 
public Commentaire getCommentaire() {
return commentaire;
}
 
public void setPropositionDetermination(Commentaire commentaire) {
this.commentaire = commentaire;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/validationobservation/EvenementValidation.java
New file
0,0 → 1,30
package org.tela_botanica.del.client.navigation.evenement.validationobservation;
 
import org.tela_botanica.del.client.modeles.Observation;
 
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementValidation extends GwtEvent<GestionnaireEvenementValidation> {
 
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementValidation> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementValidation>();
private final Observation observation;
 
public EvenementValidation(Observation observation) {
this.observation = observation;
}
@Override
protected void dispatch(GestionnaireEvenementValidation handler) {
handler.onValidationObservation(this);
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementValidation> getAssociatedType() {
return TYPE;
}
 
public Observation getObservation() {
return observation;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/validationobservation/GestionnaireEvenementValidation.java
New file
0,0 → 1,8
package org.tela_botanica.del.client.navigation.evenement.validationobservation;
 
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementValidation extends EventHandler {
public void onValidationObservation(EvenementValidation event);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/comparaisoneflore/GestionnaireEvenementComparaisonEflore.java
New file
0,0 → 1,8
package org.tela_botanica.del.client.navigation.evenement.comparaisoneflore;
 
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementComparaisonEflore extends EventHandler {
public void onComparaisonEflore(EvenementComparaisonEflore event);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/comparaisoneflore/EvenementComparaisonEflore.java
New file
0,0 → 1,32
package org.tela_botanica.del.client.navigation.evenement.comparaisoneflore;
 
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementComparaisonEflore extends GwtEvent<GestionnaireEvenementComparaisonEflore> {
 
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementComparaisonEflore> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementComparaisonEflore>();
private String taxonDemande;
 
public EvenementComparaisonEflore(String taxonDemande) {
this.taxonDemande = taxonDemande;
}
 
@Override
protected void dispatch(GestionnaireEvenementComparaisonEflore handler) {
handler.onComparaisonEflore(this);
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementComparaisonEflore> getAssociatedType() {
return TYPE;
}
 
public String getTaxonDemande() {
return taxonDemande;
}
 
public void setTaxonDemande(String taxonDemande) {
this.taxonDemande = taxonDemande;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/BusEvenementiel.java
New file
0,0 → 1,109
package org.tela_botanica.del.client.navigation.evenement;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.gestionhistorique.ConstantesNavigation;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.navigation.evenement.comparaisoneflore.EvenementComparaisonEflore;
import org.tela_botanica.del.client.navigation.evenement.comparaisoneflore.GestionnaireEvenementComparaisonEflore;
import org.tela_botanica.del.client.navigation.evenement.detailsimage.EvenementRechercheImage;
import org.tela_botanica.del.client.navigation.evenement.detailsimage.GestionnaireEvenementRechercheImage;
import org.tela_botanica.del.client.navigation.evenement.rechercheobservation.EvenementRechercheObservation;
import org.tela_botanica.del.client.navigation.evenement.rechercheobservation.GestionnaireEvenementRechercheObservation;
import org.tela_botanica.del.client.navigation.evenement.validationobservation.EvenementValidation;
import org.tela_botanica.del.client.navigation.evenement.validationobservation.GestionnaireEvenementValidation;
import org.tela_botanica.del.client.navigation.evenement.validationobservationpictoflora.EvenementValidationPictoflora;
import org.tela_botanica.del.client.navigation.evenement.validationobservationpictoflora.GestionnaireEvenementValidationPictoflora;
 
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.History;
 
public class BusEvenementiel extends HandlerManager {
 
private static BusEvenementiel instance;
private CacheClient cache;
private BusEvenementiel() {
super(null);
instance = this;
creerHandler();
this.cache = CacheClient.getInstance();
}
 
public static BusEvenementiel getInstance() {
if (instance == null) {
instance = new BusEvenementiel();
}
return instance;
}
 
private void creerHandler() {
addHandler(EvenementValidation.TYPE, new GestionnaireEvenementValidation() {
 
@Override
public void onValidationObservation(EvenementValidation event) {
doValidationObservation(event.getObservation());
cache.setPageCourante(ConstantesNavigation.PAGE_VALIDATION);
}
});
addHandler(EvenementValidationPictoflora.TYPE, new GestionnaireEvenementValidationPictoflora() {
@Override
public void onValidationObservation(EvenementValidationPictoflora event) {
doValidationObservationPictoflora(event.getObservation());
cache.setPageCourante(ConstantesNavigation.PAGE_VALIDATION_PICTOFLORA);
}
});
addHandler(EvenementComparaisonEflore.TYPE, new GestionnaireEvenementComparaisonEflore() {
 
@Override
public void onComparaisonEflore(EvenementComparaisonEflore event) {
doComparaisonAvecEflore(event.getTaxonDemande());
cache.setPageCourante(ConstantesNavigation.PAGE_COMPARAISON_EFLORE);
}
});
 
addHandler(EvenementRechercheImage.TYPE, new GestionnaireEvenementRechercheImage() {
 
@Override
public void onRechercheImage(EvenementRechercheImage event) {
doRechercheImage();
cache.setPageCourante(ConstantesNavigation.PAGE_RECHERCHE_IMAGES);
}
});
 
addHandler(EvenementRechercheObservation.TYPE, new GestionnaireEvenementRechercheObservation() {
 
@Override
public void onRechercheObservation(EvenementRechercheObservation event) {
doRechercheObservation();
cache.setPageCourante(ConstantesNavigation.PAGE_RECHERCHE_OBSERVATIONS);
}
});
 
}
 
private void doValidationObservation(Observation observation) {
CacheClient.getInstance().setObservationCourante(observation);
History.newItem(ConstantesNavigation.PAGE_VALIDATION + "~" + observation.getId(), true);
}
private void doValidationObservationPictoflora(Observation observation) {
CacheClient.getInstance().setObservationCourante(observation);
History.newItem(ConstantesNavigation.PAGE_VALIDATION_PICTOFLORA + "~" + observation.getId(), true);
}
 
private void doComparaisonAvecEflore(String taxon) {
History.newItem(ConstantesNavigation.PAGE_COMPARAISON_EFLORE, true);
}
 
private void doRechercheImage() {
History.newItem(ConstantesNavigation.PAGE_RECHERCHE_IMAGES, true);
}
 
private void doRechercheObservation() {
History.newItem(ConstantesNavigation.PAGE_RECHERCHE_OBSERVATIONS, true);
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/suppressiondetermination/EvenementSuppressionDetermination.java
New file
0,0 → 1,34
package org.tela_botanica.del.client.navigation.evenement.suppressiondetermination;
 
import org.tela_botanica.del.client.modeles.PropositionDetermination;
 
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementSuppressionDetermination extends GwtEvent<GestionnaireEvenementSuppressionDetermination> {
 
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementSuppressionDetermination> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementSuppressionDetermination>();
private PropositionDetermination propositionDetermination;
 
public EvenementSuppressionDetermination(PropositionDetermination propositionDetermination) {
this.propositionDetermination = propositionDetermination;
}
 
@Override
protected void dispatch(GestionnaireEvenementSuppressionDetermination handler) {
handler.onSuppressionDetermination(this);
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementSuppressionDetermination> getAssociatedType() {
return TYPE;
}
 
public PropositionDetermination getPropositionDetermination() {
return propositionDetermination;
}
 
public void setPropositionDetermination(PropositionDetermination propositionDetermination) {
this.propositionDetermination = propositionDetermination;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/suppressiondetermination/GestionnaireEvenementSuppressionDetermination.java
New file
0,0 → 1,8
package org.tela_botanica.del.client.navigation.evenement.suppressiondetermination;
 
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementSuppressionDetermination extends EventHandler {
public void onSuppressionDetermination(EvenementSuppressionDetermination event);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/suppressioncommentaire/EvenementSuppressionCommentaire.java
New file
0,0 → 1,33
package org.tela_botanica.del.client.navigation.evenement.suppressioncommentaire;
 
import org.tela_botanica.del.client.modeles.Commentaire;
import com.google.gwt.event.shared.GwtEvent;
 
public class EvenementSuppressionCommentaire extends GwtEvent<GestionnaireEvenementSuppressionCommentaire> {
 
public static com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementSuppressionCommentaire> TYPE = new com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementSuppressionCommentaire>();
private Commentaire commentaire;
 
public EvenementSuppressionCommentaire(Commentaire commentaire) {
this.commentaire = commentaire;
}
 
@Override
protected void dispatch(GestionnaireEvenementSuppressionCommentaire handler) {
handler.onSuppressionCommentaire(this);
}
 
@Override
public com.google.gwt.event.shared.GwtEvent.Type<GestionnaireEvenementSuppressionCommentaire> getAssociatedType() {
return TYPE;
}
 
public Commentaire getCommentaire() {
return commentaire;
}
 
public void setPropositionDetermination(Commentaire commentaire) {
this.commentaire = commentaire;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/navigation/evenement/suppressioncommentaire/GestionnaireEvenementSuppressionCommentaire.java
New file
0,0 → 1,8
package org.tela_botanica.del.client.navigation.evenement.suppressioncommentaire;
 
 
import com.google.gwt.event.shared.EventHandler;
 
public interface GestionnaireEvenementSuppressionCommentaire extends EventHandler {
public void onSuppressionCommentaire(EvenementSuppressionCommentaire event);
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/utils/UtilitairesAutoCompletionService.java
New file
0,0 → 1,89
package org.tela_botanica.del.client.utils;
 
import java.util.HashMap;
import java.util.Map;
 
import com.google.gwt.http.client.Response;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONValue;
 
public class UtilitairesAutoCompletionService {
public static String effectuerPreTraitementChaineRequeteGenreEspeceSlash(String requete) {
String chaineTraitee = requete;
String[] parties = requete.split(" ", 2);
if(parties.length == 2) {
if(parties[1].trim().isEmpty()) {
parties[1] = "*";
}
chaineTraitee = parties[0]+"/"+parties[1];
}
return chaineTraitee;
}
public static String effectuerPreTraitementChaineRequeteGenreEspeceEflore(String requete) {
String chaineTraitee = "?recherche=etendue&ns.structure=au&retour.format=oss&masque="+requete;
return chaineTraitee;
}
public static Map<String, String> extraireTaxonsNumNomsResultatRetourSimple(Response response) {
JSONObject responseValue = JSONParser.parseStrict(response.getText()).isObject();
JSONArray noms = responseValue.get("resultats").isArray();
final int taillemax = noms.size();
Map<String, String> retourTaxons = new HashMap<String, String>(taillemax);
for (int i = 0; i < taillemax; i++) {
String nom = (noms.get(i).isArray().get(0).isString().stringValue());
String taxon = (noms.get(i).isArray().get(1).isString().stringValue());
retourTaxons.put(nom, taxon);
}
return retourTaxons;
}
public static String[] parserResultatRetourSimple(Response response) {
JSONObject responseValue = JSONParser.parseStrict(response.getText()).isObject();
JSONArray noms = responseValue.get("resultats").isArray();
String[] valeurs = new String[0];
final int taillemax = noms.size();
valeurs = new String[taillemax];
for (int i = 0; i < taillemax; i++) {
valeurs[i] = (noms.get(i).isArray().get(0).isString().stringValue());
}
return valeurs;
}
public static String[] parserRetourSimple(Response response) {
final JSONValue responseValue = JSONParser.parseStrict(response.getText());
JSONArray noms;
String[] valeurs = new String[0];
if ((noms=responseValue.isArray()) != null) {
final int taillemax = noms.size();
valeurs = new String[taillemax];
for (int i = 0; i < taillemax; i++) {
valeurs[i] = (noms.get(i).isArray().get(0).isString().stringValue());
}
}
return valeurs;
}
public static String[] parserRetourOss(Response response) {
JSONValue retourJson = JSONParser.parseStrict(response.getText());
JSONArray tableauResultat = retourJson.isArray().get(1).isArray();
String[] suggestions = new String[tableauResultat.size()];
for (int i = 0; i < tableauResultat.size(); i++) {
suggestions[i] = tableauResultat.get(i).isString().stringValue();
}
return suggestions;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/utils/URLUtils.java
New file
0,0 → 1,23
package org.tela_botanica.del.client.utils;
 
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
 
public class URLUtils {
 
/**
* Renvoie le parametre contenu apres le signe ~dans l'url
* Utile pour passer des parametres dynamiquement
* @return
*/
public static String getURLSpecialParameterValue() {
String historyToken = History.getToken();
int debutParam = historyToken.indexOf("~");
String specialParam = null;
if(debutParam != -1) {
specialParam = historyToken.substring(debutParam + 1);
}
return specialParam;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/utils/UtilitairesServiceResultat.java
New file
0,0 → 1,684
package org.tela_botanica.del.client.utils;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.modeles.Commentaire;
import org.tela_botanica.del.client.modeles.Contributeur;
import org.tela_botanica.del.client.modeles.Image;
import org.tela_botanica.del.client.modeles.ImageServiceResultat;
import org.tela_botanica.del.client.modeles.InterventionForum;
import org.tela_botanica.del.client.modeles.MotCle;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.modeles.ObservationServiceResultat;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.modeles.Protocole;
import org.tela_botanica.del.client.modeles.ProtocoleServiceResultat;
import org.tela_botanica.del.client.modeles.Utilisateur;
import org.tela_botanica.del.client.modeles.VoteDetermination;
import org.tela_botanica.del.client.modeles.VoteProtocole;
 
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.Window;
 
/**
* Centralisation des methodes de parsing du code JSON retourné par les
* webservices
*
* @author LIENS
*
*/
public class UtilitairesServiceResultat {
 
/**
* Recupere un objet Image à partir du JSON
*
* @param imageJson
* @return
*/
public static Image parserImageJSON(JSONObject imageJson) {
 
Image image = new Image();
Config config = new Config();
String urlImages = config.getUrl("urlImages");
String idImage = imageJson.get("id_image").isString().stringValue();
image.setIdImage(idImage);
image.setUrlFormat(urlImages + getIdAvecPadding(idImage) + "%s%.jpg");
image.setUrl(urlImages + getIdAvecPadding(idImage) + "CRS.jpg");
image.setMiniature(urlImages + getIdAvecPadding(idImage) + "XS.jpg");
image.setMotsClefs(parserMotsCles(UtilitairesServiceResultat.getValeurOuVide(imageJson, "mots_cles_texte")));
 
return image;
}
 
/**
* Recupere un objet Observation à partir du JSON
*
* @param imageJson
* @return
*/
public static Observation parserObservationJSON(JSONObject observationJson) {
 
Observation observation = new Observation();
observation.setAuteur(getValeurOuVide(observationJson, "auteur.prenom") + " " + getValeurOuVide(observationJson, "auteur.nom"));
observation.setNomAuteur(getValeurOuVide(observationJson, "auteur.nom"));
observation.setPrenomAuteur(getValeurOuVide(observationJson, "auteur.prenom"));
observation.setIdAuteur(getValeurOuVide(observationJson, "auteur.id"));
// TODO: renvoyer le courriel de l'auteur dans les obs
observation.setCourrielAuteur("");
observation.setDateTransmission(getValeurOuVide(observationJson, "date_observation"));
observation.setDateReleve(getValeurOuVide(observationJson, "date_observation"));
observation.setFamille(getValeurOuVide(observationJson, "determination.famille"));
observation.setId(getValeurOuVide(observationJson, "id_observation"));
observation.setIdLocalite(getValeurOuVide(observationJson, "id_zone_geo"));
observation.setLocalite(getValeurOuVide(observationJson, "zone_geo"));
 
String nomRetenu = getValeurOuVide(observationJson, "determination.ns");
observation.setNomRetenu(getValeurOuVide(observationJson, "determination.ns"));
observation.setMilieu(getValeurOuVide(observationJson, "milieu"));
observation.setLieuDit(getValeurOuVide(observationJson, "lieudit"));
observation.setStation(getValeurOuVide(observationJson, "station"));
observation.setCommentaire(getValeurOuVide(observationJson, "commentaire"));
observation.setNumNomenclatural(getValeurOuVide(observationJson, "determination.nn"));
observation.setReferentiel(getValeurOuVide(observationJson, "determination.referentiel"));
observation.setMotsClefs(parserMotsCles(UtilitairesServiceResultat.getValeurOuVide(observationJson, "mots_cles_texte")));
JSONValue propositions = observationJson.get("commentaires");
 
boolean creerPropositionAPartirObs = true;
boolean propositionInitialeExiste = false;
PropositionDetermination propositionPotentiellementInitiale = null;
if (propositions != null && propositions.isObject() != null) {
List<InterventionForum> interventions = parserInterventions(propositions.isObject());
for (InterventionForum interventionForum : interventions) {
interventionForum.setObservation(observation);
// Si une proposition avec le même nom retenu que l'observation
// est déjà présente,
// alors il n'est pas nécessaire de créer la proposition
// "factice"
if (interventionForum instanceof PropositionDetermination) {
PropositionDetermination proposition = (PropositionDetermination) interventionForum;
// Si la proposition correspond au nom retenu (non vide) en cours
if (!nomRetenu.equals("") && proposition.getEspece().equals(nomRetenu)) {
creerPropositionAPartirObs = false;
//proposition.setDate(parserDateObservation(observation.getDateReleve()));
}
if (proposition.getEspece().equals(observation.getNomRetenu()) && proposition.getContributeur().getNomComplet().equals(observation.getAuteur())) {
propositionPotentiellementInitiale = proposition;
}
if (proposition.estPropositionInitiale()) {
propositionInitialeExiste = true;
}
}
}
observation.setInterventionsForum(interventions);
}
if (!propositionInitialeExiste && propositionPotentiellementInitiale != null) {
propositionPotentiellementInitiale.setEstPropositionInitiale(true);
}
if (creerPropositionAPartirObs) {
// Si elle est nécessaire, la proposition factice est ajoutée au
// début
observation.getInterventionsForum().add(0, creerPropositionDeterminationAPartirObservation(observation, propositionInitialeExiste));
}
return observation;
 
}
 
/**
* Créée une proposition de determination à partir d'une observation
*
* @param observation
* @return
*/
private static PropositionDetermination creerPropositionDeterminationAPartirObservation(Observation observation, boolean propositionInitialeExiste) {
 
String utilisateurNom = observation.getNomAuteur();
String utilisateurPrenom = observation.getPrenomAuteur();
 
String utilisateurCourriel = observation.getCourrielAuteur();
String utilisateurId = observation.getIdAuteur();
PropositionDetermination propositionDetermination = new PropositionDetermination(observation);
Contributeur contributeur = new Contributeur(utilisateurId, utilisateurNom, utilisateurPrenom, utilisateurCourriel);
propositionDetermination.setContributeur(contributeur);
java.util.Date datePropDeter = parserDateObservation(observation.getDateTransmission());
propositionDetermination.setDate(datePropDeter);
propositionDetermination.setEspece(observation.getNomRetenu());
if (!propositionInitialeExiste) {
propositionDetermination.setEstPropositionInitiale(true);
}
 
return propositionDetermination;
}
 
/**
* Recupere une liste de commentaires à partir du JSON
*
* @param imageJson
* @return
*/
public static List<Commentaire> parserCommentaires(JSONObject commentaires) {
List<InterventionForum> interventionForums = parserInterventions(commentaires);
List<Commentaire> commentairesListe = new ArrayList<Commentaire>();
for (InterventionForum interventionForum : interventionForums) {
if (interventionForum instanceof Commentaire) {
commentairesListe.add((Commentaire) interventionForum);
}
}
return commentairesListe;
 
}
 
/**
* Recupere une liste d'interventions à partir du JSON
*
* @param imageJson
* @return
*/
public static List<InterventionForum> parserInterventions(JSONObject interventions) {
HashMap<String, InterventionForum> interventionsNonTypees = new HashMap<String, InterventionForum>();
 
List<InterventionForum> retour = new ArrayList<InterventionForum>();
 
// parcourir les interventions et en faire un tableau
if (interventions == null) {
return retour;
}
Iterator<String> itInterventions = interventions.keySet().iterator();
while (itInterventions.hasNext()) {
JSONObject jsonIntervention = interventions.get(itInterventions.next()).isObject();
String nomSel = getValeurOuVide(jsonIntervention, "nom_sel");
 
String id = getValeurOuVide(jsonIntervention, "id_commentaire");
String idParent = getValeurOuVide(jsonIntervention, "id_parent");
String texte = getValeurOuVide(jsonIntervention, "texte");
 
String idUtilisateur = getValeurOuVide(jsonIntervention, "auteur.id");
String nom = getValeurOuVide(jsonIntervention, "auteur.nom");
String prenom = getValeurOuVide(jsonIntervention, "auteur.prenom");
String courriel = getValeurOuVide(jsonIntervention, "auteur.courriel");
Contributeur contributeur = new Contributeur(idUtilisateur, nom, prenom, courriel);
Date date = parserDateObservation(getValeurOuVide(jsonIntervention, "date"));
 
if (!nomSel.equals("")) {
String nom_sel = getValeurOuVide(jsonIntervention, "nom_sel");
String nom_sel_nn = getValeurOuVide(jsonIntervention, "nom_sel_nn");
String nom_ret = getValeurOuVide(jsonIntervention, "nom_ret");
String nom_ret_nn = getValeurOuVide(jsonIntervention, "nom_ret_nn");
String famille = getValeurOuVide(jsonIntervention, "famille");
String nom_referentiel = getValeurOuVide(jsonIntervention, "nom_referentiel");
String nbCommentaires = getValeurOuVide(jsonIntervention, "nb_commentaires");
 
PropositionDetermination intervention = new PropositionDetermination(id, contributeur, texte);
String proposition_initiale = getValeurOuVide(jsonIntervention, "proposition_initiale");
if (proposition_initiale != null && proposition_initiale.equals("1")) {
intervention.setEstPropositionInitiale(true);
} /*else {
String nomRetObs = intervention.getObservation().getNomRetenu();
String auteur = intervention.getObservation().getAuteur();
boolean b = nom_ret.equals(nomRetObs) && intervention.getContributeur().getNomComplet().equals(auteur);
intervention.setEstPropositionInitiale(b);
}*/
// intervention.setObservation(observation);
intervention.setEspece(nom_sel);
 
if (!nbCommentaires.equals("")) {
int nbComm = Integer.parseInt(nbCommentaires);
// if (!texte.equals("")) {
// nbComm++;
// }
intervention.setNbCommentaires(nbComm);
}
 
if (nom_sel_nn != null && !nom_sel_nn.equals("")) {
intervention.setNumNomenclatural(nom_sel_nn);
}
if(nom_referentiel != null && !nom_referentiel.equals("")) {
intervention.setReferentiel(nom_referentiel);
}
if (!idParent.equals("")) {
intervention.setIdParent(idParent);
}
 
if (jsonIntervention.get("votes") != null && jsonIntervention.get("votes").isObject() != null) {
intervention.setVotesDeterminations(parserVotesDetermination(jsonIntervention.get("votes").isObject()));
}
 
intervention.setDate(date);
interventionsNonTypees.put(intervention.getId(), intervention);
 
} else {
Commentaire intervention = new Commentaire(contributeur, date, texte);
intervention.setId(id);
intervention.setDate(date);
interventionsNonTypees.put(intervention.getId(), intervention);
if (!idParent.equals("")) {
intervention.setIdParent(idParent);
}
}
}
 
Iterator<String> itIntervention = interventionsNonTypees.keySet().iterator();
while (itIntervention.hasNext()) {
String id = itIntervention.next();
InterventionForum intervention = interventionsNonTypees.get(id);
String idParent = intervention.getIdParent();
if (idParent != null && !idParent.equals("") && !idParent.equals("0") && interventionsNonTypees.containsKey(idParent)) {
InterventionForum parent = interventionsNonTypees.get(idParent);
intervention.setParent(parent);
parent.ajouterCommentaire((Commentaire) intervention);
} else {
retour.add(intervention);
}
}
 
return retour;
}
 
/**
* Recupere une liste de commentaires à partir du JSON
*
* @param imageJson
* @return
*/
public static String convertirEtParserRetourAjoutCommentaire(String retour) {
JSONObject retourJson = JSONParser.parseStrict(retour).isObject();
return parserRetourAjoutCommentaire(retourJson);
}
 
/**
* Recupere une liste de commentaires à partir d'un objet JSON
*
* @param imageJson
* @return
*/
public static String parserRetourAjoutCommentaire(JSONObject retour) {
String id = "";
if (retour != null) {
id = getValeurOuVide(retour, "id_commentaire");
}
return id;
}
 
public static String getValeurOuVide(JSONObject objet, String index) {
return (objet.get(index) != null && objet.get(index).isString() != null) ? objet.get(index).isString().stringValue() : "";
}
 
/**
* Recupere une liste de votes sur une determination à partir du JSON
*
* @param imageJson
* @return
*/
public static HashMap<String, VoteDetermination> parserRetourListeVotesDetermination(String votesString) {
 
HashMap<String, VoteDetermination> retour = null;
 
JSONObject votes = JSONParser.parseStrict(votesString).isObject();
if (votes != null && votes.get("resultats") != null && votes.get("resultats").isObject() != null) {
JSONObject resultat = votes.get("resultats").isObject();
retour = parserVotesDetermination(resultat);
}
return retour;
}
 
/**
* Recupere une liste de votes sur une determination à partir d'un objet
* JSON
*
* @param imageJson
* @return
*/
public static HashMap<String, VoteDetermination> parserVotesDetermination(JSONObject votes) {
HashMap<String, VoteDetermination> votesDetermination = new HashMap<String, VoteDetermination>();
java.util.Iterator<String> itVotes = votes.keySet().iterator();
while (itVotes.hasNext()) {
JSONObject vote = votes.get(itVotes.next()).isObject();
VoteDetermination vd = new VoteDetermination();
vd.setContributeur(getValeurOuVide(vote, "auteur.id"));
vd.setDate(parserDateObservation(getValeurOuVide(vote, "date")));
vd.setId(getValeurOuVide(vote, "vote.id"));
vd.setVote(Integer.parseInt(getValeurOuVide(vote, "vote")));
vd.setContributeur(getValeurOuVide(vote, "auteur.id"));
 
if (vote.get("auteur.nom") != null && vote.get("auteur.nom") != null && vote.get("auteur.courriel") != null) {
Contributeur auteur = new Contributeur(getValeurOuVide(vote, "auteur.id"), getValeurOuVide(vote, "auteur.nom"), getValeurOuVide(vote, "auteur.prenom"), getValeurOuVide(vote, "auteur.courriel"));
vd.setAuteur(auteur);
}
 
votesDetermination.put(getValeurOuVide(vote, "auteur.id"), vd);
}
return votesDetermination;
}
 
/**
* Recupere une liste de votes sur des images à partir d'un objet JSON
*
* @param imageJson
* @return
*/
public static HashMap<String, HashMap<String, VoteProtocole>> parserVotesProtocoles(JSONObject votes) {
 
HashMap<String, HashMap<String, VoteProtocole>> votesProtocoles = new HashMap<String, HashMap<String, VoteProtocole>>();
java.util.Iterator<String> itProtocoles = votes.keySet().iterator();
while (itProtocoles.hasNext()) {
JSONObject protocole = votes.get(itProtocoles.next()).isObject();
JSONObject votesPourCeProtocoles = protocole.get("votes").isObject();
String idProtocoleVote = protocole.get("protocole.id").isString().stringValue();
java.util.Iterator<String> itVotes = votesPourCeProtocoles.keySet().iterator();
while (itVotes.hasNext()) {
JSONObject voteEnCours = votesPourCeProtocoles.get(itVotes.next()).isObject();
VoteProtocole vd = new VoteProtocole();
vd.setContributeur(voteEnCours.get("auteur.id").isString().stringValue());
vd.setId(voteEnCours.get("vote.id").isString().stringValue());
// TODO récupérer la date du vote et la parser
vd.setDate(parserDateObservation(getValeurOuVide(voteEnCours, "date")));
int valeurVote = Integer.parseInt(voteEnCours.get("vote").isString().stringValue());
vd.setVote(valeurVote);
if (!votesProtocoles.containsKey(idProtocoleVote)) {
votesProtocoles.put(idProtocoleVote, new HashMap<String, VoteProtocole>());
}
votesProtocoles.get(idProtocoleVote).put(vd.getContributeur(), vd);
}
}
 
return votesProtocoles;
}
 
/**
* Recupere une date à partir du JSON
*
* @param imageJson
* @return
*/
public static Date parserDateObservation(String date) {
Date dateParsee = new Date();
DateTimeFormat formatDateObs = DateTimeFormat.getFormat("yyyy-MM-dd HH:mm:ss");
try {
dateParsee = formatDateObs.parse(date);
} catch (IllegalArgumentException e) {
dateParsee = new java.sql.Date(0);
}
return dateParsee;
}
 
/**
* Recupere des mots-clefs à partir du JSON
*
* @param imageJson
* @return
*/
public static List<String> parserMotsCles(String motsClesTexte) {
String[] tabMotsCle = motsClesTexte.split(",");
List<String> motsClesParses = new ArrayList<String>();
for (int i = 0; i < tabMotsCle.length; i++) {
motsClesParses.add(tabMotsCle[i].trim());
}
 
return motsClesParses;
}
 
public static String getIdAvecPadding(String id) {
int maxZeros = 9 - id.length();
for (int i = 0; i < maxZeros; i++) {
id = "0" + id;
}
return id;
}
 
/**
* Recupere un utilisateur à partir du JSON
*
* @param imageJson
* @return
*/
public static Utilisateur parserUtilisateurJson(JSONValue valeurJson) {
 
JSONObject utilisateurJson = valeurJson.isObject();
boolean connecteUtilisateur = utilisateurJson.get("connecte").isBoolean().booleanValue();
String idUtilisateur = utilisateurJson.get("id_utilisateur").isString().stringValue();
String sessionId = utilisateurJson.get("session_id").isString().stringValue();
 
Utilisateur utilisateur;
 
if (connecteUtilisateur) {
String courrielUtilisateur = utilisateurJson.get("courriel").isString().stringValue();
String nomUtilisateur = utilisateurJson.get("nom").isString().stringValue();
String prenomUtilisateur = utilisateurJson.get("prenom").isString().stringValue();
String mdpHashUtilisateur = utilisateurJson.get("mot_de_passe").isString().stringValue();
 
utilisateur = new Utilisateur(sessionId, idUtilisateur, prenomUtilisateur, nomUtilisateur, courrielUtilisateur, mdpHashUtilisateur);
} else {
utilisateur = new Utilisateur(sessionId, idUtilisateur);
}
 
return utilisateur;
}
/**
* Recupere un utilisateur à partir du JSON
*
* @param imageJson
* @return
*/
public static HashMap<String, String> parserPreferencesUtilisateur(JSONValue valeurJson) {
JSONObject utilisateurJson = valeurJson.isObject();
HashMap<String, String> preferences = new HashMap<String, String>();
JSONObject preferencesJson = utilisateurJson.get("preferences").isObject();
java.util.Iterator<String> it = preferencesJson.keySet().iterator();
while (it.hasNext()) {
String cle = it.next();
preferences.put(cle, preferencesJson.get(cle).isString().stringValue());
}
return preferences;
}
 
/**
* Retourne un objet {@link ProtocoleServiceResultat} à partir d'un objet
* JSON
*
* @param retourJson
* @return
*/
public static ProtocoleServiceResultat parserProtocoleServiceResultat(JSONValue retourJson) {
List<Protocole> protocoles = new ArrayList<Protocole>();
JSONObject tableauProto = retourJson.isObject().get("resultats").isObject();
 
if (tableauProto != null) {
java.util.Iterator<String> it = tableauProto.keySet().iterator();
while (it.hasNext()) {
 
JSONObject protocoleJSON = tableauProto.get(it.next()).isObject();
Protocole protocole = new Protocole();
String idProtocole = UtilitairesServiceResultat.getValeurOuVide(protocoleJSON, "protocole.id");
protocole.setId(Integer.parseInt(idProtocole));
protocole.setNom(UtilitairesServiceResultat.getValeurOuVide(protocoleJSON, "protocole.intitule"));
protocole.setDescription(UtilitairesServiceResultat.getValeurOuVide(protocoleJSON, "protocole.descriptif"));
protocole.setTag(UtilitairesServiceResultat.getValeurOuVide(protocoleJSON, "protocole.tag"));
protocole.setMotsClesProtocole(UtilitairesServiceResultat.getValeurOuVide(protocoleJSON, "protocole.mots_cles"));
protocoles.add(protocole);
}
}
 
return new ProtocoleServiceResultat(protocoles);
}
 
/**
* Retourne un objet {@link ImageServiceResultat} à partir du JSON
*
* @param retourJson
* @return
*/
public static ImageServiceResultat parserImageServiceResultat(JSONValue retourJson) {
 
ImageServiceResultat imageServiceResultat = new ImageServiceResultat();
int nbTotalImagesPourLaRecherche;
 
List<Image> images = new ArrayList<Image>();
// TODO ajouter vérifications plus précises
if (retourJson.isObject().get("entete") != null) {
double total = retourJson.isObject().get("entete").isObject().get("total").isNumber().doubleValue();
nbTotalImagesPourLaRecherche = (int) total;
JSONObject tableauImg = retourJson.isObject().get("resultats").isObject();
if (tableauImg != null) {
java.util.Iterator<String> it = tableauImg.keySet().iterator();
while (it.hasNext()) {
JSONObject imageJson = tableauImg.get(it.next()).isObject();
Image image = parserRetourImage(imageJson);
images.add(image);
}
}
 
} else {
JSONArray tableauImg = retourJson.isObject().get("images").isArray();
nbTotalImagesPourLaRecherche = (int) tableauImg.size();
for (int i = 0; i < nbTotalImagesPourLaRecherche; i++) {
JSONObject imageJson = tableauImg.get(i).isObject();
Image image = parserRetourImage(imageJson);
images.add(image);
}
}
 
imageServiceResultat.setImages(images);
imageServiceResultat.setNbTotalImagesPourLaRecherche(nbTotalImagesPourLaRecherche);
 
return imageServiceResultat;
 
}
 
/**
* Retourne un objet {@link Image} à partir du JSON
*
* @param retourJson
* @return
*/
public static Image parserRetourImage(JSONObject imageJson) {
Image image = UtilitairesServiceResultat.parserImageJSON(imageJson);
 
if (imageJson.get("observation") != null && imageJson.get("observation").isObject() != null) {
JSONObject observationJson = imageJson.get("observation").isObject();
image.setObservation(UtilitairesServiceResultat.parserObservationJSON(observationJson));
}
 
if (imageJson.get("protocoles_votes") != null && imageJson.get("protocoles_votes").isObject() != null) {
JSONObject votes = imageJson.get("protocoles_votes").isObject();
image.setVoteProtocoles(UtilitairesServiceResultat.parserVotesProtocoles(votes));
}
 
return image;
}
 
/**
* Retourne un objet {@link ObservationServiceResultat} à partir du JSON
*
* @param retourJson
* @return
*/
public static ObservationServiceResultat parserObservationServiceResultat(JSONValue retourJson) {
 
ObservationServiceResultat observationServiceResultat = new ObservationServiceResultat();
 
List<Observation> observations = new ArrayList<Observation>();
int nbTotalObservationsPourLaRecherche = 0;
 
if (retourJson.isObject().get("entete") != null) {
// TODO ajouter vérifications plus précises
double total = retourJson.isObject().get("entete").isObject().get("total").isNumber().doubleValue();
nbTotalObservationsPourLaRecherche = (int) total;
JSONObject tableauObs = retourJson.isObject().get("resultats").isObject();
 
if (tableauObs != null) {
java.util.Iterator<String> it = tableauObs.keySet().iterator();
while (it.hasNext()) {
JSONObject observationJson = tableauObs.get(it.next()).isObject();
Observation observation = analyserObservation(observationJson);
observations.add(observation);
}
}
} else {
JSONObject observationJson = retourJson.isObject();
Observation observation = analyserObservation(observationJson);
observations.add(observation);
CacheClient.getInstance().setObservationCourante(observation);
}
 
observationServiceResultat.setObservations(observations);
observationServiceResultat.setNbTotalObservationsPourLaRecherche(nbTotalObservationsPourLaRecherche);
 
return observationServiceResultat;
}
 
/**
* Retourne un objet {@link Observation} avec ses {@link Image} associées à
* partir du JSON
*
* @param retourJson
* @return
*/
private static Observation analyserObservation(JSONObject observationJson) {
Observation observation = UtilitairesServiceResultat.parserObservationJSON(observationJson);
JSONArray tableauImagesObs = observationJson.get("images").isArray();
List<Image> imagesPourObs = new ArrayList<Image>();
 
int nbImages = tableauImagesObs.size();
for (int j = 0; j < nbImages; j++) {
JSONObject imageJson = tableauImagesObs.get(j).isObject();
 
Image image = UtilitairesServiceResultat.parserImageJSON(imageJson);
if (imageJson.get("protocoles_votes") != null && imageJson.get("protocoles_votes").isObject() != null) {
JSONObject votes = imageJson.get("protocoles_votes").isObject();
image.setVoteProtocoles(UtilitairesServiceResultat.parserVotesProtocoles(votes));
}
image.setObservation(observation);
imagesPourObs.add(image);
}
 
observation.setImages(imagesPourObs);
 
return observation;
}
 
public static List<MotCle> parserRetourListeMotsClesImage(JSONObject retourJson) {
List<MotCle> motsCles = new ArrayList<MotCle>();
JSONObject tableauMc = retourJson;
if (tableauMc != null) {
java.util.Iterator<String> it = tableauMc.keySet().iterator();
while (it.hasNext()) {
JSONObject mc = tableauMc.get(it.next()).isObject();
MotCle motCle = new MotCle(getValeurOuVide(mc, "id_mot_cle"), getValeurOuVide(mc, "image"), getValeurOuVide(mc, "mot_cle"));
motsCles.add(motCle);
}
}
return motsCles;
}
 
public static String parserRetourAjoutVoteProtocole(JSONObject retour) {
String id = "";
if (retour != null) {
id = getValeurOuVide(retour, "id_vote");
}
return id;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/utils/StringUtils.java
New file
0,0 → 1,33
package org.tela_botanica.del.client.utils;
 
public class StringUtils {
public static boolean checkStringNotNull(String s){
if(s!=null&&!s.equals("")){
return true;
}
return false;
}
public static String normaliser(String mot) {
mot = mot.toLowerCase().trim().replace(" ", "");
// Le manque de support des librairies standard java
// nous oblige à utiliser cette méthode un peu batarde
char[] accents = {'à','á','â','ã','ä','ç','è','é','ê','ë','ì','í','î','ï','ñ','ò','ó','ô','õ','ö','ù','ú','û','ü','ý','ÿ','À','Á','Â','Ã','Ä','Ç','È','É','Ê','Ë', 'Ì','Í','Î','Ï','Ñ','Ò','Ó','Ô','Õ','Ö','Ù','Ú','Û','Ü','Ý'};
char[] sansAccents = {'a','a','a','a','a','c', 'e','e','e','e','i','i','i','i','n','o','o','o','o','o','u','u','u','u', 'y','y','A','A','A','A','A','C','E','E','E','E','I','I','I','I','N','O','O','O','O','O','U','U','U','U','Y'};
for (int i = 0; i < accents.length; i++) {
mot = mot.replace(accents[i], sansAccents[i]);
}
return mot;
}
public static native void logChaine(String s) /*-{
if(!!($wnd.console && $wnd.console.log)) {
$wnd.console.log(s);
}
}-*/;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/utils/ComparateurPropositionDetermination.java
New file
0,0 → 1,41
package org.tela_botanica.del.client.utils;
 
import java.util.Comparator;
 
import org.tela_botanica.del.client.modeles.InterventionForum;
import org.tela_botanica.del.client.modeles.MoyenneVote;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.services.CalculVoteDeterminationService;
 
import com.google.gwt.user.client.Window;
 
public class ComparateurPropositionDetermination implements Comparator<InterventionForum> {
 
@Override
public int compare(InterventionForum intervention1, InterventionForum intervention2) {
int entierRetour = 0;
if (intervention1 instanceof PropositionDetermination && intervention2 instanceof PropositionDetermination) {
PropositionDetermination proposition1 = (PropositionDetermination) intervention1;
PropositionDetermination proposition2 = (PropositionDetermination) intervention2;
// si 1 est prop et 2 est prop
MoyenneVote moyenneP1 = CalculVoteDeterminationService.calculerVoteDetermination(proposition1);
int scoreP1 = moyenneP1.getScore();
MoyenneVote moyenneP2 = CalculVoteDeterminationService.calculerVoteDetermination(proposition2);
int scoreP2 = moyenneP2.getScore();
if (scoreP1 < scoreP2) {
entierRetour = 1;
}
} else {
entierRetour = 1;
}
//si 1 est prop et 2 est comm OU si 1 est comm et 2 est prop ou les 2 sont comm
return entierRetour;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/exceptions/ExceptionClient.java
New file
0,0 → 1,42
package org.tela_botanica.del.client.exceptions;
 
import com.google.gwt.user.client.rpc.IsSerializable;
 
/**
* An exception that can be displayed on the client side. It can receive an
* exception from server and display the message in the client.
*
* @author Benjamin
*
*/
public class ExceptionClient extends Exception implements IsSerializable {
 
/**
*
*/
private static final long serialVersionUID = 636898773374000925L;
 
private String clientMessage;
 
public ExceptionClient(String exceptionMessage) {
super();
clientMessage = exceptionMessage;
}
 
public ExceptionClient(Exception e) {
super(e);
clientMessage = e.getMessage();
}
 
public ExceptionClient() {
}
 
public String getClientMessage() {
return clientMessage;
}
 
public void setClientMessage(String clientMessage) {
this.clientMessage = clientMessage;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/comparaisoneflore/ComparaisonEfloreVue.ui.xml
New file
0,0 → 1,77
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
 
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
 
<ui:with field='res' type='org.tela_botanica.del.client.resources.Ressources' />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
<ui:style src="comparaisonEflore.css" />
<g:HTMLPanel >
<g:HTMLPanel ui:field="formulaireRecherche" styleName="{style.zoneComparaison}" />
<g:HorizontalPanel styleName="{style.zoneComparaison}" >
<g:VerticalPanel styleName="{style.photoPrincipale} arrondi">
<g:Label text="{constants.taxonADeterminer}" styleName="titre" />
<g:Label text="{constants.taxonADeterminer}" styleName="petit" />
<g:Image ui:field="imagePrincipale" />
 
<g:HTMLPanel styleName="{style.meta}">
<g:Label text="{constants.metadonneesPhoto}" styleName="titre" />
<g:Label ui:field="nomAuteurTitre" text="{constants.observateur}" styleName="petit" />
<g:Label ui:field="nomAuteur" />
<g:Label ui:field="dateObservationTitre" text="{constants.dateObservation}" styleName="petit" />
<g:Label ui:field="dateObservation" />
<g:Label ui:field="familleTitre" text="{constants.famille}" styleName="petit" />
<g:Label ui:field="famille" />
<g:Label ui:field="commentairesTitre" text="{constants.commentaires}" styleName="petit" />
<g:Label ui:field="commentaires" />
<g:Label ui:field="motsClefsTitre" text="{constants.motsClefs}" styleName="petit" />
<g:Label ui:field="motsClefs" />
<g:Label ui:field="nomRetenuTitre" text="{constants.nomRetenu}" styleName="petit" />
<g:Label ui:field="nomRetenu" />
<g:Label ui:field="nomCommunTitre" styleName="petit" text="{constants.nomCommun}" />
<g:Label ui:field="nomCommun" />
<g:Label ui:field="localiteTitre" styleName="petit" text="{constants.lieuDuReleve}" />
<g:Label ui:field="localite" />
<g:Label ui:field="milieuTitre" styleName="petit" text="{constants.milieu}" />
<g:Label ui:field="milieu"/>
</g:HTMLPanel>
</g:VerticalPanel>
<g:VerticalPanel styleName="{style.photoComparee} arrondi">
<g:Label text="{constants.imageEflore}" styleName="titre" />
<g:Label ui:field="texteEflore" text="{constants.imageEflore}" styleName="petit" />
 
<g:Image ui:field="imageEflore" />
<g:VerticalPanel ui:field="panneauChargement" styleName="{style.panneauChargement}" >
<g:Image url="./img/wait.gif" ></g:Image>
</g:VerticalPanel>
<g:HorizontalPanel styleName="{style.fleches}">
<g:Image ui:field="scrollLeftImage" resource='{res.arrowLeft}'
styleName="gauche" visible="false" />
<g:Image ui:field="scrollRightImage" resource='{res.arrowRight}'
styleName="droite" visible="false" />
</g:HorizontalPanel>
 
<g:HTMLPanel ui:field="metadonneesEflore" styleName="{style.meta}">
<g:Label text="{constants.metadonneesPhoto}" styleName="titre" />
 
<g:Label text="{constants.taxon}" styleName="petit" />
<g:Label ui:field="nomEspeceEflore" />
 
<g:Label text="{constants.localite}" styleName="petit" />
<g:Label ui:field="localiteEflore" />
 
<g:Label text="{constants.auteur}" styleName="petit" />
<g:Label ui:field="nomAuteurEflore" />
 
<g:Label text="{constants.transmisLe}" styleName="petit" />
<g:Label ui:field="dateObservationEflore" />
</g:HTMLPanel>
</g:VerticalPanel>
</g:HorizontalPanel>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/comparaisoneflore/ComparaisonEflorePresenteur.java
New file
0,0 → 1,183
package org.tela_botanica.del.client.vues.comparaisoneflore;
 
import java.util.ArrayList;
import java.util.List;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlayDefilanteVue;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlaySimplePresenteur;
import org.tela_botanica.del.client.composants.formulairerechercheeflore.FormulaireRechercheEflorePresenteur;
import org.tela_botanica.del.client.composants.images.DetailImagePresenteur;
import org.tela_botanica.del.client.composants.images.DetailImageVue;
import org.tela_botanica.del.client.modeles.Image;
import org.tela_botanica.del.client.modeles.ImageServiceResultat;
import org.tela_botanica.del.client.modeles.InformationsRecherche;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.comparaisoneflore.EvenementComparaisonEflore;
import org.tela_botanica.del.client.navigation.evenement.comparaisoneflore.GestionnaireEvenementComparaisonEflore;
import org.tela_botanica.del.client.services.rest.ImageService;
import org.tela_botanica.del.client.services.rest.async.ImagesParTaxonCallback;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class ComparaisonEflorePresenteur {
 
public interface Vue extends IsWidget {
public void chargerImagePrincipale(org.tela_botanica.del.client.modeles.Image image);
 
public void chargerImagesEflore(List<org.tela_botanica.del.client.modeles.Image> observationsEflore, int indexImage);
 
public HasClickHandlers getScrollLeftImage();
 
public HasClickHandlers getScrollRightImage();
 
public int getCurrentIndexImages();
 
public void startChargement();
 
public void stopChargement();
 
public void afficherAucuneImageTrouvee();
 
public HTMLPanel getFormulaireRecherche();
public void setCurrentIndexImages(int index);
public com.google.gwt.user.client.ui.Image getImagePrincipale();
public com.google.gwt.user.client.ui.Image getImageEflore();
}
 
private Vue vue;
private final ImageService imageService;
 
private Image imagePrincipale;
private String nomTaxonComparaison;
private List<org.tela_botanica.del.client.modeles.Image> imagesEflore = new ArrayList<Image>();
private int page = 0;
private int nbImagesPreFetch = 10;
 
public ComparaisonEflorePresenteur(Vue vue, ImageService imageService) {
this.vue = vue;
this.imagePrincipale = CacheClient.getInstance().getImageCourante();
this.nomTaxonComparaison = CacheClient.getInstance().getTaxonPourRechercheEflore();
this.imageService = imageService;
}
 
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
vue.chargerImagePrincipale(imagePrincipale);
chargerObservationsEflore();
gererEvenements();
new FormulaireRechercheEflorePresenteur().go(vue.getFormulaireRecherche());
}
 
public void chargerObservationsEflore() {
 
int debut = (page * nbImagesPreFetch) + 1;
int fin = (page + 1) * nbImagesPreFetch;
 
vue.startChargement();
 
InformationsRecherche informationsRecherche = new InformationsRecherche();
informationsRecherche.setTaxon(nomTaxonComparaison);
 
ImagesParTaxonCallback callback = new ImagesParTaxonCallback() {
 
@Override
public void surRetour(ImageServiceResultat imagesRecues) {
if (imagesRecues == null || imagesRecues.getImages() == null || imagesRecues.getImages().size() == 0) {
vue.afficherAucuneImageTrouvee();
} else {
addImagesEflore(imagesRecues.getImages());
vue.stopChargement();
vue.chargerImagesEflore(imagesEflore, vue.getCurrentIndexImages());
}
}
 
@Override
public void surErreur(String messageErreur) {
vue.afficherAucuneImageTrouvee();
Window.alert(messageErreur);
}
 
};
 
imageService.getImagesParTaxon(informationsRecherche, debut, fin, callback);
 
}
 
private void gererEvenements() {
vue.getScrollLeftImage().addClickHandler(new ClickHandler() {
 
@Override
public void onClick(ClickEvent event) {
vue.chargerImagesEflore(imagesEflore, vue.getCurrentIndexImages() - 1);
}
});
 
vue.getScrollRightImage().addClickHandler(new ClickHandler() {
 
@Override
public void onClick(ClickEvent event) {
 
if (vue.getCurrentIndexImages() == imagesEflore.size() - 1) {
page += 1;
vue.setCurrentIndexImages(vue.getCurrentIndexImages()+1);
chargerObservationsEflore();
} else {
vue.chargerImagesEflore(imagesEflore, vue.getCurrentIndexImages() + 1);
}
}
});
 
BusEvenementiel.getInstance().addHandler(EvenementComparaisonEflore.TYPE, new GestionnaireEvenementComparaisonEflore() {
 
@Override
public void onComparaisonEflore(EvenementComparaisonEflore event) {
nomTaxonComparaison = event.getTaxonDemande();
page=0;
vue.setCurrentIndexImages(0);
getImagesEflore().clear();
chargerObservationsEflore();
}
});
vue.getImagePrincipale().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent arg0) {
FenetreOverlaySimplePresenteur presenteurGalerie = new FenetreOverlaySimplePresenteur(new FenetreOverlayDefilanteVue());
presenteurGalerie.ouvrirFenetreModaleDefilante(0, new DetailImagePresenteur(imagePrincipale, new DetailImageVue()));
presenteurGalerie.afficherBoutonsSuivantsPrecedents(false);
}
});
vue.getImageEflore().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent arg0) {
FenetreOverlaySimplePresenteur presenteurGalerie = new FenetreOverlaySimplePresenteur(new FenetreOverlayDefilanteVue());
presenteurGalerie.ouvrirFenetreModaleDefilante(0, new DetailImagePresenteur(imagesEflore.get(vue.getCurrentIndexImages()), new DetailImageVue()));
presenteurGalerie.afficherBoutonsSuivantsPrecedents(false);
}
});
}
 
public List<org.tela_botanica.del.client.modeles.Image> getImagesEflore() {
return imagesEflore;
}
 
public void addImagesEflore(List<org.tela_botanica.del.client.modeles.Image> imagesEflore) {
this.imagesEflore.addAll(imagesEflore);
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/comparaisoneflore/ComparaisonEfloreVue.java
New file
0,0 → 1,202
package org.tela_botanica.del.client.vues.comparaisoneflore;
 
import java.util.List;
 
import org.tela_botanica.del.client.i18n.I18n;
import org.tela_botanica.del.client.utils.StringUtils;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class ComparaisonEfloreVue extends Composite implements ComparaisonEflorePresenteur.Vue {
 
interface MyUiBinder extends UiBinder<Widget, ComparaisonEfloreVue> {
}
 
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
private int currentIndexImages=0;
 
@UiField
Label nomAuteur, dateObservation, famille, motsClefs, nomRetenu, nomCommun, localite, milieu, commentaires, nomEspeceEflore, nomAuteurEflore, localiteEflore, dateObservationEflore, texteEflore;
 
@UiField
Label nomAuteurTitre, dateObservationTitre, familleTitre, motsClefsTitre, nomRetenuTitre, nomCommunTitre, localiteTitre, milieuTitre, commentairesTitre;
 
@UiField
Image imagePrincipale, imageEflore, scrollLeftImage, scrollRightImage;
 
@UiField
Panel panneauChargement;
 
@UiField
HTMLPanel formulaireRecherche, metadonneesEflore;
 
public ComparaisonEfloreVue() {
initWidget(uiBinder.createAndBindUi(this));
}
 
public void chargerImagePrincipale(org.tela_botanica.del.client.modeles.Image image) {
 
// mots clefs
String motsClefsConcatenes = "";
try {
for (String motClef : image.getObservation().getMotsClefs()) {
motsClefsConcatenes += motClef + ",";
}
motsClefsConcatenes = motsClefsConcatenes.subSequence(0, motsClefsConcatenes.lastIndexOf(",")).toString();
} catch (Exception e) {
// TODO: handle exception
}
 
if (StringUtils.checkStringNotNull(motsClefsConcatenes)) {
motsClefs.setText(motsClefsConcatenes);
} else {
motsClefs.setVisible(false);
motsClefsTitre.setVisible(false);
}
if (StringUtils.checkStringNotNull(image.getObservation().getAuteur())) {
nomAuteur.setText(image.getObservation().getAuteur());
} else {
nomAuteur.setVisible(false);
nomAuteurTitre.setVisible(false);
}
if (StringUtils.checkStringNotNull(image.getUrl())) {
imagePrincipale.setUrl(image.getUrl());
}
if (StringUtils.checkStringNotNull(image.getObservation().getDateReleve())) {
dateObservation.setText(image.getObservation().getDateReleve());
} else {
dateObservation.setVisible(false);
dateObservationTitre.setVisible(false);
}
if (StringUtils.checkStringNotNull(image.getObservation().getFamille())) {
famille.setText(image.getObservation().getFamille());
} else {
famille.setVisible(false);
familleTitre.setVisible(false);
}
if (StringUtils.checkStringNotNull(image.getObservation().getNomRetenu())) {
nomRetenu.setText(image.getObservation().getNomRetenuFormateReferentiel());
} else {
nomRetenu.setVisible(false);
nomRetenuTitre.setVisible(false);
}
if (StringUtils.checkStringNotNull(image.getObservation().getNomCommun())) {
nomCommun.setText(image.getObservation().getNomCommun());
} else {
nomCommun.setVisible(false);
nomCommunTitre.setVisible(false);
}
if (StringUtils.checkStringNotNull(image.getObservation().getLocaliteAvecIdFormatee())) {
localite.setText(image.getObservation().getLocaliteAvecIdFormatee());
} else {
localite.setVisible(false);
localiteTitre.setVisible(false);
}
if (StringUtils.checkStringNotNull(image.getObservation().getMilieu())) {
milieu.setText(image.getObservation().getMilieu());
} else {
milieu.setVisible(false);
milieuTitre.setVisible(false);
}
if (StringUtils.checkStringNotNull(image.getObservation().getCommentaire())) {
commentaires.setText(image.getObservation().getCommentaire());
} else {
commentaires.setVisible(false);
commentairesTitre.setVisible(false);
}
 
}
 
public void chargerImagesEflore(List<org.tela_botanica.del.client.modeles.Image> observationsEflore, int indexImage) {
 
texteEflore.setText(I18n.getVocabulary().imageEflore());
 
if (indexImage >= 0 && indexImage < observationsEflore.size()) {
currentIndexImages = indexImage;
}
 
org.tela_botanica.del.client.modeles.Image observationEflore = observationsEflore.get(currentIndexImages);
 
nomEspeceEflore.setText(observationEflore.getObservation().getNomRetenuFormateReferentiel());
nomAuteurEflore.setText(observationEflore.getObservation().getAuteur());
imageEflore.setUrl(observationEflore.getUrl());
dateObservationEflore.setText(observationEflore.getObservation().getDateReleve());
localiteEflore.setText(observationEflore.getObservation().getLocalite());
metadonneesEflore.setVisible(true);
imageEflore.setVisible(true);
 
if (observationsEflore.size() > 1) {
scrollLeftImage.setVisible(true);
scrollRightImage.setVisible(true);
}
}
 
public void setScrollLeftImage(Image scrollLeftImage) {
this.scrollLeftImage = scrollLeftImage;
}
 
public int getCurrentIndexImages() {
return currentIndexImages;
}
 
@Override
public HasClickHandlers getScrollLeftImage() {
return scrollLeftImage;
}
 
@Override
public HasClickHandlers getScrollRightImage() {
return scrollRightImage;
}
 
public void startChargement() {
texteEflore.setText(I18n.getVocabulary().chargement());
metadonneesEflore.setVisible(false);
imageEflore.setVisible(false);
scrollLeftImage.setVisible(false);
scrollRightImage.setVisible(false);
panneauChargement.setVisible(true);
}
 
public void stopChargement() {
panneauChargement.setVisible(false);
}
 
public void afficherAucuneImageTrouvee() {
texteEflore.setText(I18n.getVocabulary().aucunResultat());
scrollLeftImage.setVisible(false);
scrollRightImage.setVisible(false);
panneauChargement.setVisible(false);
}
 
public Label getNomAuteur() {
return nomAuteur;
}
 
public Image getImagePrincipale() {
return imagePrincipale;
}
 
public HTMLPanel getFormulaireRecherche() {
return formulaireRecherche;
}
 
public void setCurrentIndexImages(int index){
currentIndexImages=index;
}
 
public Image getImageEflore() {
return imageEflore;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/comparaisoneflore/comparaisonEflore.css
New file
0,0 → 1,49
.zoneComparaison {
width: 50%;
margin: 0 auto;
height: 100%
}
 
.photoComparee {
width: 500px;
margin-left: 5px;
padding: 20px;
border: #DDD solid 1px;
}
 
.photoPrincipale img,.photoComparee img {
-moz-box-shadow: 4px 4px 2px #AAA;
cursor: pointer;
}
 
.panneauChargement img{
-moz-box-shadow: none;
}
 
.photoPrincipale {
width: 500px;
border: #DDD solid 1px;
padding: 20px;
height: 100%
}
 
.fleches {
position: absolute;
margin-left: -20px;
padding: 20px;
margin-top: -50px;
width: 500px;
}
 
.fleches img {
cursor: pointer;
-moz-box-shadow: 0px 0px 0px #000
}
 
.meta {
color: white;
background: #333;
padding: 10px;
opacity: 0.8em;
margin-top: 5px
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/moteur/MoteurIdentiplantePresenteur.java
New file
0,0 → 1,128
package org.tela_botanica.del.client.vues.identiplante.moteur;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.moteurrecherche.MoteurRecherchePresenteur;
import org.tela_botanica.del.client.composants.moteurrecherche.MoteurRechercheVue;
import org.tela_botanica.del.client.composants.partageurl.PartageUrlPresenteur;
import org.tela_botanica.del.client.composants.partageurl.PartageUrlVue;
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.modeles.ModeRecherche;
import org.tela_botanica.del.client.services.rest.ObservationService;
import org.tela_botanica.del.client.services.rest.ObservationServiceConcret;
import org.tela_botanica.del.client.vues.identiplante.resultats.ResultatsIdentiplantePresenteur;
import org.tela_botanica.del.client.vues.identiplante.resultats.ResultatsIdentiplanteVue;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Panel;
 
public class MoteurIdentiplantePresenteur extends Presenteur {
 
public interface Vue extends IsWidget {
public HasWidgets getZoneRecherche();
 
public HasWidgets getZoneResultats();
 
public HasClickHandlers getOngletEnDiscussion();
public HasClickHandlers getOngletADeterminer();
public HasClickHandlers getOngletTout();
 
public HasClickHandlers getOngletValidees();
public void setOngletADeterminerActif();
public void setOngletToutActif();
public void setOngletEnDiscussionActif();
 
public void setOngletValideesActif();
}
 
private Vue vue;
 
public MoteurIdentiplantePresenteur(ObservationService serviceObs, Vue vue) {
this.vue = vue;
}
 
public void go(HasWidgets composite) {
 
composite.add(vue.asWidget());
ajouterMoteurRechercheAvancee();
gererEvenements();
}
 
protected void ajouterMoteurRechercheAvancee() {
MoteurRecherchePresenteur presenteur = new MoteurRecherchePresenteur(new MoteurRechercheVue("") {
}, ModeRecherche.MODE_OBSERVATION) {
 
@Override
public void lancerRecherche() {
chercherObservations();
}
};
presenteur.go(vue.getZoneRecherche());
}
 
public void chercherObservations() {
vue.getZoneResultats().clear();
CacheClient.getInstance().mettreAjourUrlCourante();
new ResultatsIdentiplantePresenteur(new ObservationServiceConcret(), new ResultatsIdentiplanteVue()).go(vue.getZoneResultats());
}
 
protected void gererEvenements() {
// Gestion du clic sur les onglets
vue.getOngletTout().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
CacheClient.getInstance().setFiltreStatut("tous");
CacheClient.getInstance().setPageCouranteRechercheObservations(1);
chercherObservations();
vue.setOngletToutActif();
}
});
vue.getOngletADeterminer().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
CacheClient.getInstance().setFiltreStatut("adeterminer");
CacheClient.getInstance().setPageCouranteRechercheObservations(1);
chercherObservations();
vue.setOngletADeterminerActif();
}
});
vue.getOngletEnDiscussion().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
CacheClient.getInstance().setFiltreStatut("endiscussion");
CacheClient.getInstance().setPageCouranteRechercheObservations(1);
chercherObservations();
vue.setOngletEnDiscussionActif();
}
});
 
vue.getOngletValidees().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
CacheClient.getInstance().setFiltreStatut("validees");
CacheClient.getInstance().setPageCouranteRechercheObservations(1);
chercherObservations();
vue.setOngletValideesActif();
}
});
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/moteur/MoteurIdentiplanteVue.java
New file
0,0 → 1,113
package org.tela_botanica.del.client.vues.identiplante.moteur;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.partageurl.PartageUrlPresenteur;
import org.tela_botanica.del.client.composants.partageurl.PartageUrlVue;
import org.tela_botanica.del.client.i18n.I18n;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.Widget;
 
public class MoteurIdentiplanteVue extends Composite implements MoteurIdentiplantePresenteur.Vue {
 
// Gestion d'UiBinder
interface Binder extends UiBinder<Widget, MoteurIdentiplanteVue> {
}
 
private static Binder binder = GWT.create(Binder.class);
 
@UiField
Panel zoneRecherche, zoneResultats;
 
@UiField
Label ongletTout, ongletADeterminer, ongletEnDiscussion, ongletValidees;
 
public HasWidgets getZoneRecherche() {
return zoneRecherche;
}
// Constructeur de la vue
public MoteurIdentiplanteVue() {
initWidget(binder.createAndBindUi(this));
mettreAJourOngletEnFonctionDuCache();
}
 
public Panel getZoneResultats() {
return zoneResultats;
}
@Override
public HasClickHandlers getOngletEnDiscussion() {
return ongletEnDiscussion;
}
 
@Override
public HasClickHandlers getOngletADeterminer() {
return ongletADeterminer;
}
 
@Override
public HasClickHandlers getOngletTout() {
return ongletTout;
}
 
@Override
public HasClickHandlers getOngletValidees() {
return ongletValidees;
}
 
@Override
public void setOngletADeterminerActif() {
nettoyerOngletsActifs();
ongletADeterminer.addStyleName("onglet-actif");
}
 
@Override
public void setOngletToutActif() {
nettoyerOngletsActifs();
ongletTout.addStyleName("onglet-actif");
}
 
@Override
public void setOngletEnDiscussionActif() {
nettoyerOngletsActifs();
ongletEnDiscussion.addStyleName("onglet-actif");
}
 
@Override
public void setOngletValideesActif() {
nettoyerOngletsActifs();
ongletValidees.addStyleName("onglet-actif");
}
public void nettoyerOngletsActifs() {
ongletTout.removeStyleName("onglet-actif");
ongletADeterminer.removeStyleName("onglet-actif");
ongletEnDiscussion.removeStyleName("onglet-actif");
ongletValidees.removeStyleName("onglet-actif");
}
public void mettreAJourOngletEnFonctionDuCache() {
String statut = CacheClient.getInstance().getFiltreStatut();
if (statut == null) {
setOngletToutActif();
} else if (statut.equals("adeterminer")) {
setOngletADeterminerActif();
} else if (statut.equals("endiscussion")) {
setOngletEnDiscussionActif();
} else if (statut.equals("validees")) {
setOngletValideesActif();
}
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/moteur/MoteurIdentiplante.css
New file
0,0 → 1,35
.entrerMotClef {
margin-bottom: 10px;
font-size:12px
}
 
.lienProposerObservation {
margin-left:65px;
margin-top:10px;
margin-bottom:10px;
}
.zoneStatut {
margin-top:;
}
 
.zoneStatut span {
padding-right:10px;
}
 
.zoneStatut label {
padding-left:2px;
}
 
 
.titreRechercheObs {
margin-top:5px;
}
 
.lienAide {
margin-right:70px;
padding:4px 15px;
margin-top:9px;
float:right;
color:white;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/moteur/MoteurIdentiplanteVue.ui.xml
New file
0,0 → 1,28
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui' ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateLocales="default">
<ui:with field='res'
type='org.tela_botanica.del.client.resources.Ressources' />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
 
<ui:style src="MoteurIdentiplante.css" />
<g:HTMLPanel styleName="limiteMax">
<g:HTMLPanel styleName="limiteMax importance1">
<g:Label text="{constants.rechercherObservation}" styleName="titre {style.titreRechercheObs}" />
<g:Label text="{constants.entrerMotClef}" styleName="gris {style.entrerMotClef}" />
<g:HTMLPanel ui:field="zoneRecherche" />
</g:HTMLPanel>
<g:HTMLPanel styleName="zone-onglets">
<g:Label styleName="onglet onglet-actif" text="Tout" ui:field="ongletTout"></g:Label>
<g:Label styleName="onglet" text="A déterminer" ui:field="ongletADeterminer"></g:Label>
<g:Label styleName="onglet" text="En discussion" ui:field="ongletEnDiscussion"></g:Label>
<!-- terme Validées/Vérifiées sujet à changement, "Vérifiées" en texte, "Validées" partout ailleurs dans le code -->
<g:Label styleName="onglet" text="Vérifiées" ui:field="ongletValidees"></g:Label>
</g:HTMLPanel>
<g:HTMLPanel>
<g:HTMLPanel ui:field="zoneResultats" />
</g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/plateformedetermination/IdentiplanteDeterminationVue.ui.xml
New file
0,0 → 1,54
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:forum="urn:import:org.tela_botanica.del.client.composants.forum">
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary"/>
<ui:style src="determinationVue.css" />
<g:HTMLPanel styleName="{style.pageDetermination}">
<g:HTMLPanel styleName="limiteMax">
<g:Hyperlink ui:field="lienRetour" styleName="lien">Retour</g:Hyperlink>
<g:HTMLPanel ui:field="metadonnees" styleName="{style.metadonnees}"/>
</g:HTMLPanel>
<g:HTMLPanel styleName="contenuCentre">
<g:HTMLPanel styleName="{style.zoneDetailImage}">
<g:VerticalPanel ui:field="detailImageObservation" styleName="{style.zoneImage}"/>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.zoneVote}">
<g:Label styleName="titre" text="{constants.titreDetermination}" />
<g:HTMLPanel styleName="nettoyage {style.boutons}">
<g:Button text="{constants.proposerSaDetermination}" ui:field="boutonAjoutProposition" styleName="bouton" />
<g:Button text="{constants.ajouterCommentaire}" ui:field="boutonAjoutCommentaire" styleName="bouton" />
<g:HTMLPanel ui:field="zoneRss" styleName="droite {style.zonerss}"></g:HTMLPanel>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.taxonProbable}">
<g:Label styleName="gauche" text="{constants.determinationPlusProbable}" />
<g:Label ui:field="nomTaxonProbable" styleName="gauche gras {style.nomTaxonProbable}"/>
<g:Button ui:field="boutonValidationTaxon" text="{constants.accepter}" styleName="droite bouton {style.boutonValiderTaxon}"/>
<g:HTML><br /></g:HTML>
</g:HTMLPanel>
<g:VerticalPanel ui:field="forum" />
<g:HTMLPanel styleName="nettoyage {style.boutons}">
<g:Button text="{constants.proposerSaDetermination}" ui:field="boutonAjoutPropositionBas" styleName="bouton" />
<g:Button text="{constants.ajouterCommentaire}" ui:field="boutonAjoutCommentaireBas" styleName="bouton" />
</g:HTMLPanel>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.zoneOutils}">
<g:Label text="Pour vous aider : " styleName="titre3"></g:Label>
<g:VerticalPanel ui:field="formulaireRechercheEflore"/>
<g:Label styleName="{style.autreOutils} sousTitre">Vérifier sa détermination</g:Label>
<g:Label styleName="lienListe labelLien" ui:field="lienEflore">eFlore</g:Label>
<g:Label styleName="{style.autreOutils} sousTitre">Autres outils en ligne</g:Label>
<g:Label styleName="lienListe labelLien" ui:field="lienOuvrages">Flores numérisées</g:Label>
<g:Label styleName="lienListe labelLien" ui:field="lienBonnier">Flore Bonnier interactive</g:Label>
<g:Label styleName="lienListe labelLien" ui:field="lienCles">Clés de détermination</g:Label>
</g:HTMLPanel>
</g:HTMLPanel>
</g:HTMLPanel>
 
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/plateformedetermination/IdentiplanteDeterminationPresenteur.java
New file
0,0 → 1,327
package org.tela_botanica.del.client.vues.identiplante.plateformedetermination;
 
import java.util.List;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlayDefilanteVue;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlaySimplePresenteur;
import org.tela_botanica.del.client.composants.formulaires.formulairecommentaire.FormulaireCommentairePresenteur;
import org.tela_botanica.del.client.composants.formulaires.formulairecommentaire.FormulaireCommentaireVue;
import org.tela_botanica.del.client.composants.formulaires.formulaireproposition.FormulairePropositionPresenteur;
import org.tela_botanica.del.client.composants.formulaires.formulaireproposition.FormulairePropositionVue;
import org.tela_botanica.del.client.composants.metadonnees.MetadonneesEnLigneVue;
import org.tela_botanica.del.client.composants.metadonnees.MetadonneesPresenteur;
import org.tela_botanica.del.client.composants.observations.ObservationImagesPresenteur;
import org.tela_botanica.del.client.composants.observations.ObservationImagesVue;
import org.tela_botanica.del.client.composants.partageurl.PartageUrlPresenteur;
import org.tela_botanica.del.client.composants.partageurl.PartageUrlVue;
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.composants.rss.RssPresenteur;
import org.tela_botanica.del.client.composants.rss.RssVue;
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.gestionhistorique.ConstantesNavigation;
import org.tela_botanica.del.client.i18n.I18n;
import org.tela_botanica.del.client.modeles.Image;
import org.tela_botanica.del.client.modeles.ModeRecherche;
import org.tela_botanica.del.client.modeles.MoyenneVote;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.modeles.ObservationServiceResultat;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.modeles.Utilisateur;
import org.tela_botanica.del.client.modeles.VoteDetermination;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.ajoutcommentaire.EvenementAjoutCommentaire;
import org.tela_botanica.del.client.navigation.evenement.ajoutcommentaire.GestionnaireEvenementAjoutCommentaire;
import org.tela_botanica.del.client.navigation.evenement.ajoutdetermination.EvenementAjoutDetermination;
import org.tela_botanica.del.client.navigation.evenement.ajoutdetermination.GestionnaireEvenementAjoutDetermination;
import org.tela_botanica.del.client.navigation.evenement.changementEtatUtilisateur.EvenementChangementEtatUtilisateur;
import org.tela_botanica.del.client.navigation.evenement.changementEtatUtilisateur.GestionnaireEvenementChangementEtatUtilisateur;
import org.tela_botanica.del.client.navigation.evenement.changementimagevalidation.EvenementChangementImageValidation;
import org.tela_botanica.del.client.navigation.evenement.changementimagevalidation.GestionnaireEvenementChangementImageValidation;
import org.tela_botanica.del.client.navigation.evenement.voteDetermination.EvenementVoteDetermination;
import org.tela_botanica.del.client.navigation.evenement.voteDetermination.GestionnaireEvenementVoteDetermination;
import org.tela_botanica.del.client.services.CalculVoteDeterminationService;
import org.tela_botanica.del.client.services.rest.CommentaireServiceConcret;
import org.tela_botanica.del.client.services.rest.ObservationService;
import org.tela_botanica.del.client.services.rest.PropositionDeterminationServiceConcret;
import org.tela_botanica.del.client.services.rest.async.ObservationsCallback;
import org.tela_botanica.del.client.services.rest.async.ValidationPropositionCallback;
import org.tela_botanica.del.client.utils.URLUtils;
import org.tela_botanica.del.client.composants.formulairerechercheeflore.FormulaireRechercheEflorePresenteur;
import org.tela_botanica.del.client.composants.forum.ForumPresenteur;
import org.tela_botanica.del.client.composants.forum.ForumVue;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Panel;
 
public class IdentiplanteDeterminationPresenteur extends Presenteur {
 
/**
* Vue de l'interface de détermination
* */
public interface Vue extends IsWidget {
public Panel getForum();
 
public Panel getDetailImageObservation();
 
public Panel getFormulaireRechercheEflore();
 
public Button getBoutonAjoutProposition();
 
public Button getBoutonAjoutCommentaire();
 
public Button getBoutonAjoutPropositionBas();
 
public Button getBoutonAjoutCommentaireBas();
 
public HasWidgets getMetadonnees();
 
public void afficherNomTaxonProbable(String nomTaxon);
public HasClickHandlers getLienOuvrages();
public HasClickHandlers getLienBonnier();
public HasClickHandlers getLienCles();
public HasClickHandlers getLienEflore();
public HasWidgets getZoneRss();
 
HasClickHandlers getBoutonValidationTaxon();
 
void cacherBoutonValidationTaxon();
 
void afficherBoutonValidationTaxon();
 
public void viderMetadonnees();
}
 
private Vue vue;
private FenetreOverlaySimplePresenteur fenetreOverlaySimplePresenteur;
 
// Déclaration des services à utiliser
private ObservationService observationService;
 
private CacheClient cache = CacheClient.getInstance();
private PropositionDetermination propositionPlusPopulaire;
 
public IdentiplanteDeterminationPresenteur(Vue vue, ObservationService observationService) {
this.vue = vue;
this.observationService = observationService;
}
 
public void go(final HasWidgets composite) {
// TODO afficher une icone de chargement si le chargement devient trop
// long
// car tout l'écran est asynchrone ici
String observationId = URLUtils.getURLSpecialParameterValue();
observationService.getObservation(observationId, new ObservationsCallback() {
 
@Override
public void surRetour(ObservationServiceResultat objetRetour) {
afficherRss(cache.getObservationCourante());
// trouve l'image courante si elle n'est pas deja en cache
List<Image> listeImages = cache.getObservationCourante().getImages();
if (listeImages.size() > 0) {
CacheClient.getInstance().setImageCourante(listeImages.get(0));
} else {
CacheClient.getInstance().setImageCourante(null);
}
new MetadonneesPresenteur(new MetadonneesEnLigneVue(), cache.getObservationCourante(), ModeRecherche.MODE_OBSERVATION, false).go(vue.getMetadonnees());
new ObservationImagesPresenteur(new ObservationImagesVue(), cache.getObservationCourante(), CacheClient.getInstance().getImageCourante(), ConstantesNavigation.PAGE_VALIDATION_PICTOFLORA).go(vue.getDetailImageObservation());
new ForumPresenteur(new ForumVue()).go(vue.getForum());
new FormulaireRechercheEflorePresenteur().go(vue.getFormulaireRechercheEflore());
 
composite.add(vue.asWidget());
calculerEtAfficherVoteDeterminationPlusPopulaire();
}
 
@Override
public void surErreur(String messageErreur) {
Window.alert(messageErreur);
}
});
gererEvenements();
}
 
public void afficherRss(Observation observation) {
new RssPresenteur(new RssVue(), observation, "Suivre cette observation").go(vue.getZoneRss());
}
 
private void calculerEtAfficherVoteDeterminationPlusPopulaire() {
if(cache.getObservationCourante() != null) {
Observation observation = cache.getObservationCourante();
String nomTaxon = observation.getNomRetenuFormateReferentiel();
List<MoyenneVote> votesOrdonnes = CalculVoteDeterminationService.calculerVoteDeterminationPlusPopulaire(cache.getObservationCourante().getPropositionDeterminations());
if (votesOrdonnes.size() > 0) {
nomTaxon = votesOrdonnes.get(0).getIntituleAssocie();
propositionPlusPopulaire = votesOrdonnes.get(0).getPropositionAssociee();
if(doitAfficherBoutonValidation(votesOrdonnes)) {
vue.afficherBoutonValidationTaxon();
} else {
vue.cacherBoutonValidationTaxon();
}
}
vue.afficherNomTaxonProbable(nomTaxon);
}
}
private boolean doitAfficherBoutonValidation(List<MoyenneVote> votesOrdonnes) {
boolean estPropositionRetenue = votesOrdonnes.get(0).getPropositionAssociee().estPropositionRetenue();
Utilisateur utilisateur = CacheClient.getInstance().getUtilisateur();
boolean estAuteurObservation = false;
if(utilisateur != null) {
estAuteurObservation = utilisateur.estIdentifie() && utilisateur.getId().equals(cache.getObservationCourante().getIdAuteur());
}
return estAuteurObservation && !estPropositionRetenue;
}
 
public void gererEvenements() {
BusEvenementiel.getInstance().addHandler(EvenementChangementEtatUtilisateur.TYPE, new GestionnaireEvenementChangementEtatUtilisateur() {
@Override
public void onModificationEtatUtilisateur(EvenementChangementEtatUtilisateur evenementChangementEtatUtilisateur) {
calculerEtAfficherVoteDeterminationPlusPopulaire();
};
});
BusEvenementiel.getInstance().addHandler(EvenementVoteDetermination.TYPE, new GestionnaireEvenementVoteDetermination() {
@Override
public void onVoteDetermination(VoteDetermination event) {
calculerEtAfficherVoteDeterminationPlusPopulaire();
}
});
 
ClickHandler clicAjoutProposition = new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
fenetreOverlaySimplePresenteur = new FenetreOverlaySimplePresenteur(new FenetreOverlayDefilanteVue());
fenetreOverlaySimplePresenteur.ouvrirFenetreModale(new FormulairePropositionPresenteur(new FormulairePropositionVue(), new PropositionDeterminationServiceConcret()));
}
};
vue.getBoutonAjoutProposition().addClickHandler(clicAjoutProposition);
vue.getBoutonAjoutPropositionBas().addClickHandler(clicAjoutProposition);
 
ClickHandler clicAjoutCommentaire = new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
FormulaireCommentairePresenteur commentairePresenteur = new FormulaireCommentairePresenteur(cache.getObservationCourante(), new CommentaireServiceConcret(), new FormulaireCommentaireVue());
fenetreOverlaySimplePresenteur = new FenetreOverlaySimplePresenteur(new FenetreOverlayDefilanteVue());
fenetreOverlaySimplePresenteur.ouvrirFenetreModale(commentairePresenteur);
}
};
vue.getBoutonAjoutCommentaire().addClickHandler(clicAjoutCommentaire);
vue.getBoutonAjoutCommentaireBas().addClickHandler(clicAjoutCommentaire);
 
BusEvenementiel.getInstance().addHandler(EvenementAjoutDetermination.TYPE, new GestionnaireEvenementAjoutDetermination() {
@Override
public void onAjoutDetermination(EvenementAjoutDetermination event) {
if (fenetreOverlaySimplePresenteur != null && fenetreOverlaySimplePresenteur.fenetreModaleEstOuverte()) {
fenetreOverlaySimplePresenteur.fermerFenetreModale();
}
}
});
 
BusEvenementiel.getInstance().addHandler(EvenementAjoutCommentaire.TYPE, new GestionnaireEvenementAjoutCommentaire() {
 
@Override
public void onAjoutCommentaire(EvenementAjoutCommentaire event) {
if (fenetreOverlaySimplePresenteur != null && fenetreOverlaySimplePresenteur.fenetreModaleEstOuverte()) {
fenetreOverlaySimplePresenteur.fermerFenetreModale();
}
}
});
 
BusEvenementiel.getInstance().addHandler(EvenementChangementImageValidation.TYPE, new GestionnaireEvenementChangementImageValidation() {
 
@Override
public void onChangementImage(EvenementChangementImageValidation event) {
vue.getDetailImageObservation().clear();
new ObservationImagesPresenteur(new ObservationImagesVue(), cache.getObservationCourante(), CacheClient.getInstance().getImageCourante(), ConstantesNavigation.PAGE_VALIDATION_PICTOFLORA).go(vue.getDetailImageObservation());
}
});
vue.getLienOuvrages().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Config config = new Config();
Window.open(config.getUrl("ouvragesFlore"), "Flores numérisées", null);
}
});
 
vue.getLienBonnier().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Config config = new Config();
Window.open(config.getUrl("bonnierPda"), "Flore Bonnier PDA", null);
}
});
vue.getLienCles().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Config config = new Config();
Window.open(config.getUrl("clesDetermination"), "Clés de determination", null);
}
});
vue.getLienEflore().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Config config = new Config();
Window.open(config.getUrl("eflore"), "eFlore", null);
}
});
vue.getBoutonValidationTaxon().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if(Window.confirm(I18n.getVocabulary().confirmationValidationDetermination())) {
validerPropositionPlusPopulaire();
}
}
});
}
private void validerPropositionPlusPopulaire() {
PropositionDeterminationServiceConcret propositionService = new PropositionDeterminationServiceConcret();
propositionService.validerProposition(propositionPlusPopulaire, new ValidationPropositionCallback() {
@Override
public void surRetour(String objetRetour) {
String observationId = URLUtils.getURLSpecialParameterValue();
observationService.getObservation(observationId, new ObservationsCallback() {
 
@Override
public void surRetour(ObservationServiceResultat objetRetour) {
vue.viderMetadonnees();
new MetadonneesPresenteur(new MetadonneesEnLigneVue(), cache.getObservationCourante(), ModeRecherche.MODE_OBSERVATION, false).go(vue.getMetadonnees());
calculerEtAfficherVoteDeterminationPlusPopulaire();
}
 
@Override
public void surErreur(String messageErreur) {
Window.alert(messageErreur);
}
});
}
});
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/plateformedetermination/detail/DetailImageObservationPresenteur.java
New file
0,0 → 1,24
package org.tela_botanica.del.client.vues.identiplante.plateformedetermination.detail;
 
import org.tela_botanica.del.client.cache.CacheClient;
 
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class DetailImageObservationPresenteur {
public interface Vue extends IsWidget {
public void chargerInformationsObservation(org.tela_botanica.del.client.modeles.Image image);
}
 
private Vue vue;
public DetailImageObservationPresenteur(Vue vue) {
this.vue = vue;
}
 
public void go(HasWidgets composite) {
vue.chargerInformationsObservation(CacheClient.getInstance().getImageCourante());
composite.add(vue.asWidget());
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/plateformedetermination/detail/DetailImageObservationVue.java
New file
0,0 → 1,38
package org.tela_botanica.del.client.vues.identiplante.plateformedetermination.detail;
 
 
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
 
public class DetailImageObservationVue extends Composite implements DetailImageObservationPresenteur.Vue {
 
@UiField
protected Image imageObservation;
 
@UiField
protected Label nomObservateur, nomRetenu, dateObservation, famille, localite;
 
private static DetailImageObservationUIiBinder uiBinder = GWT.create(DetailImageObservationUIiBinder.class);
 
interface DetailImageObservationUIiBinder extends UiBinder<Widget, DetailImageObservationVue> {
};
 
public DetailImageObservationVue() {
initWidget(uiBinder.createAndBindUi(this));
}
 
public void chargerInformationsObservation(org.tela_botanica.del.client.modeles.Image image) {
imageObservation.setUrl(image.getUrl());
nomObservateur.setText(image.getObservation().getAuteur());
nomRetenu.setText(image.getObservation().getNomRetenuFormateReferentiel());
famille.setText(image.getObservation().getFamille());
localite.setText(image.getObservation().getLocalite());
dateObservation.setText(image.getObservation().getDateReleve());
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/plateformedetermination/detail/detailObservation.css
New file
0,0 → 1,27
.detailObservation {
font-size: 11px;
position: absolute;
padding: 5px;
color: white;
background: #333;
opacity: 0.8;
margin-top: -80px;
width: 230px;
}
 
.observateur td {
font-size: 11px;
white-space: nowrap
}
 
.date {
}
 
.nomRetenu {
font-weight: bold
}
 
.dateObservation {
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/plateformedetermination/detail/DetailImageObservationVue.ui.xml
New file
0,0 → 1,36
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
 
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary"/>
<ui:style src="detailObservation.css" />
<g:VerticalPanel>
<g:Image ui:field="imageObservation"/>
<g:VerticalPanel ui:field="detailObservation" styleName="{style.detailObservation}">
<g:HorizontalPanel styleName="{style.observateur}">
<!-- g:Label text="{constants.observateur} : "/ -->
<g:Label ui:field="nomObservateur" /><g:HTML>&nbsp;-&nbsp;</g:HTML><g:Label ui:field="localite" /><g:HTML>&nbsp;-&nbsp;</g:HTML><g:Label ui:field="dateObservation" />
</g:HorizontalPanel>
<g:HorizontalPanel>
<!-- <g:Label text="{constants.nom_retenu} : "/> -->
<g:Label ui:field="nomRetenu" styleName="{style.nomRetenu}"/>
</g:HorizontalPanel>
<g:HorizontalPanel styleName="{style.date}">
<!-- <g:Label text="{constants.date_observation} : "/> -->
</g:HorizontalPanel>
<g:HorizontalPanel>
<!-- <g:Label text="{constants.famille} : "/> -->
<g:HorizontalPanel><g:Label ui:field="famille" /></g:HorizontalPanel>
</g:HorizontalPanel>
<g:HorizontalPanel>
<!-- <g:Label text="{constants.localite} : "/> -->
</g:HorizontalPanel>
</g:VerticalPanel>
</g:VerticalPanel>
 
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/plateformedetermination/IdentiplanteDeterminationVue.java
New file
0,0 → 1,130
package org.tela_botanica.del.client.vues.identiplante.plateformedetermination;
 
import org.tela_botanica.del.client.gestionhistorique.ConstantesNavigation;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class IdentiplanteDeterminationVue extends Composite implements IdentiplanteDeterminationPresenteur.Vue {
 
@UiField
Panel forum, detailImageObservation, formulaireRechercheEflore, zoneRss;
@UiField
Label nomTaxonProbable, lienOuvrages, lienEflore, lienBonnier, lienCles;
@UiField
Button boutonValidationTaxon;
@UiField
Hyperlink lienRetour;
@UiField
Button boutonAjoutProposition, boutonAjoutPropositionBas, boutonAjoutCommentaire, boutonAjoutCommentaireBas;
@UiField
Panel metadonnees;
 
interface DeterminationUIiBinder extends UiBinder<Widget, IdentiplanteDeterminationVue> {
};
 
private static DeterminationUIiBinder uiBinder = GWT.create(DeterminationUIiBinder.class);
 
public IdentiplanteDeterminationVue() {
initWidget(uiBinder.createAndBindUi(this));
lienRetour.setTargetHistoryToken(ConstantesNavigation.HOME);
}
 
public Panel getForum() {
return forum;
}
 
public Panel getDetailImageObservation() {
return detailImageObservation;
}
 
public Panel getFormulaireRechercheEflore() {
return formulaireRechercheEflore;
}
 
public Button getBoutonAjoutProposition() {
return boutonAjoutProposition;
}
public Button getBoutonAjoutPropositionBas() {
return boutonAjoutPropositionBas;
}
public Panel getMetadonnees() {
return metadonnees;
}
 
@Override
public void afficherNomTaxonProbable(String nomTaxon) {
this.nomTaxonProbable.setText(nomTaxon);
}
 
public Button getBoutonAjoutCommentaire() {
return boutonAjoutCommentaire;
}
public Button getBoutonAjoutCommentaireBas() {
return boutonAjoutCommentaireBas;
}
 
@Override
public HasClickHandlers getLienOuvrages() {
return lienOuvrages;
}
 
@Override
public HasClickHandlers getLienBonnier() {
return lienBonnier;
}
 
@Override
public HasClickHandlers getLienCles() {
return lienCles;
}
 
@Override
public HasClickHandlers getLienEflore() {
return lienEflore;
}
@Override
public HasWidgets getZoneRss() {
return zoneRss;
}
@Override
public HasClickHandlers getBoutonValidationTaxon() {
return boutonValidationTaxon;
}
@Override
public void cacherBoutonValidationTaxon() {
boutonValidationTaxon.setVisible(false);
}
@Override
public void afficherBoutonValidationTaxon() {
boutonValidationTaxon.setVisible(true);
}
 
@Override
public void viderMetadonnees() {
metadonnees.clear();
}
}
 
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/plateformedetermination/ligneProtocole/ligneProtocole.css
New file
0,0 → 1,7
.nomProtocole {
font-size: 11px;
overflow: hidden;
text-overflow: ellipsis;
width: 87px;
margin-bottom:15px;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/plateformedetermination/ligneProtocole/LigneProtocoleVue.ui.xml
New file
0,0 → 1,10
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:forum="urn:import:org.tela_botanica.del.client.composants.forum">
<ui:style src="ligneProtocole.css" />
<g:HorizontalPanel styleName="vote">
<g:HTMLPanel ui:field="zoneVote" />
</g:HorizontalPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/plateformedetermination/ligneProtocole/LigneProtocolePresenteur.java
New file
0,0 → 1,59
package org.tela_botanica.del.client.vues.identiplante.plateformedetermination.ligneProtocole;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.composants.votes.moyennevotes.MoyenneVotePresenteur;
import org.tela_botanica.del.client.composants.votes.moyennevotes.MoyenneVoteVue;
import org.tela_botanica.del.client.modeles.Image;
import org.tela_botanica.del.client.modeles.Protocole;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.changementimagevalidation.EvenementChangementImageValidation;
import org.tela_botanica.del.client.navigation.evenement.changementimagevalidation.GestionnaireEvenementChangementImageValidation;
import org.tela_botanica.del.client.services.rest.VoteProtocoleServiceConcret;
 
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class LigneProtocolePresenteur extends Presenteur {
 
public interface Vue extends IsWidget {
 
HasWidgets getZoneVote();
}
 
private Vue vue;
private Protocole protocole;
 
public LigneProtocolePresenteur(Protocole protocole, Vue vue) {
this.vue = vue;
this.protocole = protocole;
chargerValeursProtocolePourImageCourante();
}
public void chargerValeursProtocolePourImageCourante(){
vue.getZoneVote().clear();
Image imageCourante = CacheClient.getInstance().getImageCourante();
MoyenneVotePresenteur votePresenteur = new MoyenneVotePresenteur(imageCourante, protocole, new MoyenneVoteVue(), new VoteProtocoleServiceConcret());
votePresenteur.go(vue.getZoneVote());
}
 
public Vue getVue() {
return vue;
}
 
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
gererEvenements();
}
 
@Override
protected void gererEvenements() {
BusEvenementiel.getInstance().addHandler(EvenementChangementImageValidation.TYPE, new GestionnaireEvenementChangementImageValidation() {
 
@Override
public void onChangementImage(EvenementChangementImageValidation event) {
chargerValeursProtocolePourImageCourante();
}
});
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/plateformedetermination/ligneProtocole/LigneProtocoleVue.java
New file
0,0 → 1,30
package org.tela_botanica.del.client.vues.identiplante.plateformedetermination.ligneProtocole;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class LigneProtocoleVue extends Composite implements LigneProtocolePresenteur.Vue {
@UiField
Panel zoneVote;
interface LigneProtocoleUIiBinder extends UiBinder<Widget, LigneProtocoleVue> {
};
 
private static LigneProtocoleUIiBinder uiBinder = GWT.create(LigneProtocoleUIiBinder.class);
 
public LigneProtocoleVue() {
initWidget(uiBinder.createAndBindUi(this));
}
 
@Override
public HasWidgets getZoneVote() {
return this.zoneVote;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/plateformedetermination/determinationVue.css
New file
0,0 → 1,127
.pageDetermination {
}
.metadonnees {
margin-bottom:10px;
margin-top:10px;
display:inline-block;
}
.zoneVote {
margin-left: 5px;
height: 100%;
display:inline-block;
vertical-align:top;
border-left: solid 1px #DDD;
border-right: solid 1px #DDD;
padding-left: 10px;
padding-right:10px;
text-align:left;
}
 
.taxonPlusProbable {
float: left;
}
 
.zoneBarreRepartition {
border: solid 1px #DDD;
padding: 15px;
}
 
.zoneDetailImage {
height: 100%;
width: 255px;
display:inline-block;
vertical-align:top;
text-align:left;
clear: left;
}
 
.zoneImage {
margin-bottom: 10px;
margin-right: 15px
}
 
.zoneImage div {
clear: left;
padding-top: 5px;
}
 
.zoneImage div img {
float: left;
padding: 0 5px 5px 0;
}
 
.boutonProposer {
float: left;
padding: 5px;
cursor: pointer;
background:#8EB533;
border:none;
margin-right:10px;
margin-top:10px;
}
 
.boutonValiderTaxon {
margin-top: -7px;
}
 
.zoneOutils {
width: 15%;
padding-left:10px;
display:inline-block;
vertical-align:top;
text-align:left;
}
 
.boutons {
margin-bottom:15px;
}
 
 
.lienProposerObservation {
margin-left:65px;
margin-top:10px;
margin-bottom:10px;
}
.nomTaxonProbable {
padding-left:3px;
}
 
.taxonProbable {
background: none repeat scroll 0 0 #F8F8C3;
clear: left;
font-size: 15px;
margin-bottom: 5px;
padding: 13px 9px;
}
 
.voteProtocole div {
margin-bottom:10px;
}
 
.voteProtocole div div {
margin-bottom:0px;
border:solid 0px red
}
.autreOutils {
margin-top:15px;
}
 
.zonerss {
margin-top:5px;
}
 
 
.lienProposerImage {
margin-top:20px;
margin-left:70px;
margin-bottom:10px;
}
 
.lienAide {
margin-right:70px;
padding:4px 15px;
margin-top:10px;
float:right;
color:white;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/resultats/ResultatsIdentiplantePresenteur.java
New file
0,0 → 1,263
package org.tela_botanica.del.client.vues.identiplante.resultats;
 
import java.util.List;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.pagination.PaginationPresenteur;
import org.tela_botanica.del.client.composants.pagination.PaginationVue;
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.modeles.Image;
import org.tela_botanica.del.client.modeles.InformationsRecherche;
import org.tela_botanica.del.client.modeles.ModeTri;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.modeles.ObservationServiceResultat;
import org.tela_botanica.del.client.services.rest.ObservationService;
import org.tela_botanica.del.client.services.rest.async.ObservationsCallback;
import org.tela_botanica.del.client.vues.identiplante.resultats.observations.ObservationPresenteur;
import org.tela_botanica.del.client.vues.identiplante.resultats.observations.ObservationVue;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class ResultatsIdentiplantePresenteur extends Presenteur {
 
/**
* Interface vue : création des composants graphiques
* */
public abstract interface Vue extends IsWidget {
public HasWidgets getZoneObservations();
 
public HasWidgets getZonePaginationHaut();
 
public HasWidgets getZonePaginationBas();
 
public void startChargement();
 
public void stopChargement();
 
public void nettoyer();
 
public HasClickHandlers getTriParDateAscendant();
 
public HasClickHandlers getTriParDateDescendant();
 
public void afficherElementsAucunResultatTrouve();
 
public void afficherElementsResultatsTrouves();
 
public HasClickHandlers getLabelDate();
 
public void setModeTri(ModeTri mode);
}
 
private Vue vue;
private ObservationService serviceObs;
private ModeTri triCourantDate = ModeTri.TRI_DESCENDANT;
private CacheClient cache = CacheClient.getInstance();
private String statut;
 
/**
* Constructeur de la classe
*
* @param ObservationService
* serviceObs le service pour récupérer les observations
* @Vue Vue l'objet implémentant l'interface
* */
public ResultatsIdentiplantePresenteur(ObservationService serviceObs, Vue vue) {
String statut = CacheClient.getInstance().getFiltreStatut();
this.vue = vue;
ModeTri initTriCourantDate = CacheClient.getInstance().getInformationsRechercheObservation().getTriParDate();
initTriCourantDate = (initTriCourantDate == null) ? triCourantDate : initTriCourantDate;
triCourantDate = initTriCourantDate;
vue.setModeTri(triCourantDate);
this.serviceObs = serviceObs;
this.statut = statut;
}
 
/**
* Lancer l'affichage de la recherche dans le composant passé en paramètre
*
* @param HasWidgets
* composite le conteneur de widgets dans lequel ajouter la vue
* */
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
lancerRechercheEtCreerWidgetPagination();
gererEvenements();
}
 
/**
* Initier un callback pour créer le widget de pagination et afficher les
* observations recues et lancer la recherche avec le service
* */
public void lancerRechercheEtCreerWidgetPagination() {
 
int debut = (cache.getPageCouranteRechercheObservations() - 1) * cache.getPasPagination();
int fin = cache.getPageCouranteRechercheObservations() * cache.getPasPagination();
 
ObservationsCallback callback = new ObservationsCallback() {
 
@Override
public void surRetour(ObservationServiceResultat observationsRecues) {
creerWidgetPagination(observationsRecues.getNbTotalObservationsPourLaRecherche());
afficherObservations(observationsRecues);
 
}
 
@Override
public void surErreur(String messageErreur) {
Window.alert(messageErreur);
 
}
};
 
serviceObs.getObservations(cache.getInformationsRechercheObservation(), debut, fin, statut, callback);
}
 
/**
* Créer les widgets de pagination en fonction du nombre d'observation
*
* @param int nbObservations le nombre d'observations à afficher
* */
private void creerWidgetPagination(int nbObservations) {
vue.getZonePaginationHaut().clear();
PaginationPresenteur paginationPresenteurHaut = creerPresenteurPagination(nbObservations);
paginationPresenteurHaut.setGroupePagination("pagination_observations");
paginationPresenteurHaut.go(vue.getZonePaginationHaut());
 
vue.getZonePaginationBas().clear();
PaginationPresenteur paginationPresenteurBas = creerPresenteurPagination(nbObservations);
paginationPresenteurBas.setGroupePagination("pagination_observations");
paginationPresenteurBas.go(vue.getZonePaginationBas());
}
 
/**
* Créer un présenteur du widget pagination
*
* @param int nbObservations le nombre total d'observation à afficher
* */
private PaginationPresenteur creerPresenteurPagination(int nbObservations) {
PaginationPresenteur presenteur = new PaginationPresenteur(new PaginationVue(), nbObservations, cache.getPasPagination(), cache.getPageCouranteRechercheObservations()) {
 
@Override
public void chargerElements(int debut, int fin) {
chargerEtAfficherObservations(debut, fin);
cache.setPageCouranteRechercheObservations(getPageCourante());
}
 
@Override
public void actualiserPasCache(int pas) {
cache.setPasPagination(pas);
}
 
};
return presenteur;
}
 
/**
* Gestion des évènements de la vue recherche Observation
* */
protected void gererEvenements() {
 
ClickHandler surClicDate = new ClickHandler() {
/**
* Gestion du clic sur l'option de tri par date d'observation Masque
* les éléments de tri qui sont en cours et affiche les autres
* */
public void onClick(ClickEvent event) {
toggleModeTri();
 
InformationsRecherche informationsRechercheObservations = cache.getInformationsRechercheObservation();
informationsRechercheObservations.setTriParDate(triCourantDate);
chercherEtAfficherObservationsPageEnCours();
}
};
 
vue.getLabelDate().addClickHandler(surClicDate);
vue.getTriParDateAscendant().addClickHandler(surClicDate);
vue.getTriParDateDescendant().addClickHandler(surClicDate);
}
 
/**
* Inverser le mode de tri en fonction du précédent
* */
public void toggleModeTri() {
if (triCourantDate == ModeTri.TRI_ASCENDANT) {
triCourantDate = ModeTri.TRI_DESCENDANT;
} else {
triCourantDate = ModeTri.TRI_ASCENDANT;
}
 
vue.setModeTri(triCourantDate);
}
 
/**
* Initialiser les variable de début et fin et lancer le chargement des
* observations
* */
public void chercherEtAfficherObservationsPageEnCours() {
int debut = (cache.getPageCouranteRechercheObservations() - 1) * cache.getPasPagination();
int fin = (cache.getPageCouranteRechercheObservations()) * cache.getPasPagination();
chargerEtAfficherObservations(debut, fin);
}
 
/**
* Lancer le service pour charger les observations entre debut et fin et les
* afficher
*
* @param int debut l'entier de départ de la requete
* @param int fin l'entier de limite de la requete
* */
public void chargerEtAfficherObservations(int debut, int fin) {
vue.startChargement();
vue.nettoyer();
 
ObservationsCallback surReceptionObservation = new ObservationsCallback() {
 
@Override
public void surRetour(ObservationServiceResultat observationsRecues) {
afficherObservations(observationsRecues);
 
}
 
@Override
public void surErreur(String messageErreur) {
Window.alert(messageErreur);
 
}
};
serviceObs.getObservations(cache.getInformationsRechercheObservation(), debut, fin, statut, surReceptionObservation);
}
 
/**
* Parcrourir les résultats de la recherche pour initier l'affichage de
* chaque observation
*
* @param ObservationServiceResultat
* resultats les résultats issus de la requête
* */
private void afficherObservations(ObservationServiceResultat resultats) {
vue.nettoyer();
 
if (resultats.getObservations() == null || resultats.getObservations().size() == 0) {
vue.afficherElementsAucunResultatTrouve();
} else {
vue.afficherElementsResultatsTrouves();
for (Observation observation : resultats.getObservations()) {
List<Image> listeImagesObs = observation.getImages();
Image imagePrincipale = null;
if(listeImagesObs != null && listeImagesObs.size() > 0) {
imagePrincipale = listeImagesObs.get(0);
}
ObservationPresenteur presenteur = new ObservationPresenteur(new ObservationVue(), observation, imagePrincipale);
presenteur.go(vue.getZoneObservations());
}
}
CacheClient.getInstance().mettreAjourUrlCourante();
vue.stopChargement();
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/resultats/ResultatsIdentiplanteVue.java
New file
0,0 → 1,118
package org.tela_botanica.del.client.vues.identiplante.resultats;
 
import org.tela_botanica.del.client.modeles.ModeTri;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class ResultatsIdentiplanteVue extends Composite implements ResultatsIdentiplantePresenteur.Vue {
 
@UiField
Panel panneauChargement;
 
// Gestion d'UiBinder
interface Binder extends UiBinder<Widget, ResultatsIdentiplanteVue> {
}
 
private static Binder binder = GWT.create(Binder.class);
 
@UiField
Panel zoneObservations, zonePaginationHaut, zonePaginationBas, zoneTri;
 
@UiField
Button triParDateAscendant, triParDateDescendant;
 
@UiField
Label aucunResultat, labelDate;
 
// Constructeur de la vue
public ResultatsIdentiplanteVue() {
initWidget(binder.createAndBindUi(this));
}
@Override
public HasWidgets getZoneObservations() {
return zoneObservations;
}
 
@Override
public HasWidgets getZonePaginationHaut() {
return zonePaginationHaut;
}
 
@Override
public HasWidgets getZonePaginationBas() {
return zonePaginationBas;
}
 
/**
* Nettoie et remet à zéro les composants du panneau qui doivent l'être
* */
@Override
public void nettoyer() {
zoneObservations.clear();
}
 
@Override
public void startChargement() {
panneauChargement.setHeight(zoneObservations.getOffsetHeight() + "px");
panneauChargement.setVisible(true);
}
 
@Override
public void stopChargement() {
panneauChargement.setVisible(false);
}
 
public void afficherElementsAucunResultatTrouve() {
nettoyer();
aucunResultat.setVisible(true);
zonePaginationHaut.setVisible(false);
zonePaginationBas.setVisible(false);
zoneTri.setVisible(false);
}
 
public void afficherElementsResultatsTrouves() {
aucunResultat.setVisible(false);
zonePaginationHaut.setVisible(true);
zonePaginationBas.setVisible(true);
zoneTri.setVisible(true);
}
 
public Button getTriParDateAscendant() {
return triParDateAscendant;
}
 
public Button getTriParDateDescendant() {
return triParDateDescendant;
}
@Override
public Label getLabelDate() {
return labelDate;
}
/**
* En fonction du sens du tri (ascendant ou descendant), on change l'affichage des
* boutons de tri pour masquer que celui qui doit être cliquable.
* @param ModeTri le mode Ascendant ou Descendant
* */
public void setModeTri(ModeTri mode) {
if (mode == ModeTri.TRI_ASCENDANT) {
triParDateAscendant.setVisible(true);
triParDateDescendant.setVisible(false);
} else {
triParDateDescendant.setVisible(true);
triParDateAscendant.setVisible(false);
}
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/resultats/ResultatsIdentiplante.css
New file
0,0 → 1,48
 
.zoneObservation {
width: 100%;
clear: left;
margin-top: 10px;
}
 
.barreNavigation {
margin-top: 0;
padding-bottom: 20px;
}
 
.votes {
padding-left: 10px;
cursor: pointer;
}
 
.date {
padding-left: 10px;
cursor: pointer;
}
 
.zoneTri {
padding-left: 10px;
}
 
.boutonTriAsc, .boutonTriDesc {
border:none;
cursor:pointer;
}
.boutonTriAsc:hover, .boutonTriDesc:hover {
border-bottom:dotted 1px #8EB533
}
 
.boutonTriAsc {
height: 19px;
background: url(./img/fleche-haut.png) no-repeat
}
 
.boutonTriDesc {
height: 19px;
background: url(./img/fleche-bas.png) no-repeat
}
 
.aucunResultat{
text-align: left;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/resultats/observations/ObservationVue.java
New file
0,0 → 1,76
package org.tela_botanica.del.client.vues.identiplante.resultats.observations;
 
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class ObservationVue extends Composite implements ObservationPresenteur.Vue {
 
// Gestion d'UiBinder
interface Binder extends UiBinder<Widget, ObservationVue> {
}
 
private static Binder binder = GWT.create(Binder.class);
 
@UiField
Button boutonAjoutProposition, boutonAjoutCommentaire, boutonPlusDeDetails;
 
@UiField
Panel determinationsPanel, imagesPanel, metadonnees;
@UiField Label nomEspece;
 
public ObservationVue() {
initWidget(binder.createAndBindUi(this));
}
 
@Override
public HasClickHandlers getBoutonAjoutProposition() {
return boutonAjoutProposition;
}
@Override
public HasClickHandlers getBoutonAjoutCommentaire() {
return boutonAjoutCommentaire;
}
@Override
public HasClickHandlers getBoutonPlusDeDetails() {
return boutonPlusDeDetails;
}
 
public Panel getDeterminationsPanel() {
return determinationsPanel;
}
 
public void setDeterminationsPanel(Panel determinationsPanel) {
this.determinationsPanel = determinationsPanel;
}
 
public Panel getImagesPanel() {
return imagesPanel;
}
public Panel getMetadonneesPanel() {
return metadonnees;
}
 
@Override
public HasClickHandlers getNomEspece() {
return nomEspece;
}
 
@Override
public void setNomEspece(String nomEspece) {
this.nomEspece.setText(nomEspece);
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/resultats/observations/observation.css
New file
0,0 → 1,115
.observation {
width:480px;
padding:10px;
border: solid 1px #DDD;
}
 
.titrePropositions {
margin-top:-0px;
background:none;
}
 
.listePropositions {
background: none repeat scroll 0 0 #FAFAF0;
border-color: #DDDDDD;
border-radius: 0 10px 10px 0;
border-style: solid;
border-width: 1px 1px 1px 0;
box-shadow: 2px 2px 2px #DDDDDD;
min-height: 230px;
margin-top: 7px;
padding: 10px 10px 10px 16px;
width:470px;
}
 
.nomEspece {
padding:7px;
font-size:15px;
font-weight:bold;
background:rgba(100,100,100,0.5);
color:white;
cursor:pointer;
position:absolute;
width:236px;
}
 
.nomEspece:hover {
background:#8EB533;
}
 
.colonneImages {
min-width:260px;
background:url(./img/pasdephoto.jpg) no-repeat;
}
 
.description {
border: solid 1px #EEE;
border-width: 0 1px 0 0;
width: 270px;
padding: 10px;
margin: 0 1px 5px 0;
height: 150px
}
 
.determination {
padding: 10px;
margin: 0 1px 5px 0;
height: 150px
}
 
.photoPrincipale {
height: 20px;
float: left;
padding: 5px;
margin-bottom: 15px;
cursor: pointer
}
 
.panneauDeterminations {
text-align: right
}
 
.lienDetermination {
text-align: center;
padding: 5px;
color: blue;
cursor: pointer;
float: right;
margin: 5px;
text-decoration: underline;
}
 
.miniatures img {
height: 30px
}
 
.metadonnees {
}
 
.boutonDetermination {
background: url("./img/add.png") no-repeat scroll 5px 7px #DDDDDD;
border: 1px solid #AAAAAA;
cursor: pointer;
float: right;
margin-bottom: 5px;
margin-right: 5px;
margin-top: 10px;
padding: 5px 5px 5px 25px;
}
 
.ligneObservation {
margin-bottom: 10px;
}
 
.boutonDetermination:hover {
background-color: #AAA
}
 
.accesOutil {
margin-top: 15px;
}
 
.ajouterProposition {
margin-top:10px;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/resultats/observations/ObservationVue.ui.xml
New file
0,0 → 1,41
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui' ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
ui:generateLocales="default">
<ui:with field='res'
type='org.tela_botanica.del.client.resources.Ressources' />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
 
<ui:style src="observation.css" />
<g:HTMLPanel styleName="{style.ligneObservation} limiteMin limiteMax">
<g:HTMLPanel styleName="droite {style.listePropositions}">
<g:HTMLPanel styleName="{style.panneauDeterminations}">
<g:Label styleName="titre2 {style.titrePropositions}">Proposition des membres du réseau</g:Label>
<g:HTMLPanel ui:field="determinationsPanel" />
<g:HTMLPanel styleName="nettoyage">
<g:Button ui:field="boutonAjoutProposition" styleName="bouton-petit {style.ajouterProposition}"
text="{constants.proposerSaDetermination}" />
<g:Button ui:field="boutonAjoutCommentaire" styleName="bouton-petit"
text="{constants.ajouterCommentaire}" />
<g:Button ui:field="boutonPlusDeDetails" styleName="bouton-petit {style.ajouterProposition}"
text="Voir tous les commentaires" />
</g:HTMLPanel>
</g:HTMLPanel>
 
</g:HTMLPanel>
<g:HTMLPanel styleName="ligne ombre-faible arrondi {style.observation}">
<g:HTMLPanel styleName="colonne {style.colonneImages}">
<g:Label ui:field="nomEspece" styleName="{style.nomEspece}"></g:Label>
<g:HTMLPanel ui:field="imagesPanel" />
</g:HTMLPanel>
<g:HTMLPanel styleName="colonne">
<g:HTMLPanel ui:field="metadonnees" styleName="{style.metadonnees}" />
</g:HTMLPanel>
<g:HTML>
<br class="nettoyage" />
</g:HTML>
</g:HTMLPanel>
</g:HTMLPanel>
 
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/resultats/observations/ObservationPresenteur.java
New file
0,0 → 1,147
package org.tela_botanica.del.client.vues.identiplante.resultats.observations;
 
import java.util.List;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.metadonnees.MetadonneesPresenteur;
import org.tela_botanica.del.client.composants.metadonnees.MetadonneesVue;
import org.tela_botanica.del.client.composants.observations.ObservationImagesPresenteur;
import org.tela_botanica.del.client.composants.observations.ObservationImagesVue;
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.modeles.Image;
import org.tela_botanica.del.client.modeles.ModeRecherche;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.ajoutcommentaire.EvenementAjoutCommentaire;
import org.tela_botanica.del.client.navigation.evenement.ajoutcommentaire.GestionnaireEvenementAjoutCommentaire;
import org.tela_botanica.del.client.navigation.evenement.ajoutdetermination.EvenementAjoutDetermination;
import org.tela_botanica.del.client.navigation.evenement.ajoutdetermination.GestionnaireEvenementAjoutDetermination;
import org.tela_botanica.del.client.navigation.evenement.validationobservation.EvenementValidation;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlayDefilanteVue;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlaySimplePresenteur;
import org.tela_botanica.del.client.composants.formulaires.formulairecommentaire.FormulaireCommentairePresenteur;
import org.tela_botanica.del.client.composants.formulaires.formulairecommentaire.FormulaireCommentaireVue;
import org.tela_botanica.del.client.composants.formulaires.formulaireproposition.FormulairePropositionPresenteur;
import org.tela_botanica.del.client.composants.formulaires.formulaireproposition.FormulairePropositionVue;
import org.tela_botanica.del.client.gestionhistorique.ConstantesNavigation;
import org.tela_botanica.del.client.services.rest.CommentaireServiceConcret;
import org.tela_botanica.del.client.services.rest.PropositionDeterminationServiceConcret;
import org.tela_botanica.del.client.vues.identiplante.resultats.observationdeterminations.ObservationDeterminationPresenteur;
import org.tela_botanica.del.client.vues.identiplante.resultats.observationdeterminations.ObservationDeterminationVue;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class ObservationPresenteur extends Presenteur {
 
public interface Vue extends IsWidget {
public HasClickHandlers getBoutonAjoutProposition();
 
public HasWidgets getDeterminationsPanel();
 
public HasWidgets getImagesPanel();
 
public HasWidgets getMetadonneesPanel();
public HasClickHandlers getNomEspece();
 
public void setNomEspece(String nomEspece);
public HasClickHandlers getBoutonAjoutCommentaire();
public HasClickHandlers getBoutonPlusDeDetails();
}
 
private Vue vue;
 
private Observation observation;
private Image imagePrincipale;
 
private ObservationDeterminationPresenteur observationDeterminationPresenteur;
 
private FenetreOverlaySimplePresenteur fenetreOverlaySimplePresenteur;
 
public ObservationPresenteur(Vue vue, Observation observation, Image imagePrincipale) {
this.observation = observation;
this.vue = vue;
this.imagePrincipale=imagePrincipale;
chargerObservation();
}
 
public void chargerObservation() {
new ObservationImagesPresenteur(new ObservationImagesVue(), observation, imagePrincipale, ConstantesNavigation.PAGE_RECHERCHE_OBSERVATIONS).go(vue.getImagesPanel());
new MetadonneesPresenteur(new MetadonneesVue(), observation, ModeRecherche.MODE_OBSERVATION, false).go(vue.getMetadonneesPanel());
observationDeterminationPresenteur = new ObservationDeterminationPresenteur(new ObservationDeterminationVue(), observation.getPropositionDeterminations());
observationDeterminationPresenteur.go(vue.getDeterminationsPanel());
vue.setNomEspece(observation.getNomRetenu());
gererEvenements();
}
 
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
}
 
protected void gererEvenements() {
 
BusEvenementiel.getInstance().addHandler(EvenementAjoutDetermination.TYPE, new GestionnaireEvenementAjoutDetermination() {
@Override
public void onAjoutDetermination(EvenementAjoutDetermination event) {
if (fenetreOverlaySimplePresenteur != null && fenetreOverlaySimplePresenteur.fenetreModaleEstOuverte()) {
fenetreOverlaySimplePresenteur.fermerFenetreModale();
ajouterPropositionDetermination(event.getPropositionDetermination());
}
}
});
 
vue.getBoutonAjoutProposition().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
List<Image> images = observation.getImages();
if (images.size() > 0) {
CacheClient.getInstance().setImageCourante(images.get(0));
} else {
CacheClient.getInstance().setImageCourante(null);
}
CacheClient.getInstance().setObservationCourante(observation);
fenetreOverlaySimplePresenteur = new FenetreOverlaySimplePresenteur(new FenetreOverlayDefilanteVue());
fenetreOverlaySimplePresenteur.ouvrirFenetreModale(new FormulairePropositionPresenteur(new FormulairePropositionVue(), new PropositionDeterminationServiceConcret()));
}
});
ClickHandler versDetails = new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
BusEvenementiel.getInstance().fireEvent(new EvenementValidation(observation));
}
};
vue.getNomEspece().addClickHandler(versDetails);
vue.getBoutonPlusDeDetails().addClickHandler(versDetails);
vue.getBoutonAjoutCommentaire().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
FormulaireCommentairePresenteur commentairePresenteur = new FormulaireCommentairePresenteur(observation, new CommentaireServiceConcret(), new FormulaireCommentaireVue());
fenetreOverlaySimplePresenteur = new FenetreOverlaySimplePresenteur(new FenetreOverlayDefilanteVue());
fenetreOverlaySimplePresenteur.ouvrirFenetreModale(commentairePresenteur);
}
});
BusEvenementiel.getInstance().addHandler(EvenementAjoutCommentaire.TYPE, new GestionnaireEvenementAjoutCommentaire() {
 
@Override
public void onAjoutCommentaire(EvenementAjoutCommentaire event) {
if (fenetreOverlaySimplePresenteur != null && fenetreOverlaySimplePresenteur.fenetreModaleEstOuverte()) {
fenetreOverlaySimplePresenteur.fermerFenetreModale();
}
}
});
}
 
private void ajouterPropositionDetermination(PropositionDetermination propositionDetermination) {
observationDeterminationPresenteur.setPropositions(observation.getPropositionDeterminations());
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/resultats/votes/DetailVoteObservationVue.ui.xml
New file
0,0 → 1,12
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'
ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat' ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator" ui:generateLocales="default">
<ui:with field='res' type='org.tela_botanica.del.client.resources.Ressources'/>
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary"/>
 
<g:HTMLPanel>
<g:HTMLPanel ui:field="zoneCertitude" />
<g:HTMLPanel ui:field="zoneCommentaires" />
<g:HTMLPanel ui:field="zoneNomEspece" />
<g:HTMLPanel ui:field="zoneVoter" />
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/resultats/votes/DetailVoteObservationPresenteur.java
New file
0,0 → 1,41
package org.tela_botanica.del.client.vues.identiplante.resultats.votes;
 
import org.tela_botanica.del.client.composants.votes.barrerepartition.BarreRepartitionVotePresenteur;
import org.tela_botanica.del.client.composants.votes.barrerepartition.BarreRepartitionVoteVue;
import org.tela_botanica.del.client.modeles.MoyenneVote;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.services.CalculVoteDeterminationService;
import org.tela_botanica.del.client.services.rest.VoteDeterminationServiceConcret;
 
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class DetailVoteObservationPresenteur {
 
public interface Vue extends IsWidget {
public HasWidgets getZoneCertitude();
 
public HasWidgets getZoneCommentaires();
 
public HasWidgets getZoneNomEspece();
 
public HasWidgets getZoneVoter();
}
 
private Vue vue;
private PropositionDetermination proposition;
 
public DetailVoteObservationPresenteur(Vue vue, PropositionDetermination proposition) {
this.vue = vue;
this.proposition = proposition;
}
 
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
BarreRepartitionVotePresenteur presenteurVote = new BarreRepartitionVotePresenteur(new BarreRepartitionVoteVue(), new VoteDeterminationServiceConcret());
MoyenneVote moyenne = CalculVoteDeterminationService.calculerVoteDetermination(proposition);
presenteurVote.afficherVotes(moyenne);
presenteurVote.go(vue.getZoneCertitude());
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/resultats/votes/DetailVoteObservationVue.java
New file
0,0 → 1,40
package org.tela_botanica.del.client.vues.identiplante.resultats.votes;
 
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class DetailVoteObservationVue extends Composite implements DetailVoteObservationPresenteur.Vue {
 
interface Binder extends UiBinder<Widget, DetailVoteObservationVue> {}
 
private static Binder binder = GWT.create(Binder.class);
 
protected @UiField Panel zoneCertitude, zoneCommentaires, zoneNomEspece, zoneVoter;
public DetailVoteObservationVue() {
initWidget(binder.createAndBindUi(this));
}
public HasWidgets getZoneCertitude() {
return zoneCertitude;
}
public HasWidgets getZoneCommentaires() {
return zoneCommentaires;
}
public HasWidgets getZoneNomEspece() {
return zoneNomEspece;
}
public HasWidgets getZoneVoter() {
return zoneVoter;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/resultats/observationdeterminations/LignePropositionVue.java
New file
0,0 → 1,75
package org.tela_botanica.del.client.vues.identiplante.resultats.observationdeterminations;
 
import org.tela_botanica.del.client.i18n.I18n;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
 
public class LignePropositionVue extends Composite implements LignePropositionPresenteur.Vue {
 
// Gestion d'UiBinder
interface MyUiBinder extends UiBinder<Widget, LignePropositionVue> {
}
 
private static MyUiBinder uibinder = GWT.create(MyUiBinder.class);
@UiField
HTMLPanel conteneurPanneauDeterminations;
 
@UiField
FocusPanel conteneurPanneauVotes, conteneurPanneauCommentaires;
 
@UiField
HTML nbVotesHtml, nbCommentairesHtml;
 
public LignePropositionVue(IsWidget panneauDeterminations) {
initWidget(uibinder.createAndBindUi(this));
conteneurPanneauDeterminations.add(panneauDeterminations);
conteneurPanneauVotes.setTitle(I18n.getVocabulary().voirDetailVotes());
conteneurPanneauCommentaires.setTitle(I18n.getVocabulary().voirDetailCommentaires());
}
 
public HasClickHandlers getZoneNbVotes() {
return conteneurPanneauVotes;
}
 
public HasClickHandlers getZoneNbCommentaires() {
return conteneurPanneauCommentaires;
}
 
public void setNbVotes(int nbVotes) {
nbVotesHtml.setHTML(nbVotes + "");
if (nbVotes == 0) {
nbVotesHtml.setVisible(false);
}
}
 
public void setNbCommentaires(int nbCommentaires) {
nbCommentairesHtml.setHTML(nbCommentaires + "");
if (nbCommentaires == 0) {
nbCommentairesHtml.setVisible(false);
}
}
public void enleverLienCommentaires() {
conteneurPanneauCommentaires.setVisible(false);
}
public void enleverLienVotes() {
nbVotesHtml.setVisible(false);
conteneurPanneauVotes.removeStyleName("nombreVotes");
}
public void ajouterLienVotes() {
nbVotesHtml.setVisible(true);
conteneurPanneauVotes.addStyleName("nombreVotes");
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/resultats/observationdeterminations/observationdetermination.css
New file
0,0 → 1,94
.determinationOriginale {
padding-top:3px;
}
 
.lignePropositionRetenue {
}
 
.determInitiale, .especesProposees {
padding-left:10px;
}
 
.headerTableau {
display:inline;
}
 
.gauche {
float:left;
}
 
.milieu {
margin:0 0 0 115px;
float:left
}
 
.droite {
float:right;
}
 
.determination {
margin: -23px 1px 5px 0;
}
 
.especesProposees {
margin-top:15px;
}
 
.determination>div {
margin-top: 2px;
margin-bottom: 30px;
}
.ligneProposition {
clear:both;
}
.ligneProposition>div {
display: block;
float: left;
margin-right: 5px;
}
 
.nombreVotes {
width:15px;
height:16px;
padding-left: 10px;
margin-top:1px;
}
 
.commentaires {
background: url("./img/comment.png") no-repeat scroll 0 0 transparent;
cursor: pointer;
height: 20px;
padding-left: 20px;
margin-left:13px;
}
 
.infobulle {
background: none repeat scroll 0 0 #1A5AC3;
color: white;
font-size: 11px;
height: 11px;
line-height: 0.9;
margin-left: 2px;
margin-top: 8px;
min-width: 7px;
padding: 1px;
position: absolute;
}
 
.infobulleCommentaire {
margin-left:-9px;
}
 
.zonePropositions {
height:130px;
text-align:left;
margin-top:60px;
}
 
.rss {
position:absolute;
margin-top:-25px;
margin-left:446px;
}
 
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/resultats/observationdeterminations/ObservationDeterminationVue.ui.xml
New file
0,0 → 1,30
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui' ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
ui:generateLocales="default">
<ui:with field='res' type='org.tela_botanica.del.client.resources.Ressources' />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
 
<ui:style src="observationdetermination.css" />
<g:HTMLPanel>
<g:HTMLPanel styleName="{style.determinationOriginale}">
<g:Label styleName="petit {style.headerTableau} {style.gauche}">Score</g:Label>
<g:Label styleName="petit {style.headerTableau} {style.gauche} {style.determInitiale}">Détermination initiale</g:Label>
<g:Label styleName="petit {style.headerTableau} {style.milieu}">Voter</g:Label>
<g:HTMLPanel styleName="{style.determination} {style.determinationOriginale}" ui:field="tableauPropositionInitiale" />
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.determinationOriginale} nettoyage {style.lignePropositionRetenue}" ui:field="lignePropositionRetenue">
<g:Label styleName="petit {style.headerTableau} {style.gauche}">Score</g:Label>
<g:Label styleName="petit {style.headerTableau} {style.gauche} {style.determInitiale}">Détermination retenue</g:Label>
<g:Label styleName="petit {style.headerTableau} {style.milieu}">Voter</g:Label>
<g:HTMLPanel styleName="{style.determination} {style.determinationOriginale}" ui:field="tableauPropositionRetenue" />
</g:HTMLPanel>
<g:HTML><br class="nettoyage"></br></g:HTML>
<g:HTMLPanel styleName="{style.determinationOriginale}" ui:field="zonePropositions">
<g:Label styleName="petit {style.headerTableau} {style.gauche}">Score</g:Label>
<g:Label styleName="petit {style.headerTableau} {style.gauche} {style.determInitiale}">Espèces proposées</g:Label>
<g:HTMLPanel styleName="{style.determination}" ui:field="tableauPropositions" />
</g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/resultats/observationdeterminations/ObservationDeterminationPresenteur.java
New file
0,0 → 1,139
package org.tela_botanica.del.client.vues.identiplante.resultats.observationdeterminations;
 
import java.util.Collections;
import java.util.List;
 
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlaySimplePresenteur;
import org.tela_botanica.del.client.composants.rss.RssPresenteur;
import org.tela_botanica.del.client.composants.rss.RssVue;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.modeles.VoteDetermination;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.voteDetermination.EvenementVoteDetermination;
import org.tela_botanica.del.client.navigation.evenement.voteDetermination.GestionnaireEvenementVoteDetermination;
import org.tela_botanica.del.client.utils.ComparateurPropositionDetermination;
import org.tela_botanica.del.client.vues.identiplante.resultats.votes.DetailVoteObservationPresenteur;
import org.tela_botanica.del.client.vues.identiplante.resultats.votes.DetailVoteObservationVue;
 
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class ObservationDeterminationPresenteur {
public abstract interface Vue extends IsWidget {
public void viderTableau();
 
public void viderTableauPropositionInitiale();
public HasWidgets getTableauPropositions();
 
public HasWidgets getTableauPropositionInitiale();
public void viderTableauPropositionRetenue();
public HasWidgets getTableauPropositionRetenue();
 
void setNbVotes(int index, int nbVotes);
 
void setNbCommentaires(int index, int nbCommentaires);
 
int getIndexLigneProposition(LignePropositionVue lignePropositionVue);
 
public void masquerPropositions();
public void toggleTableauPropositionRetenue();
}
private Vue vue;
private List<PropositionDetermination> propositions;
FenetreOverlaySimplePresenteur fenetreOverlaySimplePresenteur;
 
public ObservationDeterminationPresenteur(Vue vue, List<PropositionDetermination> propositions) {
this.propositions = propositions;
this.vue = vue;
}
 
public void chargerPropositionRetenue(PropositionDetermination proposition) {
vue.viderTableauPropositionRetenue();
HTMLPanel panneau = new HTMLPanel("");
DetailVoteObservationPresenteur presenteurVote = new DetailVoteObservationPresenteur(new DetailVoteObservationVue(), proposition);
presenteurVote.go(panneau);
LignePropositionVue lignePropositionVue = new LignePropositionVue(panneau);
LignePropositionPresenteur lignePropositionPresenteur = new LignePropositionPresenteur(lignePropositionVue, proposition);
lignePropositionPresenteur.go(vue.getTableauPropositionRetenue());
vue.toggleTableauPropositionRetenue();
}
public void chargerPropositionOriginale(PropositionDetermination proposition) {
vue.viderTableauPropositionInitiale();
// TODO: afficher nombre de votes total et mettre à jour en cas de
// vote
HTMLPanel panneau = new HTMLPanel("");
DetailVoteObservationPresenteur presenteurVote = new DetailVoteObservationPresenteur(new DetailVoteObservationVue(), proposition);
presenteurVote.go(panneau);
LignePropositionVue lignePropositionVue = new LignePropositionVue(panneau);
LignePropositionPresenteur lignePropositionPresenteur = new LignePropositionPresenteur(lignePropositionVue, proposition);
lignePropositionPresenteur.go(vue.getTableauPropositionInitiale());
}
public void classerPropositions(List<PropositionDetermination> propositions) {
Collections.sort(propositions, new ComparateurPropositionDetermination());
}
 
public void chargerPropositions() {
vue.viderTableau();
int nbPropositions = 0;
classerPropositions(propositions);
for (PropositionDetermination proposition : propositions) {
if (proposition.estPropositionInitiale()) {
chargerPropositionOriginale(proposition);
} else if (proposition.estPropositionRetenue()) {
chargerPropositionRetenue(proposition);
} else {
nbPropositions++;
// TODO: afficher nombre de votes total et mettre à jour en
// cas de
// vote
HTMLPanel panneau = new HTMLPanel("");
DetailVoteObservationPresenteur presenteurVote = new DetailVoteObservationPresenteur(new DetailVoteObservationVue(), proposition);
presenteurVote.go(panneau);
LignePropositionVue lignePropositionVue = new LignePropositionVue(panneau);
LignePropositionPresenteur lignePropositionPresenteur = new LignePropositionPresenteur(lignePropositionVue, proposition);
lignePropositionPresenteur.go(vue.getTableauPropositions());
}
}
if (nbPropositions > 0) {
} else {
vue.masquerPropositions();
}
BusEvenementiel.getInstance().addHandler(EvenementVoteDetermination.TYPE, new GestionnaireEvenementVoteDetermination() {
@Override
public void onVoteDetermination(VoteDetermination event) {
surVoteDetermination(event);
}
});
}
 
public void setPropositions(List<PropositionDetermination> propositions) {
this.propositions = propositions;
chargerPropositions();
}
 
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
chargerPropositions();
}
 
public void surVoteDetermination(VoteDetermination voteDetermination) {
int indexProposition = propositions.indexOf(voteDetermination.getPropositionDetermination());
if (indexProposition != -1) {
vue.setNbVotes(indexProposition, voteDetermination.getPropositionDetermination().getVotesDeterminations().size());
}
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/resultats/observationdeterminations/ObservationDeterminationVue.java
New file
0,0 → 1,87
package org.tela_botanica.del.client.vues.identiplante.resultats.observationdeterminations;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;
 
public class ObservationDeterminationVue extends Composite implements ObservationDeterminationPresenteur.Vue {
 
// Gestion d'UiBinder
interface Binder extends UiBinder<Widget, ObservationDeterminationVue> {
}
 
private static Binder binder = GWT.create(Binder.class);
 
@UiField
HTMLPanel tableauPropositions, tableauPropositionInitiale, zonePropositions, tableauPropositionRetenue, lignePropositionRetenue;
 
public HTMLPanel getTableauPropositions() {
return tableauPropositions;
}
 
public ObservationDeterminationVue() {
initWidget(binder.createAndBindUi(this));
toggleTableauPropositionRetenue();
}
 
@Override
public int getIndexLigneProposition(LignePropositionVue lignePropositionVue) {
return tableauPropositions.getWidgetIndex(lignePropositionVue);
}
 
@Override
public void setNbVotes(int index, int nbVotes) {
// cette conversion ne devrait jamais poser de problème, car le tableau
// ne doit contenir que ça
LignePropositionVue lignePropositionVue = (LignePropositionVue) tableauPropositions.getWidget(index);
lignePropositionVue.setNbVotes(nbVotes);
}
 
@Override
public void setNbCommentaires(int index, int nbCommentaires) {
// cette conversion ne devrait jamais poser de problème, car le tableau
// ne doit contenir que ça
LignePropositionVue lignePropositionVue = (LignePropositionVue) tableauPropositions.getWidget(index);
lignePropositionVue.setNbVotes(nbCommentaires);
}
 
@Override
public void viderTableau() {
tableauPropositions.clear();
}
 
@Override
public HasWidgets getTableauPropositionInitiale() {
return tableauPropositionInitiale;
}
public void masquerPropositions() {
this.zonePropositions.setVisible(false);
}
 
@Override
public void viderTableauPropositionInitiale() {
tableauPropositionInitiale.clear();
}
@Override
public void viderTableauPropositionRetenue() {
tableauPropositionRetenue.clear();
}
 
@Override
public HasWidgets getTableauPropositionRetenue() {
return tableauPropositionRetenue;
}
 
@Override
public void toggleTableauPropositionRetenue() {
lignePropositionRetenue.setVisible(!lignePropositionRetenue.isVisible());
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/resultats/observationdeterminations/LignePropositionVue.ui.xml
New file
0,0 → 1,19
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui' ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
ui:generateLocales="default">
<ui:with field='res' type='org.tela_botanica.del.client.resources.Ressources' />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
 
<ui:style src="observationdetermination.css" />
<g:HTMLPanel styleName="{style.ligneProposition}">
<g:HTMLPanel ui:field="conteneurPanneauDeterminations" />
<g:FocusPanel ui:field="conteneurPanneauVotes" styleName="{style.nombreVotes}">
<g:HTML ui:field="nbVotesHtml" styleName="{style.infobulle}"/>
</g:FocusPanel>
<g:FocusPanel ui:field="conteneurPanneauCommentaires" styleName="{style.commentaires}">
<g:HTML ui:field="nbCommentairesHtml" styleName="{style.infobulle} {style.infobulleCommentaire}"/>
</g:FocusPanel>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/resultats/observationdeterminations/LignePropositionPresenteur.java
New file
0,0 → 1,125
package org.tela_botanica.del.client.vues.identiplante.resultats.observationdeterminations;
 
import org.tela_botanica.del.client.composants.commentaires.DetailCommentairePresenteur;
import org.tela_botanica.del.client.composants.commentaires.DetailCommentaireVue;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlayDefilanteVue;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlaySimplePresenteur;
import org.tela_botanica.del.client.composants.votes.details.DetailListeVotesDeterminationPresenteur;
import org.tela_botanica.del.client.composants.votes.details.DetailListeVotesDeterminationVue;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.modeles.VoteDetermination;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.voteDetermination.EvenementVoteDetermination;
import org.tela_botanica.del.client.navigation.evenement.voteDetermination.GestionnaireEvenementVoteDetermination;
import org.tela_botanica.del.client.services.rest.CommentaireServiceConcret;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class LignePropositionPresenteur {
 
private int nbCommentaires, nbVotes;
 
public abstract interface Vue extends IsWidget {
public HasClickHandlers getZoneNbVotes();
 
public HasClickHandlers getZoneNbCommentaires();
 
public void setNbVotes(int nbVotes);
 
public void setNbCommentaires(int nbCommentaires);
 
public void enleverLienCommentaires();
 
public void enleverLienVotes();
public void ajouterLienVotes();
}
 
private Vue vue;
 
private PropositionDetermination propositionDetermination;
 
public LignePropositionPresenteur(Vue vue,
PropositionDetermination propositionDetermination) {
this.vue = vue;
this.propositionDetermination = propositionDetermination;
}
 
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
chargerPropositionDetermination();
gererEvenements();
}
 
public void chargerPropositionDetermination() {
this.nbCommentaires = propositionDetermination.getTotalCommentaires();
this.nbVotes = propositionDetermination.getVotesDeterminations().size();
vue.setNbCommentaires(nbCommentaires);
vue.setNbVotes(nbVotes);
}
 
public void gererEvenements() {
gererEvenementsVotes();
if (nbCommentaires > 0) {
vue.getZoneNbCommentaires().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if (nbCommentaires > 0) {
FenetreOverlaySimplePresenteur fenetreOverlaySimplePresenteur = new FenetreOverlaySimplePresenteur(
new FenetreOverlayDefilanteVue());
DetailCommentairePresenteur detailCommentairePresenteur = new DetailCommentairePresenteur(
new DetailCommentaireVue(),
new CommentaireServiceConcret(),
propositionDetermination);
fenetreOverlaySimplePresenteur
.ouvrirFenetreModale(detailCommentairePresenteur);
detailCommentairePresenteur.afficherCommentaires();
}
}
});
} else {
vue.enleverLienCommentaires();
}
BusEvenementiel.getInstance().addHandler(EvenementVoteDetermination.TYPE, new GestionnaireEvenementVoteDetermination() {
@Override
public void onVoteDetermination(VoteDetermination event) {
if(event.getPropositionDetermination() == propositionDetermination) {
if(nbVotes == 0) {
nbVotes++;
gererEvenementsVotes();
}
vue.setNbVotes(nbVotes);
}
}
});
}
 
private void gererEvenementsVotes() {
if (nbVotes > 0) {
vue.getZoneNbVotes().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if (nbVotes > 0) {
FenetreOverlaySimplePresenteur fenetreOverlaySimplePresenteur = new FenetreOverlaySimplePresenteur(
new FenetreOverlayDefilanteVue());
DetailListeVotesDeterminationPresenteur detailListeVotesDeterminationPresenteur = new DetailListeVotesDeterminationPresenteur(
new DetailListeVotesDeterminationVue());
fenetreOverlaySimplePresenteur
.ouvrirFenetreModale(detailListeVotesDeterminationPresenteur);
detailListeVotesDeterminationPresenteur
.afficherVotes(propositionDetermination);
}
}
});
vue.ajouterLienVotes();
} else {
vue.enleverLienVotes();
}
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/identiplante/resultats/ResultatsIdentiplanteVue.ui.xml
New file
0,0 → 1,31
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui' ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
ui:generateLocales="default">
<ui:with field='res' type='org.tela_botanica.del.client.resources.Ressources' />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
 
<ui:style src="ResultatsIdentiplante.css" />
<g:HTMLPanel>
<g:HTMLPanel styleName="{style.barreNavigation} limiteMax">
<g:VerticalPanel ui:field="zonePaginationHaut" styleName="gauche" />
<g:HTMLPanel ui:field="zoneTri" styleName="droite {style.zoneTri} petit">
<g:Label text="{constants.tri}" styleName="gauche"/>
<g:HTMLPanel ui:field="triParDate" styleName="gauche">
<g:Label text="{constants.triParDate}" styleName="gauche {style.date}" ui:field="labelDate"/>
<g:Button title="{constants.triParDateAscendant}" ui:field="triParDateAscendant" styleName="{style.boutonTriAsc} gauche" />
<g:Button title="{constants.triParDateDescendant}" ui:field="triParDateDescendant" styleName="{style.boutonTriDesc} gauche" />
</g:HTMLPanel>
</g:HTMLPanel>
</g:HTMLPanel>
<g:HTMLPanel>
<g:HTMLPanel ui:field="panneauChargement">
<g:Image url="./img/wait.gif"></g:Image>
</g:HTMLPanel>
<g:Label ui:field="aucunResultat" styleName="{style.aucunResultat}" text="{constants.aucunResultat}" visible="false" />
<g:HTMLPanel ui:field="zoneObservations" styleName="{style.zoneObservation}" />
<g:VerticalPanel ui:field="zonePaginationBas" />
</g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/moteur/MoteurPictofloraVue.ui.xml
New file
0,0 → 1,26
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui' ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateLocales="default">
 
<ui:with field='res'
type='org.tela_botanica.del.client.resources.Ressources' />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
<ui:style src="rechercheImage.css" />
<g:HTMLPanel>
<g:HTMLPanel styleName="limiteMax">
<g:HorizontalPanel styleName="gauche {style.protocoles}">
<g:Label>Choisir un protocole : </g:Label>
<g:ListBox ui:field="listeProtocoles" />
</g:HorizontalPanel>
<g:HTMLPanel styleName="importance1">
<g:Label text="{constants.rechercherImage}" styleName="titre {style.titreRecherche}" />
<g:Label text="{constants.entrerMotClef}" styleName="gris {style.entrerMotClef}" />
<g:HTMLPanel ui:field="zoneRecherche" />
</g:HTMLPanel>
</g:HTMLPanel>
<g:HTMLPanel ui:field="panneauResultats" />
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/moteur/MoteurPictofloraPresenteur.java
New file
0,0 → 1,196
package org.tela_botanica.del.client.vues.pictoflora.moteur;
 
import java.util.List;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.moteurrecherche.MoteurRecherchePresenteur;
import org.tela_botanica.del.client.composants.moteurrecherche.MoteurRechercheVue;
import org.tela_botanica.del.client.modeles.ModeRecherche;
import org.tela_botanica.del.client.modeles.Protocole;
import org.tela_botanica.del.client.modeles.ProtocoleServiceResultat;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.changementprotocole.EvenementChangementProtocole;
import org.tela_botanica.del.client.services.rest.ImageServiceConcret;
import org.tela_botanica.del.client.services.rest.ProtocoleService;
import org.tela_botanica.del.client.services.rest.ProtocoleServiceConcret;
import org.tela_botanica.del.client.services.rest.async.ProtocolesCallback;
import org.tela_botanica.del.client.vues.pictoflora.resultats.ResultatPictofloraPresenteur;
import org.tela_botanica.del.client.vues.pictoflora.resultats.ResultatPictofloraVue;
 
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.HasChangeHandlers;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.ListBox;
 
public class MoteurPictofloraPresenteur {
 
public interface Vue extends IsWidget {
public HasWidgets getZoneResultats();
 
public HasWidgets getZoneRecherche();
 
public void ajouterVue(HasWidgets composite);
 
public void setListeProtocoles(ListBox listeProtocoles);
public HasChangeHandlers getListeProtocoles();
public void ajouterProtocole(String NomProtocole, String idProtocole);
 
public void selectionnerProtocole(int index);
public void selectionnerProtocoleParProtocole(Protocole protocole);
public String getNomProtocoleSelectionne();
 
public int getIdProtocoleSelectionne();
 
public void ajouterProtocoles(List<Protocole> protocoles);
 
public void mettreAJourDescriptionProtocoleCourant(Protocole protocoleCourant);
}
 
private Vue vue;
private ProtocoleService protocoleService;
private List<Protocole> protocoles;
 
/**
* Constructeur
* */
public MoteurPictofloraPresenteur(Vue vue, ProtocoleService protocoleService) {
this.vue = vue;
this.protocoleService = protocoleService;
chargerProtocoles();
// TODO: le code ci dessous sert à ne pas recharger les protocoles
// à chaque fois, voir si on peut le factoriser quelque part
if (CacheClient.getInstance().getProtocoleCourant() == null) {
if (CacheClient.getInstance().getListeProtocoles() == null) {
protocoleService.getProtocoles(new ProtocolesCallback() {
 
@Override
public void surRetour(ProtocoleServiceResultat protocolesRecus) {
CacheClient.getInstance().setListeProtocoles(protocolesRecus.getProtocoles());
if (protocolesRecus.getProtocoles().size() > 0) {
if(protocoles == null) {
protocoles = protocolesRecus.getProtocoles();
}
//Vérifier qu'on n'a pas demandé un protocole particulier en paramètre
String parametre = CacheClient.getInstance().getIdProtocoleEnAttente();
if (parametre != null) {
for (Protocole protocoleCourant : protocoles) {
if (parametre.equals(String.valueOf(protocoleCourant.getId()))) {
CacheClient.getInstance().setProtocoleCourant(protocoleCourant);
}
}
CacheClient.getInstance().setIdProtocoleEnAttente(null);
} else {
CacheClient.getInstance().setProtocoleCourant(protocolesRecus.getProtocoles().get(0));
}
} else {
// TODO afficher message indiquant que la liste des
// protocoles de votes n'est pas fourni
}
}
});
} else {
CacheClient.getInstance().setProtocoleCourant(CacheClient.getInstance().getListeProtocoles().get(0));
}
}
gererEvenements();
}
private void gererEvenements() {
vue.getListeProtocoles().addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
surChangementProtocole();
}
});
}
private void chargerProtocoles() {
// test pour ne pas charger les protocoles déjà chargés
// TODO: faire un systeme de cache gérés par les web service eux même
if (CacheClient.getInstance().getListeProtocoles() == null) {
protocoleService.getProtocoles(new ProtocolesCallback() {
 
@Override
public void surRetour(ProtocoleServiceResultat protocolesRecus) {
protocoles = protocolesRecus.getProtocoles();
remplirListeProtocole(protocoles);
surChangementProtocole();
}
});
} else {
protocoles = CacheClient.getInstance().getListeProtocoles();
remplirListeProtocole(CacheClient.getInstance().getListeProtocoles());
}
}
public void surChangementProtocole() {
Protocole protocoleCourant = null;
for (Protocole protocole : protocoles) {
if (protocole.getId() == vue.getIdProtocoleSelectionne()) {
protocoleCourant = protocole;
}
}
vue.mettreAJourDescriptionProtocoleCourant(protocoleCourant);
CacheClient.getInstance().setProtocoleCourant(protocoleCourant);
EvenementChangementProtocole evenement = new EvenementChangementProtocole(protocoleCourant);
BusEvenementiel.getInstance().fireEvent(evenement);
CacheClient.getInstance().mettreAjourUrlCourante();
}
private void remplirListeProtocole(List<Protocole> protocoles) {
//si un paramètre est passé dans l'url, on sélectionne un protocole
String parametre = CacheClient.getInstance().getIdProtocoleEnAttente();
if (parametre != null) {
for (Protocole protocoleCourant : protocoles) {
if (parametre.equals(String.valueOf(protocoleCourant.getId()))) {
CacheClient.getInstance().setProtocoleCourant(protocoleCourant);
}
}
}
vue.ajouterProtocoles(protocoles);
if (CacheClient.getInstance().getProtocoleCourant() == null) {
vue.selectionnerProtocole(0);
vue.mettreAJourDescriptionProtocoleCourant(protocoles.get(0));
} else {
vue.selectionnerProtocoleParProtocole(CacheClient.getInstance().getProtocoleCourant());
vue.mettreAJourDescriptionProtocoleCourant(CacheClient.getInstance().getProtocoleCourant());
}
CacheClient.getInstance().mettreAjourUrlCourante();
}
 
public void go(HasWidgets composite) {
vue.ajouterVue(composite);
chargerMoteurRechercheAvancee();
}
 
public void chargerMoteurRechercheAvancee() {
MoteurRecherchePresenteur presenteurRecherche = new MoteurRecherchePresenteur(new MoteurRechercheVue(""), ModeRecherche.MODE_IMAGE) {
public void lancerRecherche() {
chercherImages();
}
};
presenteurRecherche.go(vue.getZoneRecherche());
}
 
public void chercherImages() {
vue.getZoneResultats().clear();
CacheClient.getInstance().mettreAjourUrlCourante();
new ResultatPictofloraPresenteur(new ImageServiceConcret(), new ProtocoleServiceConcret(), new ResultatPictofloraVue()).go(vue.getZoneResultats());
}
 
public HasWidgets getZoneResultats() {
return vue.getZoneResultats();
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/moteur/MoteurPictofloraVue.java
New file
0,0 → 1,118
package org.tela_botanica.del.client.vues.pictoflora.moteur;
 
import java.util.List;
 
import org.tela_botanica.del.client.modeles.Protocole;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.OptionElement;
import com.google.gwt.dom.client.SelectElement;
import com.google.gwt.event.dom.client.HasChangeHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class MoteurPictofloraVue extends Composite implements MoteurPictofloraPresenteur.Vue {
 
private final Panel panneauChargement = new FlowPanel();
 
interface MyUiBinder extends UiBinder<Widget, MoteurPictofloraVue> {
}
 
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
 
@UiField
Panel panneauResultats, zoneRecherche;
@UiField
ListBox listeProtocoles;
// Constructeur
public MoteurPictofloraVue() {
initWidget(uiBinder.createAndBindUi(this));
}
 
public Panel getPanneauChargement() {
return panneauChargement;
}
 
// Cette méthode est public car appelé dans GestionnaireHistorique
public Panel getZoneResultats() {
return panneauResultats;
}
 
public void setPanneauResultats(Panel panneauResultats) {
this.panneauResultats = panneauResultats;
}
 
public HasWidgets getZoneRecherche() {
return zoneRecherche;
}
 
@Override
public void ajouterVue(HasWidgets composite) {
composite.add(this.asWidget());
}
public void setListeProtocoles(ListBox listeProtocoles) {
this.listeProtocoles = listeProtocoles;
}
public HasChangeHandlers getListeProtocoles() {
return listeProtocoles;
}
public void ajouterProtocole(String NomProtocole, String idProtocole) {
listeProtocoles.addItem(NomProtocole, idProtocole);
}
 
public void selectionnerProtocole(int index) {
listeProtocoles.setSelectedIndex(index);
}
@Override
public String getNomProtocoleSelectionne() {
return listeProtocoles.getItemText((listeProtocoles.getSelectedIndex()));
}
 
@Override
public int getIdProtocoleSelectionne() {
return Integer.parseInt(listeProtocoles.getValue((listeProtocoles.getSelectedIndex())));
}
@Override
public void ajouterProtocoles(List<Protocole> protocoles) {
SelectElement selectElement = SelectElement.as(listeProtocoles.getElement());
NodeList<OptionElement> options = selectElement.getOptions();
for (int i = 0; i < protocoles.size(); i++) {
listeProtocoles.addItem(protocoles.get(i).getNom(), protocoles.get(i).getId()+"");
options.getItem(i).setTitle(protocoles.get(i).getDescription());
}
}
 
@Override
public void mettreAJourDescriptionProtocoleCourant(
Protocole protocoleCourant) {
listeProtocoles.setTitle(protocoleCourant.getDescription());
}
 
@Override
public void selectionnerProtocoleParProtocole(Protocole protocole) {
int index = 0;
for (int i = 0; i < listeProtocoles.getItemCount(); i++) {
int id = Integer.parseInt(listeProtocoles.getValue(i));
if (id == protocole.getId()) {
index = i;
}
}
listeProtocoles.setSelectedIndex(index);
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/moteur/rechercheImage.css
New file
0,0 → 1,53
.zoneRecherche {
width: 100%
}
 
.protocoles {
margin-top:-61px;
margin-left:68px;
position:absolute;
}
 
.moteurRecherche {
margin-bottom: 10px;
}
 
.moteurRecherche button {
margin-left: 2px;
margin-top: -1px
}
 
.labelProtocole {
padding: 0 5px 0 0;
float: left
}
 
.chapeau {
min-height:70px;
}
 
.labelProtocole:after {
content: " :"
}
 
.entrerMotClef {
margin-bottom: 10px;
}
 
.lienProposerImage {
margin-top:20px;
margin-left:70px;
margin-bottom:10px;
}
 
.lienAide {
margin-right:70px;
padding:4px 15px;
margin-top:19px;
float:right;
color:white;
}
 
.titreRecherche {
margin:0;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/plateformedetermination/PictofloraDeterminationPresenteur.java
New file
0,0 → 1,294
package org.tela_botanica.del.client.vues.pictoflora.plateformedetermination;
 
import java.util.Iterator;
import java.util.List;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlayDefilanteVue;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlaySimplePresenteur;
import org.tela_botanica.del.client.composants.formulairerechercheeflore.FormulaireRechercheEflorePresenteur;
import org.tela_botanica.del.client.composants.formulaires.formulairecommentaire.FormulaireCommentairePresenteur;
import org.tela_botanica.del.client.composants.formulaires.formulairecommentaire.FormulaireCommentaireVue;
import org.tela_botanica.del.client.composants.formulaires.formulaireproposition.FormulairePropositionPresenteur;
import org.tela_botanica.del.client.composants.formulaires.formulaireproposition.FormulairePropositionVue;
import org.tela_botanica.del.client.composants.forum.ForumPresenteur;
import org.tela_botanica.del.client.composants.forum.ForumVue;
import org.tela_botanica.del.client.composants.metadonnees.MetadonneesEnLigneVue;
import org.tela_botanica.del.client.composants.metadonnees.MetadonneesPresenteur;
import org.tela_botanica.del.client.composants.observations.ObservationImagesPresenteur;
import org.tela_botanica.del.client.composants.observations.ObservationImagesVue;
import org.tela_botanica.del.client.composants.partageurl.PartageUrlPresenteur;
import org.tela_botanica.del.client.composants.partageurl.PartageUrlVue;
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.composants.rss.RssPresenteur;
import org.tela_botanica.del.client.composants.rss.RssVue;
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.gestionhistorique.ConstantesNavigation;
import org.tela_botanica.del.client.modeles.Image;
import org.tela_botanica.del.client.modeles.ModeRecherche;
import org.tela_botanica.del.client.modeles.MoyenneVote;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.modeles.ObservationServiceResultat;
import org.tela_botanica.del.client.modeles.Protocole;
import org.tela_botanica.del.client.modeles.ProtocoleServiceResultat;
import org.tela_botanica.del.client.modeles.VoteDetermination;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.ajoutcommentaire.EvenementAjoutCommentaire;
import org.tela_botanica.del.client.navigation.evenement.ajoutcommentaire.GestionnaireEvenementAjoutCommentaire;
import org.tela_botanica.del.client.navigation.evenement.ajoutdetermination.EvenementAjoutDetermination;
import org.tela_botanica.del.client.navigation.evenement.ajoutdetermination.GestionnaireEvenementAjoutDetermination;
import org.tela_botanica.del.client.navigation.evenement.changementimagevalidation.EvenementChangementImageValidation;
import org.tela_botanica.del.client.navigation.evenement.changementimagevalidation.GestionnaireEvenementChangementImageValidation;
import org.tela_botanica.del.client.navigation.evenement.voteDetermination.EvenementVoteDetermination;
import org.tela_botanica.del.client.navigation.evenement.voteDetermination.GestionnaireEvenementVoteDetermination;
import org.tela_botanica.del.client.services.CalculVoteDeterminationService;
import org.tela_botanica.del.client.services.rest.CommentaireServiceConcret;
import org.tela_botanica.del.client.services.rest.ObservationService;
import org.tela_botanica.del.client.services.rest.PropositionDeterminationServiceConcret;
import org.tela_botanica.del.client.services.rest.ProtocoleService;
import org.tela_botanica.del.client.services.rest.async.ObservationsCallback;
import org.tela_botanica.del.client.services.rest.async.ProtocolesCallback;
import org.tela_botanica.del.client.utils.URLUtils;
import org.tela_botanica.del.client.vues.pictoflora.plateformedetermination.ligneProtocole.LigneProtocolePresenteur;
import org.tela_botanica.del.client.vues.pictoflora.plateformedetermination.ligneProtocole.LigneProtocoleVue;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Panel;
 
public class PictofloraDeterminationPresenteur extends Presenteur {
 
/**
* Vue de l'interface de détermination
* */
public interface Vue extends IsWidget {
public Panel getForum();
 
public Panel getDetailImageObservation();
 
public Panel getFormulaireRechercheEflore();
 
public Panel getVoteProtocole();
 
public Button getBoutonAjoutProposition();
 
public Button getBoutonAjoutCommentaire();
 
public Button getBoutonAjoutPropositionBas();
 
public Button getBoutonAjoutCommentaireBas();
 
public HasWidgets getMetadonnees();
 
public HasWidgets getNouvelleLigneProtocole();
 
public void afficherNomTaxonProbable(String nomTaxon);
public HasClickHandlers getLienOuvrages();
public HasClickHandlers getLienBonnier();
public HasClickHandlers getLienCles();
public HasClickHandlers getLienEflore();
public HasWidgets getZoneRss();
}
 
private Vue vue;
private FenetreOverlaySimplePresenteur fenetreOverlaySimplePresenteur;
 
// Déclaration des services à utiliser
private ProtocoleService protocoleService;
private ObservationService observationService;
 
private CacheClient cache = CacheClient.getInstance();
 
public PictofloraDeterminationPresenteur(Vue vue, ObservationService observationService, ProtocoleService protocoleService) {
this.vue = vue;
this.protocoleService = protocoleService;
this.observationService = observationService;
}
 
public void go(final HasWidgets composite) {
 
// TODO afficher une icone de chargement si le chargement devient trop
// long
// car tout l'écran est asynchrone ici
String observationId = URLUtils.getURLSpecialParameterValue();
 
observationService.getObservation(observationId, new ObservationsCallback() {
 
@Override
public void surRetour(ObservationServiceResultat objetRetour) {
afficherRss(cache.getObservationCourante());
// trouve l'image courante si elle n'est pas deja en cache
List<Image> listeImages = cache.getObservationCourante().getImages();
if (listeImages.size() > 0) {
CacheClient.getInstance().setImageCourante(listeImages.get(0));
} else {
CacheClient.getInstance().setImageCourante(null);
}
 
new MetadonneesPresenteur(new MetadonneesEnLigneVue(), cache.getObservationCourante(), ModeRecherche.MODE_OBSERVATION, false).go(vue.getMetadonnees());
new ObservationImagesPresenteur(new ObservationImagesVue(), cache.getObservationCourante(), CacheClient.getInstance().getImageCourante(), ConstantesNavigation.PAGE_VALIDATION_PICTOFLORA).go(vue.getDetailImageObservation());
chargerEtAjouterLignesVotesProtocole();
new ForumPresenteur(new ForumVue()).go(vue.getForum());
new FormulaireRechercheEflorePresenteur().go(vue.getFormulaireRechercheEflore());
 
calculerEtAfficherVoteDeterminationPlusPopulaire();
composite.add(vue.asWidget());
 
}
 
@Override
public void surErreur(String messageErreur) {
Window.alert(messageErreur);
}
});
gererEvenements();
}
 
public void afficherRss(Observation observation) {
new RssPresenteur(new RssVue(), observation, "Suivre cette observation").go(vue.getZoneRss());
}
private void chargerEtAjouterLignesVotesProtocole() {
if (cache.getListeProtocoles() == null) {
protocoleService.getProtocoles(new ProtocolesCallback() {
 
@Override
public void surRetour(ProtocoleServiceResultat protocolesRecus) {
List<Protocole> listeProtocoles = protocolesRecus.getProtocoles();
ajouterLignesVotesProtocole(listeProtocoles);
}
});
} else {
List<Protocole> listeProtocoles = cache.getListeProtocoles();
ajouterLignesVotesProtocole(listeProtocoles);
}
}
 
private void ajouterLignesVotesProtocole(List<Protocole> listeProtocoles) {
for (Iterator<Protocole> iterator = listeProtocoles.iterator(); iterator.hasNext();) {
Protocole protocole = iterator.next();
LigneProtocolePresenteur presenteurLigneProtocole = new LigneProtocolePresenteur(protocole, new LigneProtocoleVue());
presenteurLigneProtocole.go(vue.getNouvelleLigneProtocole());
}
}
 
private void calculerEtAfficherVoteDeterminationPlusPopulaire() {
 
Observation observation = cache.getObservationCourante();
String nomTaxon = observation.getNomRetenu();
 
List<MoyenneVote> votesOrdonnes = CalculVoteDeterminationService.calculerVoteDeterminationPlusPopulaire(cache.getObservationCourante().getPropositionDeterminations());
if (votesOrdonnes.size() > 0) {
nomTaxon = votesOrdonnes.get(0).getIntituleAssocie();
}
 
vue.afficherNomTaxonProbable(nomTaxon);
}
 
public void gererEvenements() {
BusEvenementiel.getInstance().addHandler(EvenementVoteDetermination.TYPE, new GestionnaireEvenementVoteDetermination() {
@Override
public void onVoteDetermination(VoteDetermination event) {
calculerEtAfficherVoteDeterminationPlusPopulaire();
}
});
 
ClickHandler clicAjoutProposition = new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
fenetreOverlaySimplePresenteur = new FenetreOverlaySimplePresenteur(new FenetreOverlayDefilanteVue());
fenetreOverlaySimplePresenteur.ouvrirFenetreModale(new FormulairePropositionPresenteur(new FormulairePropositionVue(), new PropositionDeterminationServiceConcret()));
}
};
vue.getBoutonAjoutProposition().addClickHandler(clicAjoutProposition);
vue.getBoutonAjoutPropositionBas().addClickHandler(clicAjoutProposition);
 
ClickHandler clicAjoutCommentaire = new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
FormulaireCommentairePresenteur commentairePresenteur = new FormulaireCommentairePresenteur(cache.getObservationCourante(), new CommentaireServiceConcret(), new FormulaireCommentaireVue());
fenetreOverlaySimplePresenteur = new FenetreOverlaySimplePresenteur(new FenetreOverlayDefilanteVue());
fenetreOverlaySimplePresenteur.ouvrirFenetreModale(commentairePresenteur);
}
};
vue.getBoutonAjoutCommentaire().addClickHandler(clicAjoutCommentaire);
vue.getBoutonAjoutCommentaireBas().addClickHandler(clicAjoutCommentaire);
 
BusEvenementiel.getInstance().addHandler(EvenementAjoutDetermination.TYPE, new GestionnaireEvenementAjoutDetermination() {
@Override
public void onAjoutDetermination(EvenementAjoutDetermination event) {
if (fenetreOverlaySimplePresenteur != null && fenetreOverlaySimplePresenteur.fenetreModaleEstOuverte()) {
fenetreOverlaySimplePresenteur.fermerFenetreModale();
}
}
});
 
BusEvenementiel.getInstance().addHandler(EvenementAjoutCommentaire.TYPE, new GestionnaireEvenementAjoutCommentaire() {
 
@Override
public void onAjoutCommentaire(EvenementAjoutCommentaire event) {
if (fenetreOverlaySimplePresenteur != null && fenetreOverlaySimplePresenteur.fenetreModaleEstOuverte()) {
fenetreOverlaySimplePresenteur.fermerFenetreModale();
}
}
});
 
BusEvenementiel.getInstance().addHandler(EvenementChangementImageValidation.TYPE, new GestionnaireEvenementChangementImageValidation() {
 
@Override
public void onChangementImage(EvenementChangementImageValidation event) {
vue.getDetailImageObservation().clear();
vue.getVoteProtocole().clear();
new ObservationImagesPresenteur(new ObservationImagesVue(), cache.getObservationCourante(), CacheClient.getInstance().getImageCourante(), ConstantesNavigation.PAGE_VALIDATION_PICTOFLORA).go(vue.getDetailImageObservation());
chargerEtAjouterLignesVotesProtocole();
}
});
vue.getLienOuvrages().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Config config = new Config();
Window.open(config.getUrl("ouvragesFlore"), "Flores numérisées", null);
}
});
 
vue.getLienBonnier().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Config config = new Config();
Window.open(config.getUrl("bonnierPda"), "Flore Bonnier PDA", null);
}
});
vue.getLienCles().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Config config = new Config();
Window.open(config.getUrl("clesDetermination"), "Clés de determination", null);
}
});
vue.getLienEflore().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Config config = new Config();
Window.open(config.getUrl("eflore"), "eFlore", null);
}
});
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/plateformedetermination/detail/DetailImageObservationVue.ui.xml
New file
0,0 → 1,36
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
 
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary"/>
<ui:style src="detailObservation.css" />
<g:VerticalPanel>
<g:Image ui:field="imageObservation"/>
<g:VerticalPanel ui:field="detailObservation" styleName="{style.detailObservation}">
<g:HorizontalPanel styleName="{style.observateur}">
<!-- g:Label text="{constants.observateur} : "/ -->
<g:Label ui:field="nomObservateur" /><g:HTML>&nbsp;-&nbsp;</g:HTML><g:Label ui:field="localite" /><g:HTML>&nbsp;-&nbsp;</g:HTML><g:Label ui:field="dateObservation" />
</g:HorizontalPanel>
<g:HorizontalPanel>
<!-- <g:Label text="{constants.nom_retenu} : "/> -->
<g:Label ui:field="nomRetenu" styleName="{style.nomRetenu}"/>
</g:HorizontalPanel>
<g:HorizontalPanel styleName="{style.date}">
<!-- <g:Label text="{constants.date_observation} : "/> -->
</g:HorizontalPanel>
<g:HorizontalPanel>
<!-- <g:Label text="{constants.famille} : "/> -->
<g:HorizontalPanel><g:Label ui:field="famille" /></g:HorizontalPanel>
</g:HorizontalPanel>
<g:HorizontalPanel>
<!-- <g:Label text="{constants.localite} : "/> -->
</g:HorizontalPanel>
</g:VerticalPanel>
</g:VerticalPanel>
 
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/plateformedetermination/detail/DetailImageObservationPresenteur.java
New file
0,0 → 1,24
package org.tela_botanica.del.client.vues.pictoflora.plateformedetermination.detail;
 
import org.tela_botanica.del.client.cache.CacheClient;
 
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class DetailImageObservationPresenteur {
public interface Vue extends IsWidget {
public void chargerInformationsObservation(org.tela_botanica.del.client.modeles.Image image);
}
 
private Vue vue;
public DetailImageObservationPresenteur(Vue vue) {
this.vue = vue;
}
 
public void go(HasWidgets composite) {
vue.chargerInformationsObservation(CacheClient.getInstance().getImageCourante());
composite.add(vue.asWidget());
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/plateformedetermination/detail/DetailImageObservationVue.java
New file
0,0 → 1,38
package org.tela_botanica.del.client.vues.pictoflora.plateformedetermination.detail;
 
 
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
 
public class DetailImageObservationVue extends Composite implements DetailImageObservationPresenteur.Vue {
 
@UiField
protected Image imageObservation;
 
@UiField
protected Label nomObservateur, nomRetenu, dateObservation, famille, localite;
 
private static DetailImageObservationUIiBinder uiBinder = GWT.create(DetailImageObservationUIiBinder.class);
 
interface DetailImageObservationUIiBinder extends UiBinder<Widget, DetailImageObservationVue> {
};
 
public DetailImageObservationVue() {
initWidget(uiBinder.createAndBindUi(this));
}
 
public void chargerInformationsObservation(org.tela_botanica.del.client.modeles.Image image) {
imageObservation.setUrl(image.getUrl());
nomObservateur.setText(image.getObservation().getAuteur());
nomRetenu.setText(image.getObservation().getNomRetenuFormateReferentiel());
famille.setText(image.getObservation().getFamille());
localite.setText(image.getObservation().getLocalite());
dateObservation.setText(image.getObservation().getDateReleve());
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/plateformedetermination/detail/detailObservation.css
New file
0,0 → 1,27
.detailObservation {
font-size: 11px;
position: absolute;
padding: 5px;
color: white;
background: #333;
opacity: 0.8;
margin-top: -80px;
width: 230px;
}
 
.observateur td {
font-size: 11px;
white-space: nowrap
}
 
.date {
}
 
.nomRetenu {
font-weight: bold
}
 
.dateObservation {
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/plateformedetermination/PictofloraDeterminationVue.java
New file
0,0 → 1,117
package org.tela_botanica.del.client.vues.pictoflora.plateformedetermination;
 
import org.tela_botanica.del.client.gestionhistorique.ConstantesNavigation;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class PictofloraDeterminationVue extends Composite implements PictofloraDeterminationPresenteur.Vue {
 
@UiField
Panel forum, detailImageObservation, formulaireRechercheEflore, voteProtocole, zoneRss;
@UiField
Label nomTaxonProbable, lienOuvrages, lienEflore, lienBonnier, lienCles;
@UiField
Hyperlink lienRetour;
@UiField
Button boutonAjoutProposition, boutonAjoutPropositionBas, boutonAjoutCommentaire, boutonAjoutCommentaireBas;
@UiField
Panel metadonnees;
 
interface DeterminationUIiBinder extends UiBinder<Widget, PictofloraDeterminationVue> {
};
 
private static DeterminationUIiBinder uiBinder = GWT.create(DeterminationUIiBinder.class);
 
public PictofloraDeterminationVue() {
initWidget(uiBinder.createAndBindUi(this));
lienRetour.setTargetHistoryToken(ConstantesNavigation.HOME);
}
 
public Panel getForum() {
return forum;
}
 
public Panel getDetailImageObservation() {
return detailImageObservation;
}
 
public Panel getFormulaireRechercheEflore() {
return formulaireRechercheEflore;
}
 
public Panel getVoteProtocole() {
return voteProtocole;
}
public Button getBoutonAjoutProposition() {
return boutonAjoutProposition;
}
public Button getBoutonAjoutPropositionBas() {
return boutonAjoutPropositionBas;
}
public Panel getMetadonnees() {
return metadonnees;
}
 
@Override
public void afficherNomTaxonProbable(String nomTaxon) {
this.nomTaxonProbable.setText(nomTaxon);
}
 
@Override
public HasWidgets getNouvelleLigneProtocole() {
HTMLPanel nouvelleLigne = new HTMLPanel("");
this.voteProtocole.add(nouvelleLigne);
return nouvelleLigne;
}
 
public Button getBoutonAjoutCommentaire() {
return boutonAjoutCommentaire;
}
public Button getBoutonAjoutCommentaireBas() {
return boutonAjoutCommentaireBas;
}
 
@Override
public HasClickHandlers getLienOuvrages() {
return lienOuvrages;
}
 
@Override
public HasClickHandlers getLienBonnier() {
return lienBonnier;
}
 
@Override
public HasClickHandlers getLienCles() {
return lienCles;
}
 
@Override
public HasClickHandlers getLienEflore() {
return lienEflore;
}
public HasWidgets getZoneRss() {
return zoneRss;
}
}
 
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/plateformedetermination/ligneProtocole/ligneProtocole.css
New file
0,0 → 1,7
.nomProtocole {
font-size: 11px;
overflow: hidden;
text-overflow: ellipsis;
width: 87px;
margin-bottom:15px;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/plateformedetermination/ligneProtocole/LigneProtocoleVue.ui.xml
New file
0,0 → 1,10
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:forum="urn:import:org.tela_botanica.del.client.composants.forum">
<ui:style src="ligneProtocole.css" />
<g:HorizontalPanel styleName="vote">
<g:HTMLPanel ui:field="zoneVote" />
</g:HorizontalPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/plateformedetermination/ligneProtocole/LigneProtocolePresenteur.java
New file
0,0 → 1,59
package org.tela_botanica.del.client.vues.pictoflora.plateformedetermination.ligneProtocole;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.composants.votes.moyennevotes.MoyenneVotePresenteur;
import org.tela_botanica.del.client.composants.votes.moyennevotes.MoyenneVoteVue;
import org.tela_botanica.del.client.modeles.Image;
import org.tela_botanica.del.client.modeles.Protocole;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.changementimagevalidation.EvenementChangementImageValidation;
import org.tela_botanica.del.client.navigation.evenement.changementimagevalidation.GestionnaireEvenementChangementImageValidation;
import org.tela_botanica.del.client.services.rest.VoteProtocoleServiceConcret;
 
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class LigneProtocolePresenteur extends Presenteur {
 
public interface Vue extends IsWidget {
 
HasWidgets getZoneVote();
}
 
private Vue vue;
private Protocole protocole;
 
public LigneProtocolePresenteur(Protocole protocole, Vue vue) {
this.vue = vue;
this.protocole = protocole;
chargerValeursProtocolePourImageCourante();
}
public void chargerValeursProtocolePourImageCourante(){
vue.getZoneVote().clear();
Image imageCourante = CacheClient.getInstance().getImageCourante();
MoyenneVotePresenteur votePresenteur = new MoyenneVotePresenteur(imageCourante, protocole, new MoyenneVoteVue(), new VoteProtocoleServiceConcret());
votePresenteur.go(vue.getZoneVote());
}
 
public Vue getVue() {
return vue;
}
 
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
gererEvenements();
}
 
@Override
protected void gererEvenements() {
BusEvenementiel.getInstance().addHandler(EvenementChangementImageValidation.TYPE, new GestionnaireEvenementChangementImageValidation() {
 
@Override
public void onChangementImage(EvenementChangementImageValidation event) {
chargerValeursProtocolePourImageCourante();
}
});
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/plateformedetermination/ligneProtocole/LigneProtocoleVue.java
New file
0,0 → 1,30
package org.tela_botanica.del.client.vues.pictoflora.plateformedetermination.ligneProtocole;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class LigneProtocoleVue extends Composite implements LigneProtocolePresenteur.Vue {
@UiField
Panel zoneVote;
interface LigneProtocoleUIiBinder extends UiBinder<Widget, LigneProtocoleVue> {
};
 
private static LigneProtocoleUIiBinder uiBinder = GWT.create(LigneProtocoleUIiBinder.class);
 
public LigneProtocoleVue() {
initWidget(uiBinder.createAndBindUi(this));
}
 
@Override
public HasWidgets getZoneVote() {
return this.zoneVote;
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/plateformedetermination/determinationVue.css
New file
0,0 → 1,120
.pageDetermination {
}
.metadonnees {
margin-bottom:10px;
margin-top:10px;
display:inline-block;
}
.zoneVote {
margin-left: 5px;
height: 100%;
display:inline-block;
vertical-align:top;
border-left: solid 1px #DDD;
border-right: solid 1px #DDD;
padding-left: 10px;
padding-right:10px;
text-align:left;
}
 
.taxonPlusProbable {
float: left;
}
 
.zoneBarreRepartition {
border: solid 1px #DDD;
padding: 15px;
}
 
.zoneDetailImage {
height: 100%;
width: 255px;
display:inline-block;
vertical-align:top;
text-align:left;
clear: left;
}
 
.zoneImage {
margin-bottom: 10px;
margin-right: 15px
}
 
.zoneImage div {
clear: left;
padding-top: 5px;
}
 
.zoneImage div img {
float: left;
padding: 0 5px 0 0;
}
 
.boutonProposer {
float: left;
padding: 5px;
cursor: pointer;
background:#8EB533;
border:none;
margin-right:10px;
margin-top:10px;
}
 
.zoneOutils {
width: 15%;
padding-left:10px;
display:inline-block;
vertical-align:top;
text-align:left;
}
 
.boutons {
margin-bottom:15px;
}
 
.lienProposerObservation {
margin-left: 575px;
}
 
.nomTaxonProbable{
padding-left:3px;
}
 
.taxonProbable {
background: none repeat scroll 0 0 #F8F8C3;
clear: left;
font-size: 15px;
margin-bottom: 5px;
padding: 13px 9px;
}
 
.voteProtocole div {
margin-bottom:10px;
}
 
.voteProtocole div div {
margin-bottom:0px;
border:solid 0px red
}
.autreOutils {
margin-top:15px;
}
 
.zonerss {
margin-top:5px;
}
 
.lienProposerImage {
margin-top:20px;
margin-left:70px;
margin-bottom:10px;
}
 
.lienAide {
margin-right:70px;
padding:4px 15px;
margin-top:19px;
float:right;
color:white;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/plateformedetermination/PictofloraDeterminationVue.ui.xml
New file
0,0 → 1,56
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:forum="urn:import:org.tela_botanica.del.client.composants.forum">
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary"/>
<ui:style src="determinationVue.css" />
<g:HTMLPanel styleName="{style.pageDetermination}">
<g:HTMLPanel styleName="limiteMax">
<g:Hyperlink ui:field="lienRetour" styleName="lien">Retour</g:Hyperlink>
<g:HTMLPanel ui:field="metadonnees" styleName="{style.metadonnees}"/>
</g:HTMLPanel>
<g:HTMLPanel styleName="contenuCentre">
<g:HTMLPanel styleName="{style.zoneDetailImage}">
<g:VerticalPanel ui:field="detailImageObservation" styleName="{style.zoneImage}"/>
<g:Label text="Votes associés à l'image" styleName="titre"></g:Label>
<g:HTMLPanel ui:field="voteProtocole" styleName="{style.voteProtocole}"/>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.zoneVote}">
<g:Label styleName="titre" text="{constants.titreDetermination}" />
<g:HTMLPanel styleName="nettoyage {style.boutons}">
<g:Button text="{constants.proposerSaDetermination}" ui:field="boutonAjoutProposition" styleName="bouton" />
<g:Button text="{constants.ajouterCommentaire}" ui:field="boutonAjoutCommentaire" styleName="bouton" />
<g:HTMLPanel ui:field="zoneRss" styleName="droite {style.zonerss}"></g:HTMLPanel>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.taxonProbable}">
<g:Label styleName="gauche" text="{constants.determinationPlusProbable}" />
<g:Label ui:field="nomTaxonProbable" styleName="gauche gras {style.nomTaxonProbable}"/>
<g:HTML><br /></g:HTML>
</g:HTMLPanel>
<g:VerticalPanel ui:field="forum" />
<g:HTMLPanel styleName="nettoyage {style.boutons}">
<g:Button text="{constants.proposerSaDetermination}" ui:field="boutonAjoutPropositionBas" styleName="bouton" />
<g:Button text="{constants.ajouterCommentaire}" ui:field="boutonAjoutCommentaireBas" styleName="bouton" />
</g:HTMLPanel>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.zoneOutils}">
<g:Label text="Pour vous aider : " styleName="titre3"></g:Label>
<g:VerticalPanel ui:field="formulaireRechercheEflore"/>
<g:Label styleName="{style.autreOutils} sousTitre">Vérifier sa détermination</g:Label>
<g:Label styleName="lienListe labelLien" ui:field="lienEflore">eFlore</g:Label>
<g:Label styleName="{style.autreOutils} sousTitre">Autres outils en ligne</g:Label>
<g:Label styleName="lienListe labelLien" ui:field="lienOuvrages">Flores numérisées</g:Label>
<g:Label styleName="lienListe labelLien" ui:field="lienBonnier">Flore Bonnier interactive</g:Label>
<g:Label styleName="lienListe labelLien" ui:field="lienCles">Clés de détermination</g:Label>
</g:HTMLPanel>
</g:HTMLPanel>
</g:HTMLPanel>
 
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/resultats/ResultatPictofloraVue.ui.xml
New file
0,0 → 1,43
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui' ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
ui:generateLocales="default">
 
<ui:style src="ResultatPictoflora.css" />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
 
<g:HTMLPanel styleName="{style.contenuResultat}">
<g:HTMLPanel styleName="{style.barreNavigation} limiteMax limiteMin">
<g:VerticalPanel ui:field="panneauPaginationHaut" styleName="gauche {style.paginationHaut}" />
<g:HTMLPanel ui:field="zoneTri" styleName="gauche {style.zoneTri} petit">
<g:Label text="{constants.tri}" styleName="gauche {style.labeltri}"/>
<g:HTMLPanel ui:field="triParNbVotes" styleName="gauche">
<g:Label text="{constants.triParNbVotes}" styleName="gauche {style.votes}" ui:field="labelVote"/>
<g:Button title="{constants.triParNbVotesAscendant}" ui:field="triParNbVotesAscendant" styleName="{style.boutonTriAsc} gauche" />
<g:Button title="{constants.triParNbVotesDescendant}" ui:field="triParNbVotesDescendant" styleName="{style.boutonTriDesc} gauche" />
</g:HTMLPanel>
<g:HTMLPanel ui:field="triParDate" styleName="gauche">
<g:Label text="{constants.triParDate}" styleName="gauche {style.date}" ui:field="labelDate"/>
<g:Button title="{constants.triParDateAscendant}" ui:field="triParDateAscendant" styleName="{style.boutonTriAsc} gauche" />
<g:Button title="{constants.triParDateDescendant}" ui:field="triParDateDescendant" styleName="{style.boutonTriDesc} gauche" />
</g:HTMLPanel>
<g:HTMLPanel ui:field="triParNbTags" styleName="gauche">
<g:Label text="{constants.triParNbTags}" styleName="gauche {style.tag}" ui:field="labelTag"/>
<g:Button title="{constants.triParNbTagsAscendant}" ui:field="triParNbTagsAscendant" styleName="{style.boutonTriAsc} gauche" />
<g:Button title="{constants.triParNbTagsDescendant}" ui:field="triParNbTagsDescendant" styleName="{style.boutonTriDesc} gauche" />
</g:HTMLPanel>
</g:HTMLPanel>
</g:HTMLPanel>
<g:VerticalPanel ui:field="panneauChargement">
<g:Image url="./img/wait.gif"></g:Image>
</g:VerticalPanel>
<g:Label ui:field="aucunResultat" styleName="{style.aucunResultat}" text="{constants.aucunResultat}" visible="false" />
<g:HTMLPanel ui:field="imageTable" styleName="{style.images}" />
<g:HTMLPanel styleName="nettoyage"></g:HTMLPanel>
<g:VerticalPanel ui:field="panneauPagination" styleName="limiteMax limiteMin"/>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/resultats/ResultatPictofloraPresenteur.java
New file
0,0 → 1,365
package org.tela_botanica.del.client.vues.pictoflora.resultats;
 
import java.util.List;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.pagination.PaginationPresenteur;
import org.tela_botanica.del.client.composants.pagination.PaginationVue;
import org.tela_botanica.del.client.modeles.Image;
import org.tela_botanica.del.client.modeles.ImageServiceResultat;
import org.tela_botanica.del.client.modeles.InformationsRecherche;
import org.tela_botanica.del.client.modeles.ModeTri;
import org.tela_botanica.del.client.modeles.Protocole;
import org.tela_botanica.del.client.modeles.ProtocoleServiceResultat;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.changementprotocole.EvenementChangementProtocole;
import org.tela_botanica.del.client.navigation.evenement.changementprotocole.GestionnaireEvenementChangementProtocole;
import org.tela_botanica.del.client.services.rest.ImageService;
import org.tela_botanica.del.client.services.rest.ProtocoleService;
import org.tela_botanica.del.client.services.rest.async.ImagesParTaxonCallback;
import org.tela_botanica.del.client.services.rest.async.ProtocolesCallback;
import org.tela_botanica.del.client.vues.pictoflora.resultats.images.ImagePresenteur;
import org.tela_botanica.del.client.vues.pictoflora.resultats.images.ImageVue;
 
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.OptionElement;
import com.google.gwt.dom.client.SelectElement;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasChangeHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.ListBox;
 
public class ResultatPictofloraPresenteur {
public interface Vue extends IsWidget {
public void startChargement();
 
public void nettoyer();
 
public void creerPanneauxObservations(int size);
 
public void stopChargement();
 
public List<HasWidgets> getPanneauxImages();
 
public HasWidgets getPanneauPagination();
 
public HasWidgets getPanneauPaginationHaut();
 
public HasClickHandlers getTriParNbVotesAscendant();
 
public HasClickHandlers getTriParNbVotesDescendant();
 
public HasClickHandlers getTriParDateAscendant();
 
public HasClickHandlers getTriParDateDescendant();
public HasClickHandlers getTriParNbTagsAscendant();
 
public HasClickHandlers getTriParNbTagsDescendant();
 
public void afficherElementsAucunResultatTrouve();
 
public void afficherElementsResultatsTrouve();
 
public HTMLPanel getImageTable();
 
public HasClickHandlers getLabelVote();
 
public void masquerVoteAscendant();
 
public void masquerVoteDescendant();
 
public void afficherVoteAscendant();
 
public void afficherVoteDescendant();
 
public HasClickHandlers getLabelDate();
public HasClickHandlers getLabelTag();
 
public void masquerDateAscendant();
 
public void masquerDateDescendant();
 
public void afficherDateAscendant();
 
public void afficherDateDescendant();
 
public void masquerTagAscendant();
 
public void afficherTagDescendant();
 
public void masquerTagDescendant();
 
public void afficherTagAscendant();
 
}
 
private Vue vue;
private ImageService imageService;
private final ProtocoleService protocoleService;
private ModeTri triCourantVote = ModeTri.TRI_ASCENDANT;
private ModeTri triCourantDate = ModeTri.TRI_DESCENDANT;
private ModeTri triCourantTag = ModeTri.TRI_DESCENDANT;
 
public ResultatPictofloraPresenteur(ImageService imageService, ProtocoleService protocoleService, Vue vue) {
this.vue = vue;
this.imageService = imageService;
this.protocoleService=protocoleService;
}
 
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
vue.startChargement();
rechercherImagesEtCreerWidgetPagination();
gererEvenements();
vue.masquerVoteDescendant();
vue.masquerVoteAscendant();
vue.masquerDateDescendant();
vue.masquerDateAscendant();
vue.masquerTagAscendant();
vue.masquerTagDescendant();
initialiserAPartirInfosCache();
}
private void initialiserAPartirInfosCache() {
InformationsRecherche infos = CacheClient.getInstance().getInformationsRechercheImage();
if(infos.getTriParDate() != ModeTri.PAS_DE_TRI) {
mettreAJourAffichageTriDate();
}
if(infos.getTriParNbVotes() != ModeTri.PAS_DE_TRI) {
mettreAJourAffichageTriVote();
}
if(infos.getTriParNbTags() != ModeTri.PAS_DE_TRI) {
mettreAjourAffichageTriTag();
}
}
 
public void gererEvenements() {
ClickHandler surClicTriVote = new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
surClicTriVote();
}
};
 
vue.getLabelVote().addClickHandler(surClicTriVote);
vue.getTriParNbVotesAscendant().addClickHandler(surClicTriVote);
vue.getTriParNbVotesDescendant().addClickHandler(surClicTriVote);
 
ClickHandler surClicTriDate = new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
surClicTriDate();
}
};
 
vue.getLabelDate().addClickHandler(surClicTriDate);
vue.getTriParDateAscendant().addClickHandler(surClicTriDate);
vue.getTriParDateDescendant().addClickHandler(surClicTriDate);
ClickHandler surClicTriTag = new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
surClicTriTag();
}
};
vue.getLabelTag().addClickHandler(surClicTriTag);
vue.getTriParNbTagsAscendant().addClickHandler(surClicTriTag);
vue.getTriParNbTagsDescendant().addClickHandler(surClicTriTag);
 
BusEvenementiel.getInstance().addHandler(EvenementChangementProtocole.TYPE, new GestionnaireEvenementChangementProtocole() {
@Override
public void onChangementProtocole(EvenementChangementProtocole event) {
InformationsRecherche informationsRechercheImages = CacheClient.getInstance().getInformationsRechercheImage();
if (informationsRechercheImages.getTriParNbVotes() != ModeTri.PAS_DE_TRI) {
informationsRechercheImages.setIdProtocoleSelectionne(event.getProtocole().getId() + "");
chargerEtAfficherImagesPageEnCours();
}
}
});
}
 
protected void surClicTriTag() {
mettreAjourAffichageTriTag();
InformationsRecherche informationsRechercheImages = CacheClient.getInstance().getInformationsRechercheImage();
informationsRechercheImages.setTriParNbTags(triCourantTag);
informationsRechercheImages.setTriParDate(ModeTri.PAS_DE_TRI);
informationsRechercheImages.setTriParNbVotes(ModeTri.PAS_DE_TRI);
chargerEtAfficherImagesPageEnCours();
}
private void mettreAjourAffichageTriTag() {
vue.masquerDateDescendant();
vue.masquerDateAscendant();
vue.masquerVoteDescendant();
vue.masquerVoteAscendant();
if (triCourantTag == ModeTri.TRI_ASCENDANT) {
triCourantTag = ModeTri.TRI_DESCENDANT;
vue.masquerTagAscendant();
vue.afficherTagDescendant();
} else {
triCourantTag = ModeTri.TRI_ASCENDANT;
vue.masquerTagDescendant();
vue.afficherTagAscendant();
}
}
 
public void surClicTriVote() {
mettreAJourAffichageTriVote();
InformationsRecherche informationsRechercheImages = CacheClient.getInstance().getInformationsRechercheImage();
int IdProtocole = CacheClient.getInstance().getProtocoleCourant().getId();
informationsRechercheImages.setTriParNbVotes(triCourantVote);
informationsRechercheImages.setIdProtocoleSelectionne(IdProtocole + "");
informationsRechercheImages.setTriParDate(ModeTri.PAS_DE_TRI);
informationsRechercheImages.setTriParNbTags(ModeTri.PAS_DE_TRI);
chargerEtAfficherImagesPageEnCours();
}
private void mettreAJourAffichageTriVote() {
vue.masquerDateDescendant();
vue.masquerDateAscendant();
vue.masquerTagAscendant();
vue.masquerTagDescendant();
if (triCourantVote == ModeTri.TRI_ASCENDANT) {
triCourantVote = ModeTri.TRI_DESCENDANT;
vue.masquerVoteAscendant();
vue.afficherVoteDescendant();
} else {
triCourantVote = ModeTri.TRI_ASCENDANT;
vue.masquerVoteDescendant();
vue.afficherVoteAscendant();
}
}
 
public void surClicTriDate() {
mettreAJourAffichageTriDate();
InformationsRecherche informationsRechercheImages = CacheClient.getInstance().getInformationsRechercheImage();
informationsRechercheImages.setTriParDate(triCourantDate);
informationsRechercheImages.setTriParNbVotes(ModeTri.PAS_DE_TRI);
informationsRechercheImages.setTriParNbTags(ModeTri.PAS_DE_TRI);
chargerEtAfficherImagesPageEnCours();
}
private void mettreAJourAffichageTriDate() {
vue.masquerTagAscendant();
vue.masquerTagDescendant();
vue.masquerVoteDescendant();
vue.masquerVoteAscendant();
if (triCourantDate == ModeTri.TRI_ASCENDANT) {
triCourantDate = ModeTri.TRI_DESCENDANT;
vue.masquerDateAscendant();
vue.afficherDateDescendant();
} else {
triCourantDate = ModeTri.TRI_ASCENDANT;
vue.masquerDateDescendant();
vue.afficherDateAscendant();
}
}
 
public void rechercherImagesEtCreerWidgetPagination() {
// appel du service d'image pour avoir le nb total d'elements pour la
// pagination
ImagesParTaxonCallback callback = new ImagesParTaxonCallback() {
 
@Override
public void surRetour(ImageServiceResultat imagesRecues) {
creerWidgetPagination(imagesRecues.getNbTotalImagesPourLaRecherche());
afficherImages(imagesRecues);
 
}
 
@Override
public void surErreur(String messageErreur) {
Window.alert(messageErreur);
 
}
};
final int debut = (CacheClient.getInstance().getPageCouranteRechercheImage() - 1) * CacheClient.getInstance().getPasPagination();
final int fin = (CacheClient.getInstance().getPageCouranteRechercheImage()) * CacheClient.getInstance().getPasPagination();
imageService.getImagesParTaxon(CacheClient.getInstance().getInformationsRechercheImage(), debut, fin, callback);
}
 
private void chargerEtAfficherImages(final int premier, final int dernier) {
vue.startChargement();
vue.nettoyer();
ImagesParTaxonCallback callback = new ImagesParTaxonCallback() {
 
@Override
public void surRetour(ImageServiceResultat imagesRecues) {
afficherImages(imagesRecues);
}
 
@Override
public void surErreur(String messageErreur) {
Window.alert(messageErreur);
}
 
};
imageService.getImagesParTaxon(CacheClient.getInstance().getInformationsRechercheImage(), premier, dernier, callback);
}
 
public void afficherImages(ImageServiceResultat imageServiceResult) {
List<Image> images = imageServiceResult.getImages();
if (images == null || images.size() == 0) {
vue.afficherElementsAucunResultatTrouve();
} else {
vue.afficherElementsResultatsTrouve();
for (Image image : images) {
ImagePresenteur imagePresenteur = new ImagePresenteur(image, CacheClient.getInstance().getProtocoleCourant(), new ImageVue());
imagePresenteur.go(vue.getImageTable());
}
}
CacheClient.getInstance().mettreAjourUrlCourante();
vue.stopChargement();
}
 
private void creerWidgetPagination(int nbImages) {
PaginationPresenteur imagesPaginationPresenteurHaut = creerPresenteurPagination(nbImages);
PaginationPresenteur imagesPaginationPresenteurBas = creerPresenteurPagination(nbImages);
imagesPaginationPresenteurHaut.setGroupePagination("pagination_images");
imagesPaginationPresenteurBas.setGroupePagination("pagination_images");
imagesPaginationPresenteurHaut.go(vue.getPanneauPaginationHaut());
imagesPaginationPresenteurBas.go(vue.getPanneauPagination());
}
 
public PaginationPresenteur creerPresenteurPagination(int nbImages) {
PaginationPresenteur imagesPaginationPresenteur = new PaginationPresenteur(new PaginationVue(), nbImages, CacheClient.getInstance().getPasPagination(), CacheClient.getInstance().getPageCouranteRechercheImage()) {
@Override
public void chargerElements(int debut, int fin) {
chargerEtAfficherImages(debut, fin);
CacheClient.getInstance().setPageCouranteRechercheImages(getPageCourante());
}
 
@Override
public void actualiserPasCache(int pas) {
CacheClient.getInstance().setPasPagination(pas);
}
};
return imagesPaginationPresenteur;
}
 
public void chargerEtAfficherImagesPageEnCours() {
final int debut = (CacheClient.getInstance().getPageCouranteRechercheImage() - 1) * CacheClient.getInstance().getPasPagination();
final int fin = (CacheClient.getInstance().getPageCouranteRechercheImage()) * CacheClient.getInstance().getPasPagination();
chargerEtAfficherImages(debut, fin);
}
 
public Vue getVue() {
return vue;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/resultats/images/image.css
New file
0,0 → 1,136
.observations {
width: 250px;
height: 250px;
margin-bottom: 50px;
}
 
.observations img {
width: 250px;
padding: 0;
}
 
.zoneCache {
position: absolute;
padding: 5px;
border: solid 1px #CCC;
background: #333;
opacity: 0.9;
color: white;
width: 250px;
z-index: 1000;
margin-top: 30px;
}
 
.zoneMotsCles {
position: absolute;
padding: 5px;
border: solid 1px #CCC;
background: #333;
opacity: 0.9;
color: white;
width: 239px;
z-index: 1000;
margin-top: 212px;
}
 
.enSavoirPlus {
position: absolute;
background: url(./img/ajouter.png) no-repeat;
width: 30px;
height: 30px;
cursor: pointer;
margin-top: 3px;
margin-left: 3px;
}
 
.voirMotsCles {
position: absolute;
background: url(./img/tagger.png) no-repeat;
width: 30px;
height: 30px;
cursor: pointer;
margin-top: 180px;
margin-left: 216px;
}
 
.zoom {
background: url(./img/loupe.png);
width: 30px;
height: 30px;
cursor: pointer;
margin-top: 3px;
position: absolute;
margin-left: 217px;
}
 
.espece {
font-size: 12px;
font-weight: bold;
color: white;
padding-left: 5px;
padding-right: 1px;
}
 
.espece p,.auteur p {
padding: 0px;
margin: 0px;
overflow: hidden;
text-overflow: ellipsis;
white-space: pre;
min-height: 13px;
}
 
.zoneDetail {
position: absolute;
}
 
.zonePlus {
position: absolute;
width: 246px;
padding: 2px;
margin-top: -88px;
opacity: 0.9;
color: white;
text-align: left;
overflow: hidden;
text-overflow: ellipsis;
background:#333;
}
 
.zoneImage {
cursor: pointer;
height: 280px;
margin-bottom: 20px;
background: #DDD;
}
 
.zoneVoter {
margin-top: -48px;
text-align: center;
opacity: 0.9;
width: 240px;
position: absolute;
height: 35px;
padding: 5px;
}
 
.metadonnees, .motsCles {
text-align: left;
}
 
.auteur {
padding-left: 5px;
padding-right: 1px;
padding-top: 3px;
}
 
.boutonFermer {
background: url("./img/close.png") no-repeat scroll 5px 0 transparent;
border: medium none;
height: 30px;
margin-left: 104px;
margin-top: -20px;
position: absolute;
width: 40px;
cursor:pointer;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/resultats/images/ImageVue.ui.xml
New file
0,0 → 1,31
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui' ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator" ui:generateLocales="default">
 
<ui:with field='res' type='org.tela_botanica.del.client.resources.Ressources'/>
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary"/>
<ui:style src="image.css" />
 
<g:HTMLPanel styleName="{style.observations}">
<g:HTMLPanel styleName="{style.zoneDetail}">
<g:Label ui:field="enSavoirPlus" text=" " styleName="{style.enSavoirPlus}"/>
<g:Label ui:field="voirMotsCles" text=" " styleName="{style.voirMotsCles}"/>
<g:HTMLPanel styleName="{style.zoneCache}" ui:field="zoneCache">
<g:HTMLPanel ui:field="metadonnees" styleName="{style.metadonnees}"/>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.zoneMotsCles}" ui:field="zoneMotsCles">
<g:Button ui:field="boutonFermer" styleName="{style.boutonFermer}"/>
<g:HTMLPanel ui:field="motsCles" styleName="{style.motsCles}"/>
</g:HTMLPanel>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.zoneImage}"><g:Image ui:field="imagePrincipale" resource='{res.logo}'/></g:HTMLPanel>
<g:HTMLPanel styleName="{style.zonePlus}" ui:field="zonePlus">
<g:HTML ui:field="nomAuteur" styleName="petit {style.auteur} lien">Auteur</g:HTML>
<g:HTML ui:field="nomEspece" styleName="{style.espece}"></g:HTML>
</g:HTMLPanel>
<g:HTMLPanel styleName="{style.zoneVoter} arrondi-faible" ui:field="zoneVoter"><g:HorizontalPanel ui:field="voter"/></g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/resultats/images/ImagePresenteur.java
New file
0,0 → 1,258
package org.tela_botanica.del.client.vues.pictoflora.resultats.images;
 
import java.util.HashMap;
import java.util.List;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlayDefilanteVue;
import org.tela_botanica.del.client.composants.fenetreoverlay.FenetreOverlaySimplePresenteur;
import org.tela_botanica.del.client.composants.formulaires.formulairecommentaire.FormulaireCommentairePresenteur;
import org.tela_botanica.del.client.composants.formulaires.formulairecommentaire.FormulaireCommentaireVue;
import org.tela_botanica.del.client.composants.images.DetailImagePresenteur;
import org.tela_botanica.del.client.composants.images.DetailImageVue;
import org.tela_botanica.del.client.composants.metadonnees.MetadonneesPresenteur;
import org.tela_botanica.del.client.composants.metadonnees.MetadonneesVue;
import org.tela_botanica.del.client.composants.motsclesimages.MotsClesImagePresenteur;
import org.tela_botanica.del.client.composants.motsclesimages.MotsClesImageVue;
import org.tela_botanica.del.client.composants.motsclesimages.formulairesaisiemotclesimages.FormulaireSaisieMotsClesImagePresenteur;
import org.tela_botanica.del.client.composants.motsclesimages.formulairesaisiemotclesimages.FormulaireSaisieMotsClesImageVue;
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.composants.votefleur.VoteFleurPresenteur;
import org.tela_botanica.del.client.composants.votefleur.VoteFleurVue;
import org.tela_botanica.del.client.composants.votes.moyennevotes.MoyenneVotePresenteur;
import org.tela_botanica.del.client.composants.votes.moyennevotes.MoyenneVoteVue;
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.modeles.Image;
import org.tela_botanica.del.client.modeles.ModeRecherche;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.modeles.Protocole;
import org.tela_botanica.del.client.modeles.VoteProtocole;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.ajoutcommentaire.EvenementAjoutCommentaire;
import org.tela_botanica.del.client.navigation.evenement.ajoutcommentaire.GestionnaireEvenementAjoutCommentaire;
import org.tela_botanica.del.client.navigation.evenement.ajoutmotcleimage.EvenementAjoutMotCleImage;
import org.tela_botanica.del.client.navigation.evenement.ajoutmotcleimage.GestionnaireEvenementAjoutMotCleImage;
import org.tela_botanica.del.client.navigation.evenement.changementprotocole.EvenementChangementProtocole;
import org.tela_botanica.del.client.navigation.evenement.changementprotocole.GestionnaireEvenementChangementProtocole;
import org.tela_botanica.del.client.navigation.evenement.fermermotcleimage.EvenementFermerMotCleImage;
import org.tela_botanica.del.client.navigation.evenement.fermermotcleimage.GestionnaireEvenementFermerMotCleImage;
import org.tela_botanica.del.client.navigation.evenement.rechercheimage.EvenementVoirDetailsImage;
import org.tela_botanica.del.client.navigation.evenement.rechercheimage.GestionnaireEvenementVoirDetailsImage;
import org.tela_botanica.del.client.navigation.evenement.validationobservation.EvenementValidation;
import org.tela_botanica.del.client.navigation.evenement.validationobservationpictoflora.EvenementValidationPictoflora;
import org.tela_botanica.del.client.services.rest.CommentaireServiceConcret;
import org.tela_botanica.del.client.services.rest.MotsClesService;
import org.tela_botanica.del.client.services.rest.MotsClesServiceConcret;
import org.tela_botanica.del.client.services.rest.VoteProtocoleServiceConcret;
import org.tela_botanica.del.client.services.rest.async.ListeMotsClesImageCallBack;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
 
public class ImagePresenteur extends Presenteur {
 
public interface Vue extends IsWidget {
public abstract void loadImage(Image image);
 
public abstract HasClickHandlers getImagePrincipale();
 
public IsWidget getImagePrincipaleWidget();
 
public void setUrlImagePrincipale(String url);
 
public void setTitreImagePrincipale(String titre);
 
public void setAltTextImagePrincipale(String altText);
 
public String getUrlImagePrincipale();
 
public String getTitreImagePrincipale();
 
public String getAltTextImagePrincipale();
 
public abstract HasClickHandlers getEnSavoirPlus();
 
public abstract void cacherZoneCache();
 
public abstract void afficherZoneCache();
 
public abstract HasWidgets getZoneVoter();
 
public HasClickHandlers getNomAuteur();
 
public HasClickHandlers getNomEspece();
 
public HasWidgets getMetadonnees();
 
public HasClickHandlers getVoirMotsCles();
public HasWidgets getZoneMotsCles();
 
public void cacherZoneMotsCles();
 
public void afficherZoneMotsCles();
public HasClickHandlers getBoutonFermer();
}
 
private Vue vue;
 
private final Image image;
private boolean detailsOuverts = false;
 
private Protocole protocole;
 
private boolean motsClesOuverts = false;
private MotsClesImagePresenteur motsClesImagePresenteur;
 
final FenetreOverlaySimplePresenteur fenetreOverlaySimplePresenteur = new FenetreOverlaySimplePresenteur(new FenetreOverlayDefilanteVue());
public ImagePresenteur(Image image, Protocole protocole, Vue vue) {
this.image = image;
this.protocole = protocole;
this.vue = vue;
}
 
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
vue.loadImage(image);
vue.getNomAuteur().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Window.open(new Config().getUrl("urlProfil") + image.getObservation().getIdAuteur(), "Profil utilisateur", null);
}
});
new MetadonneesPresenteur(new MetadonneesVue(), image.getObservation(), ModeRecherche.MODE_IMAGE, true).go(vue.getMetadonnees());
chargerDonneesValidation();
gererEvenements();
}
 
private void chargerDonneesValidation() {
vue.getZoneVoter().clear();
if (protocole != null) {
HashMap<String, VoteProtocole> observationValidationDatas = image.getVotesProtocoles(protocole.getId());
if (observationValidationDatas != null) {
new MoyenneVotePresenteur(image, protocole, new MoyenneVoteVue(), new VoteProtocoleServiceConcret()).go(vue.getZoneVoter());
}
}
}
 
private void lancerEvenementValidation() {
CacheClient.getInstance().setImageCourante(image);
final Observation obs = image.getObservation();
BusEvenementiel.getInstance().fireEvent(new EvenementValidationPictoflora(obs));
}
 
protected void gererEvenements() {
ClickHandler zoomeur = new ClickHandler() {
public void onClick(ClickEvent event) {
FenetreOverlaySimplePresenteur presenteurGalerie = new FenetreOverlaySimplePresenteur(new FenetreOverlayDefilanteVue());
presenteurGalerie.ouvrirFenetreModaleDefilante(0, new DetailImagePresenteur(image, new DetailImageVue()));
presenteurGalerie.afficherBoutonsSuivantsPrecedents(false);
}};
vue.getImagePrincipale().addClickHandler(zoomeur);
 
vue.getEnSavoirPlus().addClickHandler(new ClickHandler() {
 
@Override
public void onClick(ClickEvent event) {
BusEvenementiel.getInstance().fireEvent(new EvenementVoirDetailsImage(image));
}
});
vue.getVoirMotsCles().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
CacheClient.getInstance().setImageCourante(image);
motsClesImagePresenteur = new MotsClesImagePresenteur(image, new MotsClesServiceConcret(), new FormulaireSaisieMotsClesImagePresenteur(image.getIdImage(),
new MotsClesServiceConcret(), new FormulaireSaisieMotsClesImageVue()), new MotsClesImageVue());
motsClesImagePresenteur.chargerMotsCles();
fenetreOverlaySimplePresenteur.ouvrirFenetreModale(motsClesImagePresenteur);
}
});
vue.getBoutonFermer().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
cacherPanneauMotsCles();
}
});
BusEvenementiel.getInstance().addHandler(EvenementVoirDetailsImage.TYPE, new GestionnaireEvenementVoirDetailsImage() {
@Override
public void onVoirDetailsImage(EvenementVoirDetailsImage event) {
if (image.getIdImage().equals(event.getImage().getIdImage())) {
if (!detailsOuverts) {
afficherDetails();
} else {
cacherDetails();
}
} else {
cacherDetails();
}
}
});
 
BusEvenementiel.getInstance().addHandler(EvenementChangementProtocole.TYPE, new GestionnaireEvenementChangementProtocole() {
@Override
public void onChangementProtocole(EvenementChangementProtocole event) {
setProtocole(event.getProtocole());
chargerDonneesValidation();
}
});
BusEvenementiel.getInstance().addHandler(EvenementFermerMotCleImage.TYPE, new GestionnaireEvenementFermerMotCleImage() {
@Override
public void onFermerMotCleImage(
EvenementFermerMotCleImage evenementFermerMotCleImage) {
if (evenementFermerMotCleImage.getIdImage().equals(image.getIdImage())) {
fenetreOverlaySimplePresenteur.fermerFenetreModale();
}
}
});
}
 
protected void afficherPanneauMotsCles() {
vue.afficherZoneMotsCles();
motsClesOuverts = true;
motsClesImagePresenteur.chargerMotsCles();
motsClesImagePresenteur.focuserChampsSaisie();
}
protected void cacherPanneauMotsCles() {
vue.cacherZoneMotsCles();
motsClesOuverts = false;
}
 
public void cacherDetails() {
vue.cacherZoneCache();
detailsOuverts = false;
}
 
public void afficherDetails() {
vue.afficherZoneCache();
detailsOuverts = true;
}
 
public boolean isDetailsOpen() {
return detailsOuverts;
}
 
public Protocole getProtocole() {
return protocole;
}
 
public void setProtocole(Protocole protocole) {
this.protocole = protocole;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/resultats/images/ImageVue.java
New file
0,0 → 1,169
package org.tela_botanica.del.client.vues.pictoflora.resultats.images;
 
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.i18n.I18n;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class ImageVue extends Composite implements ImagePresenteur.Vue {
 
// Annotation can be used to change the name of the associated xml file
// @UiTemplate("ObservationVue.ui.xml")
interface MyUiBinder extends UiBinder<Widget, ImageVue> {
}
 
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
@UiField
protected HTML nomEspece, nomAuteur;
@UiField
protected HTMLPanel zoneVoter, zonePlus;
 
@UiField
protected HorizontalPanel voter;
 
@UiField
protected Panel zoneCache, zoneMotsCles;
 
@UiField
Image imagePrincipale;
 
@UiField
Label enSavoirPlus, voirMotsCles;
@UiField
Button boutonFermer;
@UiField Panel metadonnees;
 
public ImageVue() {
// sets listBox
initWidget(uiBinder.createAndBindUi(this));
}
 
public HasWidgets getZoneVoter() {
return voter;
}
 
public void cacherZoneCache() {
zoneCache.setVisible(false);
}
 
public void afficherZoneCache() {
zoneCache.setVisible(true);
}
 
public void loadImage(org.tela_botanica.del.client.modeles.Image image) {
zoneCache.setVisible(false);
zoneMotsCles.setVisible(false);
nomEspece.setHTML("<p>"+image.getObservation().getNomRetenu()+"</p>");
 
nomAuteur.setHTML("<p>"+image.getObservation().getAuteur()+"</p>");
 
imagePrincipale.setUrl(image.getUrl());
imagePrincipale.setTitle(I18n.getVocabulary().indicationActionClicImage());
imagePrincipale.setAltText(image.getObservation().getAuteur() + " - " + image.getObservation().getNomRetenu());
voirMotsCles.setTitle(I18n.getVocabulary().voirMotsCles());
enSavoirPlus.setTitle(I18n.getVocabulary().voirMetadonnees());
}
 
@Override
public HasClickHandlers getImagePrincipale() {
return imagePrincipale;
}
 
@Override
public IsWidget getImagePrincipaleWidget() {
return imagePrincipale;
}
@Override
public HasClickHandlers getEnSavoirPlus() {
return enSavoirPlus;
}
@Override
public HasClickHandlers getVoirMotsCles() {
return voirMotsCles;
}
 
@Override
public void setUrlImagePrincipale(String url) {
imagePrincipale.setUrl(url);
}
 
@Override
public void setTitreImagePrincipale(String titre) {
imagePrincipale.setTitle(titre);
}
 
@Override
public void setAltTextImagePrincipale(String altText) {
imagePrincipale.setAltText(altText);
}
 
@Override
public String getUrlImagePrincipale() {
return imagePrincipale.getUrl();
}
 
@Override
public String getTitreImagePrincipale() {
return imagePrincipale.getTitle();
}
 
@Override
public String getAltTextImagePrincipale() {
return imagePrincipale.getAltText();
}
 
@Override
public HasClickHandlers getNomAuteur() {
return nomAuteur;
}
@Override
public HasClickHandlers getNomEspece() {
return nomEspece;
}
public HasWidgets getMetadonnees() {
return metadonnees;
}
 
@Override
public void cacherZoneMotsCles() {
zoneMotsCles.setVisible(false);
}
 
@Override
public void afficherZoneMotsCles() {
zoneMotsCles.setVisible(true);
}
 
@Override
public HasWidgets getZoneMotsCles() {
return zoneMotsCles;
}
 
@Override
public HasClickHandlers getBoutonFermer() {
return boutonFermer;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/resultats/ResultatPictofloraVue.java
New file
0,0 → 1,239
package org.tela_botanica.del.client.vues.pictoflora.resultats;
 
import java.util.ArrayList;
import java.util.List;
 
import org.tela_botanica.del.client.modeles.Protocole;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.OptionElement;
import com.google.gwt.dom.client.SelectElement;
import com.google.gwt.event.dom.client.HasChangeHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class ResultatPictofloraVue extends Composite implements ResultatPictofloraPresenteur.Vue {
 
@UiField
Panel panneauChargement;
private final List<HasWidgets> panneauxImages = new ArrayList<HasWidgets>();
private final int nbImagesPerPage = 10;
private int numImage = 0;
 
// Annotation can be used to change the name of the associated xml file
// @UiTemplate("ObservationRechercheVue.ui.xml")
interface MyUiBinder extends UiBinder<Widget, ResultatPictofloraVue> {
}
 
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
 
@UiField
Panel panneauPagination, panneauPaginationHaut, zoneTri;
 
@UiField
HTMLPanel imageTable;
 
@UiField
Button triParNbVotesAscendant, triParNbVotesDescendant, triParDateAscendant, triParDateDescendant, triParNbTagsAscendant, triParNbTagsDescendant;
 
@UiField
Label aucunResultat;
@UiField
Label labelVote, labelDate, labelTag;
// Constructeur
public ResultatPictofloraVue() {
initWidget(uiBinder.createAndBindUi(this));
}
 
/**
* Nettoie et remet à zéro les composants du panneau qui doivent l'être
* */
public void nettoyer() {
setNumImage(0);
imageTable.clear();
panneauxImages.clear();
}
 
public void creerPanneauxObservations(int taille) {
 
panneauxImages.clear();
for (int i = 0; i < taille; i++) {
Panel imagePanel = new HTMLPanel("");
panneauxImages.add(imagePanel);
}
}
 
public void afficherElementsAucunResultatTrouve() {
imageTable.clear();
aucunResultat.setVisible(true);
panneauPaginationHaut.setVisible(false);
panneauPagination.setVisible(false);
zoneTri.setVisible(false);
}
 
public void afficherElementsResultatsTrouve() {
aucunResultat.setVisible(false);
panneauPaginationHaut.setVisible(true);
panneauPagination.setVisible(true);
zoneTri.setVisible(true);
}
 
public void setNumImage(int numImage) {
this.numImage = numImage;
}
 
public void startChargement() {
panneauChargement.setHeight((this.getOffsetHeight() - (panneauPagination.getOffsetHeight() * 2)) + "px");
panneauChargement.setVisible(true);
}
 
public void stopChargement() {
panneauChargement.setVisible(false);
}
 
public HTMLPanel getImageTable() {
return imageTable;
}
 
public int getNumImage() {
return numImage;
}
 
public Panel getPanneauChargement() {
return panneauChargement;
}
 
public Panel getPanneauPagination() {
return panneauPagination;
}
 
public Panel getPanneauPaginationHaut() {
return panneauPaginationHaut;
}
 
public int getNbImagesPerPage() {
return nbImagesPerPage;
}
 
public List<HasWidgets> getPanneauxImages() {
return panneauxImages;
}
 
public Button getTriParNbVotesAscendant() {
return triParNbVotesAscendant;
}
 
public Button getTriParNbVotesDescendant() {
return triParNbVotesDescendant;
}
 
public Button getTriParDateAscendant() {
return triParDateAscendant;
}
 
public Button getTriParDateDescendant() {
return triParDateDescendant;
}
 
@Override
public Label getLabelVote() {
return labelVote;
}
 
@Override
public void masquerVoteAscendant() {
triParNbVotesAscendant.setVisible(false);
}
@Override
public void masquerVoteDescendant() {
triParNbVotesDescendant.setVisible(false);
}
@Override
public void afficherVoteAscendant() {
triParNbVotesAscendant.setVisible(true);
}
@Override
public void afficherVoteDescendant() {
triParNbVotesDescendant.setVisible(true);
}
@Override
public Label getLabelDate() {
return labelDate;
}
@Override
public Label getLabelTag() {
return labelTag;
}
@Override
public void masquerDateAscendant() {
triParDateAscendant.setVisible(false);
}
@Override
public void masquerDateDescendant() {
triParDateDescendant.setVisible(false);
}
@Override
public void afficherDateAscendant() {
triParDateAscendant.setVisible(true);
}
@Override
public void afficherDateDescendant() {
triParDateDescendant.setVisible(true);
}
 
@Override
public HasClickHandlers getTriParNbTagsAscendant() {
return triParNbTagsAscendant;
}
 
@Override
public HasClickHandlers getTriParNbTagsDescendant() {
return triParNbTagsDescendant;
}
 
@Override
public void afficherTagAscendant() {
triParNbTagsAscendant.setVisible(true);
}
 
@Override
public void masquerTagAscendant() {
triParNbTagsAscendant.setVisible(false);
}
 
@Override
public void afficherTagDescendant() {
triParNbTagsDescendant.setVisible(true);
}
 
@Override
public void masquerTagDescendant() {
triParNbTagsDescendant.setVisible(false);
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/pictoflora/resultats/ResultatPictoflora.css
New file
0,0 → 1,80
.contenuResultat {
text-align: center;
}
 
.barreNavigation {
max-width: 810px;
margin-top: -15px;
padding-bottom: 20px
}
 
.votes {
padding-left: 10px;
padding-top: 3px;
cursor: pointer;
}
 
.date {
padding-left: 10px;
padding-top: 3px;
cursor: pointer;
}
 
.tag {
padding-left: 10px;
padding-top: 3px;
cursor: pointer;
}
 
.zoneTri {
padding-left: 10px;
float: right;
}
 
.labeltri {
padding-top: 3px;
}
 
.protocoles {
padding-left: 10px;
}
 
.paginationHaut {
}
 
.images {
width: 100%;
clear: left;
margin-top: 10px;
margin-left:15px;
}
 
.images>div {
float: left;
margin: 0 20px 50px 0px
}
 
.boutonTriAsc,.boutonTriDesc {
border: none;
cursor: pointer;
}
 
.boutonTriAsc:hover,.boutonTriDesc:hover {
border:dotted 1px #8EB533;
border-width:0 0 1px 0;
}
 
.boutonTriAsc {
height: 19px;
background: url(./img/fleche-haut.png) no-repeat
}
 
.boutonTriDesc {
height: 19px;
background: url(./img/fleche-bas.png) no-repeat
}
 
.aucunResultat {
text-align: left;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/entete/EnteteVue.java
New file
0,0 → 1,56
package org.tela_botanica.del.client.vues.entete;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
import org.tela_botanica.del.client.vues.entete.EntetePresenteur;
 
public class EnteteVue extends Composite implements EntetePresenteur.Vue {
 
// Gestion d'UiBinder
interface Binder extends UiBinder<Widget, EnteteVue> {
}
 
private static Binder binder = GWT.create(Binder.class);
@UiField
Panel zoneTitre, zoneIdentification, zoneLiens, zoneChapeau;
public EnteteVue(String titre) {
initWidget(binder.createAndBindUi(this));
zoneTitre.clear();
HTML html = new HTML("<h1>" + titre + "</h1>");
zoneTitre.add(html);
}
 
@Override
public HasWidgets getZoneIdentification() {
return zoneIdentification;
}
 
@Override
public HasWidgets getZoneLiens() {
return zoneLiens;
}
 
@Override
public HasWidgets getZoneChapeau() {
return zoneChapeau;
}
}
 
 
 
 
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/entete/liens/LiensPresenteur.java
New file
0,0 → 1,76
package org.tela_botanica.del.client.vues.entete.liens;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.partageurl.PartageUrlPresenteur;
import org.tela_botanica.del.client.composants.partageurl.PartageUrlVue;
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.modeles.ProtocoleServiceResultat;
import org.tela_botanica.del.client.services.rest.ProtocoleServiceConcret;
import org.tela_botanica.del.client.services.rest.async.ProtocolesCallback;
 
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class LiensPresenteur extends Presenteur {
 
public interface Vue extends IsWidget {
public HasWidgets getZonePartageUrl();
}
private Vue vue;
public LiensPresenteur(Vue vue) {
this.vue = vue;
}
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
 
PartageUrlPresenteur partageUrl = new PartageUrlPresenteur(new PartageUrlVue());
partageUrl.go(vue.getZonePartageUrl());
gererProtocoles();
}
protected void gererProtocoles() {
//FIXME : ne doit pas etre concret ici ?
ProtocoleServiceConcret protocoleService = new ProtocoleServiceConcret();
if (CacheClient.getInstance().getProtocoleCourant() == null) {
if (CacheClient.getInstance().getListeProtocoles() == null || CacheClient.getInstance().getListeProtocoles().size() == 0) {
protocoleService.getProtocoles(new ProtocolesCallback() {
 
@Override
public void surRetour(ProtocoleServiceResultat protocolesRecus) {
CacheClient.getInstance().setListeProtocoles(protocolesRecus.getProtocoles());
if (protocolesRecus.getProtocoles().size() > 0) {
CacheClient.getInstance().setProtocoleCourant(protocolesRecus.getProtocoles().get(0));
} else {
// TODO afficher message indiquant que la liste des
// protocoles de votes n'est pas fourni
}
}
});
} else {
CacheClient.getInstance().setProtocoleCourant(CacheClient.getInstance().getListeProtocoles().get(0));
}
}
}
 
@Override
protected void gererEvenements() {
// TODO Auto-generated method stub
/*
* vue.getLienAjoutObservation().addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Config config = new Config();
Window.open(config.getUrl("applisaisie"), "Saisie d'une nouvelle observation", null);
}
});
*/
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/entete/liens/LiensVue.java
New file
0,0 → 1,82
package org.tela_botanica.del.client.vues.entete.liens;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.gestionhistorique.ConstantesNavigation;
import org.tela_botanica.del.client.i18n.I18n;
import org.tela_botanica.del.client.navigation.evenement.BusEvenementiel;
import org.tela_botanica.del.client.navigation.evenement.changementprotocole.EvenementChangementProtocole;
import org.tela_botanica.del.client.navigation.evenement.changementprotocole.GestionnaireEvenementChangementProtocole;
import org.tela_botanica.del.client.utils.UtilitairesServiceResultat;
 
import com.gargoylesoftware.htmlunit.Cache;
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
import com.google.web.bindery.autobean.vm.Configuration;
 
public class LiensVue extends Composite implements LiensPresenteur.Vue {
// Gestion d'UiBinder
interface Binder extends UiBinder<Widget, LiensVue> {}
 
private static Binder binder = GWT.create(Binder.class);
@UiField Panel zonePartageUrl;
@UiField Anchor ajouterObservation, aidePictoflora, aide, participerProjet;
public LiensVue() {
initWidget(binder.createAndBindUi(this));
gererAffichageEnFonctionDeLaNavigation();
gererEvenements();
}
public HasWidgets getZonePartageUrl() {
return zonePartageUrl;
}
public void gererAffichageEnFonctionDeLaNavigation() {
CacheClient cache = CacheClient.getInstance();
String pageCourante = cache.getPageCourante();
if (pageCourante.startsWith(ConstantesNavigation.PICTOFLORA) || pageCourante.startsWith(ConstantesNavigation.PAGE_RECHERCHE_IMAGES)
|| pageCourante.startsWith(ConstantesNavigation.PAGE_VALIDATION_PICTOFLORA)) {
//SI PICTO
ajouterObservation.setVisible(false);
aide.setVisible(false);
setLienSaisieProjet();
} else {
aidePictoflora.setVisible(false);
participerProjet.setVisible(false);
}
}
private void setLienSaisieProjet() {
participerProjet.setHref(formaterLienSaisieProjetUrl());
participerProjet.setTitle(I18n.getVocabulary().legendeAjouterImage());
}
private String formaterLienSaisieProjetUrl() {
String urlSaisieProjet = I18n.getVocabulary().lienAppliSaisie();
if(CacheClient.getInstance().getProtocoleCourant() != null) {
String tagProtocole = CacheClient.getInstance().getProtocoleCourant().getTag();
urlSaisieProjet = I18n.getVocabulary().lienAppliSaisieProjetUrl();
urlSaisieProjet = urlSaisieProjet.replace("{projet}", tagProtocole);
}
return urlSaisieProjet;
}
private void gererEvenements() {
BusEvenementiel.getInstance().addHandler(EvenementChangementProtocole.TYPE, new GestionnaireEvenementChangementProtocole() {
@Override
public void onChangementProtocole(EvenementChangementProtocole event) {
setLienSaisieProjet();
}
});
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/entete/liens/liens.css
New file
0,0 → 1,14
.zonePartageUrl {
display:inline-block;
width:150px;
float:right;
}
 
.aide {
float:right;
margin-left:5px;
}
 
.boutonParticiper {
margin-right:5px;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/entete/liens/LiensVue.ui.xml
New file
0,0 → 1,25
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'
ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateLocales="default">
<ui:with field='res'
type='org.tela_botanica.del.client.resources.Ressources' />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
<ui:style src="liens.css" />
<g:HTMLPanel>
<!-- Liens identiplante -->
<g:HTMLPanel styleName="limiteMax">
<!-- picto -->
<g:Anchor target="_blank" href="{constants.lienAidePictoflora}" ui:field="aidePictoflora" text="{constants.accesAide}" title="{constants.accesAide}" styleName="acceder-aide {style.aide}"/>
<!-- identiplante -->
<g:Anchor ui:field="ajouterObservation" text="{constants.ajouterObservation}" title="{constants.legendeAjouterObservation}" styleName="acceder-outil" href="{constants.lienAppliSaisie}" target="_blank"/>
<g:Anchor target="_blank" href="{constants.lienAideIdentiplante}" ui:field="aide" text="{constants.accesAide}" title="{constants.accesAide}" styleName="acceder-aide {style.aide}"/>
<!-- Commun -->
<g:HTMLPanel ui:field="zonePartageUrl" styleName="{style.zonePartageUrl}"></g:HTMLPanel>
<g:Anchor ui:field="participerProjet" text="Participer au projet" title="{constants.legendeAjouterObservation}" styleName="acceder-outil droite {style.boutonParticiper}" target="_blank"/>
</g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/entete/entete.css
New file
0,0 → 1,36
.zoneTitre {
float: left;
height: 50px;
width: 50%;
margin:10px 0;
font-size:20px
}
 
.zoneLogos {
float: right;
height: 50px;
width: 50%;
text-align:center;
margin:10px 0;
}
 
.zoneIdentification {
float: right;
height: 129px;
width: 45%;
background: url("./img/carre_orange.png") no-repeat scroll -0px -8px transparent;
text-align:right;
padding-left:27px;
}
 
.zoneChapeau {
float: left;
height: 130px;
width: 52%;
}
 
.zoneLiens {
clear: both;
height: 40px;
padding:10px 65px;
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/entete/chapeaux/chapeau.css
--- v1.1-helium/src/org/tela_botanica/del/client/vues/entete/chapeaux/ChapeauVue.ui.xml (revision 0)
+++ v1.1-helium/src/org/tela_botanica/del/client/vues/entete/chapeaux/ChapeauVue.ui.xml (revision 1535)
@@ -0,0 +1,18 @@
+<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'
+ ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
+ ui:generateLocales="default">
+ <ui:with field='res'
+ type='org.tela_botanica.del.client.resources.Ressources' />
+ <ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
+
+ <ui:style src="chapeau.css" />
+
+ <g:HTMLPanel>
+ <g:HTMLPanel ui:field="chapeauIdentiplante"><ui:msg key="chapeauObservation">Cet espace vous permet d'échanger sur la détermination d'espèces.
+ Vous ne parvenez pas à déterminer une plante ? Soumettez-la aux membres du réseau.
+ Vous avez relevé des erreurs dans les images soumises par le réseau ? Postez un commentaire ou proposez une nouvelle détermination.</ui:msg></g:HTMLPanel>
+ <g:HTMLPanel ui:field="chapeauPictoflora"><ui:msg key="chapeauImages">Cette galerie vous permet de rechercher les illustrations des membres du réseau issues du
+ Carnet en ligne... et de voter pour la qualité des images selon un protocole défini?
+ Postez un commentaire ou proposez une nouvelle détermination.</ui:msg></g:HTMLPanel>
+ </g:HTMLPanel>
+</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/entete/chapeaux/ChapeauPresenteur.java
New file
0,0 → 1,30
package org.tela_botanica.del.client.vues.entete.chapeaux;
 
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
 
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
 
public class ChapeauPresenteur extends Presenteur {
public interface Vue extends IsWidget {
}
private Vue vue;
public ChapeauPresenteur(Vue vue) {
this.vue = vue;
}
 
@Override
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
}
 
@Override
protected void gererEvenements() {
// TODO Auto-generated method stub
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/entete/chapeaux/ChapeauVue.java
New file
0,0 → 1,41
package org.tela_botanica.del.client.vues.entete.chapeaux;
 
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.gestionhistorique.ConstantesNavigation;
 
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
 
public class ChapeauVue extends Composite implements ChapeauPresenteur.Vue {
 
// Gestion d'UiBinder
interface Binder extends UiBinder<Widget, ChapeauVue> {
}
private static Binder binder = GWT.create(Binder.class);
@UiField
Panel chapeauIdentiplante, chapeauPictoflora;
public ChapeauVue() {
initWidget(binder.createAndBindUi(this));
gererAffichageEnFonctionDeLaNavigation();
}
public void gererAffichageEnFonctionDeLaNavigation() {
CacheClient cache = CacheClient.getInstance();
String pageCourante = cache.getPageCourante();
if (pageCourante.startsWith(ConstantesNavigation.PICTOFLORA) || pageCourante.startsWith(ConstantesNavigation.PAGE_RECHERCHE_IMAGES)
|| pageCourante.startsWith(ConstantesNavigation.PAGE_VALIDATION_PICTOFLORA)) {
chapeauIdentiplante.setVisible(false);
chapeauPictoflora.setVisible(true);
} else {
chapeauIdentiplante.setVisible(true);
chapeauPictoflora.setVisible(false);
}
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/entete/chapeaux/ChapeauVueBinderImplGenMessages.properties
New file
0,0 → 1,10
# Generated from org.tela_botanica.del.client.vues.rechercheobservations.moteur.MoteurRechercheObservationsVueBinderImplGenMessages
# for locale fr
 
chapeauObservation=<ul class="traitTela">\
<li>Cet espace vous permet d''échanger sur la détermination d''espèces.</li> \
<li>Vous ne parvenez pas à déterminer une plante ? <br />Soumettez-la aux membres du réseau.</li> \
<li>Vous avez relevé des erreurs dans les images soumises par le réseau ? <br />Postez un commentaire ou proposez une nouvelle détermination.</li> \
</ul>
 
chapeauImages=<ul class="traitTela"><li>Cette galerie vous permet de rechercher les illustrations des membres du réseau issues du Carnet en ligne... et de voter pour la qualité des images selon un protocole défini.</li></ul>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/entete/EnteteVue.ui.xml
New file
0,0 → 1,20
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'
ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateLocales="default">
<ui:with field='res'
type='org.tela_botanica.del.client.resources.Ressources' />
<ui:with field="constants" type="org.tela_botanica.del.client.i18n.Vocabulary" />
<ui:style src="entete.css" />
<g:HTMLPanel styleName="limiteMax">
<g:HTMLPanel ui:field="zoneTitre" styleName="{style.zoneTitre}"></g:HTMLPanel>
<g:HTMLPanel ui:field="zoneLogos" styleName="{style.zoneLogos}">
<a class="logo_tela" href="http://www.tela-botanica.org" target="_blank"></a>
<a class="logo_pn" href="http://www.plantnet-project.org/papyrus.php?langue=fr" target="_blank"></a>
</g:HTMLPanel>
<g:HTMLPanel ui:field="zoneChapeau" styleName="{style.zoneChapeau}"></g:HTMLPanel>
<g:HTMLPanel ui:field="zoneIdentification" styleName="{style.zoneIdentification}"></g:HTMLPanel>
<g:HTMLPanel ui:field="zoneLiens" styleName="{style.zoneLiens}"></g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>
/tags/v1.1-helium/src/org/tela_botanica/del/client/vues/entete/EntetePresenteur.java
New file
0,0 → 1,63
package org.tela_botanica.del.client.vues.entete;
 
import org.tela_botanica.del.client.composants.formulaires.identification.FormulaireIdentificationPresenteur;
import org.tela_botanica.del.client.composants.formulaires.identification.FormulaireIdentificationVue;
import org.tela_botanica.del.client.composants.partageurl.PartageUrlPresenteur;
import org.tela_botanica.del.client.composants.partageurl.PartageUrlVue;
import org.tela_botanica.del.client.composants.presenteur.Presenteur;
import org.tela_botanica.del.client.services.rest.UtilisateurServiceConcret;
import org.tela_botanica.del.client.vues.entete.chapeaux.ChapeauPresenteur;
import org.tela_botanica.del.client.vues.entete.chapeaux.ChapeauVue;
import org.tela_botanica.del.client.vues.entete.liens.LiensPresenteur;
import org.tela_botanica.del.client.vues.entete.liens.LiensVue;
 
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
 
/**
* Classe pour le header de l'application affichant le formulaire de connexion, le titre, les logos
* */
public class EntetePresenteur extends Presenteur {
 
/**
* La vue du header
* */
public interface Vue extends IsWidget {
public HasWidgets getZoneIdentification();
public HasWidgets getZoneLiens();
public HasWidgets getZoneChapeau();
}
private Vue vue;
 
public EntetePresenteur(Vue vue) {
this.vue = vue;
}
 
@Override
public void go(HasWidgets composite) {
composite.add(vue.asWidget());
//Ajout de la zone identification
FormulaireIdentificationPresenteur identification = new FormulaireIdentificationPresenteur(new FormulaireIdentificationVue(), new UtilisateurServiceConcret());
identification.go(vue.getZoneIdentification());
ChapeauPresenteur chapeau = new ChapeauPresenteur(new ChapeauVue());
chapeau.go(vue.getZoneChapeau());
LiensPresenteur liens = new LiensPresenteur(new LiensVue());
liens.go(vue.getZoneLiens());
}
 
@Override
protected void gererEvenements() {
// TODO Auto-generated method stub
}
public void ajouterLien(Widget lien) {
this.vue.getZoneLiens().add(lien);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/test/vues/identiplante/ResultatIdentiplanteTest.java
New file
0,0 → 1,35
package org.tela_botanica.del.test.vues.identiplante;
 
import static org.mockito.Mockito.mock;
 
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import org.mockito.Mockito;
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.services.rest.ImageService;
import org.tela_botanica.del.client.services.rest.ObservationService;
import org.tela_botanica.del.client.vues.identiplante.resultats.ResultatsIdentiplantePresenteur;
 
public class ResultatIdentiplanteTest {
 
private ResultatsIdentiplantePresenteur resultatPresenteur;
private ResultatsIdentiplantePresenteur.Vue vueResultat;
private ImageService serviceImage;
 
@Before
public void setUp() throws Exception {
 
vueResultat = mock( ResultatsIdentiplantePresenteur.Vue.class, Mockito.RETURNS_MOCKS);
serviceImage = mock(ImageService.class);
ObservationService obsService = Mockito.mock(ObservationService.class);
resultatPresenteur = new ResultatsIdentiplantePresenteur(obsService, vueResultat);
}
 
@Test
public void testAfficherImages() {
resultatPresenteur.chercherEtAfficherObservationsPageEnCours();
assertEquals(CacheClient.getInstance().getPageCouranteRechercheImage(), 1);
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/test/vues/identiplante/MoteurIdentiplantePresenteurTest.java
New file
0,0 → 1,31
package org.tela_botanica.del.test.vues.identiplante;
 
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.tela_botanica.del.client.services.rest.ObservationService;
import org.tela_botanica.del.client.vues.identiplante.moteur.MoteurIdentiplantePresenteur;
 
import com.google.gwt.user.client.ui.HasWidgets;
 
public class MoteurIdentiplantePresenteurTest {
 
MoteurIdentiplantePresenteur moteurRecherchePresenteur;
MoteurIdentiplantePresenteur.Vue moteurRechercheVue;
HasWidgets container;
 
@Before
public void setUp() {
moteurRechercheVue = Mockito.mock(MoteurIdentiplantePresenteur.Vue.class, Mockito.RETURNS_MOCKS);
ObservationService obsService = Mockito.mock(ObservationService.class);
moteurRecherchePresenteur = new MoteurIdentiplantePresenteur(obsService, moteurRechercheVue);
 
container = Mockito.mock(HasWidgets.class);
}
 
@Test
public void testerMoteurRechercheImage() {
// TODO faire un test GWTTestCase
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/test/services/CalculVoteDeterminationServiceTest.java
New file
0,0 → 1,108
package org.tela_botanica.del.test.services;
 
import static org.junit.Assert.assertTrue;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
 
import org.junit.Test;
import org.tela_botanica.del.client.modeles.Contributeur;
import org.tela_botanica.del.client.modeles.MoyenneVote;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.modeles.VoteDetermination;
import org.tela_botanica.del.client.services.CalculVoteDeterminationService;
 
public class CalculVoteDeterminationServiceTest {
 
@Test
public void testCalculerVoteDetermination() {
 
Observation obs = new Observation();
VoteDetermination voteDetermination = new VoteDetermination();
voteDetermination.setVote(1);
voteDetermination.setDate(new Date());
voteDetermination.setContributeur("benjamin");
 
PropositionDetermination propositionDetermination = new PropositionDetermination(obs);
propositionDetermination.setEspece("Iris lutescens subsp. lutescens");
propositionDetermination.setContributeur(new Contributeur("1", "contrib", "test", "contrib@test.com"));
propositionDetermination.setId("1");
propositionDetermination.ajouterVoteDetermination(voteDetermination);
obs.ajouterPropositionDetermination(propositionDetermination);
 
MoyenneVote moyenneVote = CalculVoteDeterminationService
.calculerVoteDetermination(propositionDetermination);
 
assertTrue(moyenneVote.getScore() == 100);
 
}
@Test
public void testCalculerVoteDeterminationPlusPopulaire() {
Observation obs = new Observation();
 
Contributeur cIdent1 = new Contributeur("1", "Peronnet", "Aurélien", "aurelien@tela-botanica.org");
Contributeur cIdent2 = new Contributeur("2", "Liens", "Benjamin", "benjamin@tela-botanica.org");
Contributeur cAnon1 = new Contributeur("a1a5f7b8s8c4v2b3g4g5t7t8t94", "", "", "");
VoteDetermination voteDetermination1 = new VoteDetermination();
voteDetermination1.setVote(1);
voteDetermination1.setDate(new Date());
voteDetermination1.setContributeur(cIdent1.getId());
voteDetermination1.setAuteur(cIdent1);
VoteDetermination voteDetermination2 = new VoteDetermination();
voteDetermination2.setVote(1);
voteDetermination2.setDate(new Date());
voteDetermination2.setContributeur(cIdent2.getId());
voteDetermination2.setAuteur(cIdent2);
VoteDetermination voteDetermination3 = new VoteDetermination();
voteDetermination3.setVote(0);
voteDetermination3.setDate(new Date());
voteDetermination3.setContributeur(cAnon1.getId());
voteDetermination3.setAuteur(cAnon1);
 
PropositionDetermination propositionDetermination = new PropositionDetermination(obs);
propositionDetermination.setEspece("Iris lutescens subsp. lutescens");
propositionDetermination.setContributeur(new Contributeur("1", "contrib", "test", "contrib@test.com"));
propositionDetermination.setId("1");
propositionDetermination.ajouterVoteDetermination(voteDetermination2);
propositionDetermination.ajouterVoteDetermination(voteDetermination3);
obs.ajouterPropositionDetermination(propositionDetermination);
PropositionDetermination propositionDetermination2 = new PropositionDetermination(obs);
propositionDetermination2.setEspece("Iris urticans");
propositionDetermination2.setContributeur(new Contributeur("1", "contrib", "test", "contrib@test.com"));
propositionDetermination2.setId("2");
propositionDetermination2.ajouterVoteDetermination(voteDetermination1);
propositionDetermination2.ajouterVoteDetermination(voteDetermination2);
propositionDetermination2.ajouterVoteDetermination(voteDetermination3);
obs.ajouterPropositionDetermination(propositionDetermination2);
List<PropositionDetermination> listePropositions = new ArrayList<PropositionDetermination>();
listePropositions.add(propositionDetermination2);
listePropositions.add(propositionDetermination);
 
List<MoyenneVote> listeMoyenneVote = CalculVoteDeterminationService
.calculerVoteDeterminationPlusPopulaire(listePropositions);
for (Iterator iterator = listeMoyenneVote.iterator(); iterator
.hasNext();) {
MoyenneVote moyenneVote = (MoyenneVote) iterator.next();
System.out.println(moyenneVote.getScore());
}
 
// le premier vote est sensé être celui qui possède le plus gros score
assertTrue(listeMoyenneVote.get(0).getIntituleAssocie().equals("Iris urticans"));
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/test/MockDatasource.java
New file
0,0 → 1,423
package org.tela_botanica.del.test;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
 
import org.tela_botanica.del.client.modeles.Commentaire;
import org.tela_botanica.del.client.modeles.Contributeur;
import org.tela_botanica.del.client.modeles.Image;
import org.tela_botanica.del.client.modeles.InformationsRecherche;
import org.tela_botanica.del.client.modeles.InterventionForum;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.modeles.Protocole;
import org.tela_botanica.del.client.modeles.VoteDetermination;
import org.tela_botanica.del.client.modeles.VoteProtocole;
import org.tela_botanica.del.client.services.rest.ImageService;
import org.tela_botanica.del.client.services.rest.ObservationService;
import org.tela_botanica.del.client.services.rest.PropositionDeterminationService;
import org.tela_botanica.del.client.services.rest.ProtocoleService;
import org.tela_botanica.del.client.services.rest.VoteProtocoleService;
import org.tela_botanica.del.client.services.rest.async.AjoutVoteProtocoleCallback;
import org.tela_botanica.del.client.services.rest.async.ImagesParTaxonCallback;
import org.tela_botanica.del.client.services.rest.async.ObservationsCallback;
import org.tela_botanica.del.client.services.rest.async.PropositionDeterminationCallBack;
import org.tela_botanica.del.client.services.rest.async.ProtocolesCallback;
import org.tela_botanica.del.client.services.rest.async.SuppressionPropositionDeterminationCallback;
import org.tela_botanica.del.client.services.rest.async.ValidationPropositionCallback;
import org.tela_botanica.del.client.services.rest.async.VoteProtocoleCallback;
 
public class MockDatasource implements ObservationService, ImageService, ProtocoleService, VoteProtocoleService, PropositionDeterminationService {
 
static MockDatasource instance;
 
List<Observation> observations = new ArrayList<Observation>();
 
List<InterventionForum> observationValidationDatas = new ArrayList<InterventionForum>();
 
List<String> propositionsTaxonDatas = new ArrayList<String>();
 
List<Protocole> protocoles = new ArrayList<Protocole>();
 
List<Image> images = new ArrayList<Image>();
 
private MockDatasource() {
 
HashMap<String, String> auteurObs = new LinkedHashMap<String, String>();
auteurObs.put("01Juliette 1MOUREAU", "Tragopogon porrifolius subsp. australis (Jord.) Nyman");
auteurObs.put("02Robert 2LERAS", "Iris lutescens subsp. lutescens");
auteurObs.put("03Geneviève 3BOTTI", "Euphorbia dendroides L.");
auteurObs.put("04Robert 4LERAS", "Lonicera japonica Thunb. ex Murray");
auteurObs.put("05Juliette 5MOUREAU", "Lavatera arborea L.");
auteurObs.put("06Robert 6LERAS", "Lavatera arborea L.");
auteurObs.put("07Juliette 7MOUREAU", "Serapias vomeracea (Burm.f.) Briq. ");
auteurObs.put("08Benjamin 8LIENS", "Lonicera etrusca Santi");
auteurObs.put("09Aurélient 9PERONNET", "Ophrys scolopax Cav. ");
auteurObs.put("10Grégoire 10DUCHÉ", "Staehelina dubia L. ");
auteurObs.put("11Juliette 11MOUREAU", "Tragopogon porrifolius subsp. australis (Jord.) Nyman");
auteurObs.put("12Robert 12LERAS", "Iris lutescens subsp. lutescens");
auteurObs.put("13Geneviève 13BOTTI", "Euphorbia dendroides L.");
auteurObs.put("14Robert 14LERAS", "Lonicera japonica Thunb. ex Murray");
auteurObs.put("15Juliette 15MOUREAU", "Lavatera arborea L.");
auteurObs.put("16Robert 16LERAS", "Lavatera arborea L.");
auteurObs.put("17Juliette 17MOUREAU", "Serapias vomeracea (Burm.f.) Briq. ");
auteurObs.put("18Benjamin 18LIENS", "Lonicera etrusca Santi");
auteurObs.put("19Aurélient 19PERONNET", "Ophrys scolopax Cav. ");
auteurObs.put("20Grégoire 20DUCHÉ", "Staehelina dubia L. ");
 
auteurObs.put("21Juliette 1MOUREAU", "Tragopogon porrifolius subsp. australis (Jord.) Nyman");
auteurObs.put("22R2obert 2LERAS", "Iris lutescens subsp. lutescens");
auteurObs.put("23Ge3neviève 3BOTTI", "Euphorbia dendroides L.");
auteurObs.put("24Rob4ert 4LERAS", "Lonicera japonica Thunb. ex Murray");
auteurObs.put("25Jul5iette 5MOUREAU", "Lavatera arborea L.");
auteurObs.put("26Rob6ert 6LERAS", "Lavatera arborea L.");
auteurObs.put("27J6ul7iette 7MOUREAU", "Serapias vomeracea (Burm.f.) Briq. ");
auteurObs.put("28Ben8jamin 8LIENS", "Lonicera etrusca Santi");
auteurObs.put("29Auré9lient 9PERONNET", "Ophrys scolopax Cav. ");
auteurObs.put("30Gég10oire 10DUCHÉ", "Staehelina dubia L. ");
auteurObs.put("31Julie11tte 11MOUREAU", "Tragopogon porrifolius subsp. australis (Jord.) Nyman");
auteurObs.put("32Rober12t 12LERAS", "Iris lutescens subsp. lutescens");
auteurObs.put("33Genev13iève 13BOTTI", "Euphorbia dendroides L.");
auteurObs.put("34Robe14rt 14LERAS", "Lonicera japonica Thunb. ex Murray");
auteurObs.put("35Julie15tte 15MOUREAU", "Lavatera arborea L.");
auteurObs.put("36Robe16rt 16LERAS", "Lavatera arborea L.");
auteurObs.put("37Julie17tte 17MOUREAU", "Serapias vomeracea (Burm.f.) Briq. ");
auteurObs.put("38Benja1m11in 18LIENS", "Lonicera etrusca Santi");
auteurObs.put("39Auré1111lient 19PERONNET", "Ophrys scolopax Cav. ");
auteurObs.put("40Gr545égoire 20DUCHÉ", "Staehelina dubia L. ");
 
ArrayList<String> motsClefs = new ArrayList<String>();
motsClefs.add("plantnet");
motsClefs.add("fleur");
motsClefs.add("fruit");
 
Iterator<String> auteurs = auteurObs.keySet().iterator();
 
Protocole protocol1 = new Protocole();
protocol1.setNom("esthétique");
protocol1.setId(0);
 
Protocole protocol2 = new Protocole();
protocol2.setNom("capitalisation de scan de feuilles");
protocol2.setId(1);
 
protocoles.add(protocol1);
protocoles.add(protocol2);
 
VoteDetermination voteDetermination = new VoteDetermination();
voteDetermination.setVote(1);
voteDetermination.setDate(new Date());
voteDetermination.setContributeur("benjamin");
 
PropositionDetermination observationValidationData = new PropositionDetermination(new Observation());
observationValidationData.setEspece("Iris lutescens subsp. lutescens");
Contributeur contributeur = new Contributeur("1", "contributeur", "test", "contrib@test.com");
observationValidationData.setContributeur(contributeur);
observationValidationData.setId("1");
 
observationValidationData.ajouterVoteDetermination(voteDetermination);
observationValidationData.setDate(new Date());
observationValidationDatas.add(observationValidationData);
 
PropositionDetermination observationValidationData2 = new PropositionDetermination(new Observation());
Contributeur contributeur2 = new Contributeur("2", "contributeur2", "test2", "contrib2@test.com");
observationValidationData2.setContributeur(contributeur2);
observationValidationData2.setEspece("Lavatera arborea L.");
observationValidationData2.setId("2");
observationValidationData2.ajouterVoteDetermination(voteDetermination);
observationValidationData2.setDate(new Date());
observationValidationDatas.add(observationValidationData2);
 
PropositionDetermination observationValidationData3 = new PropositionDetermination(new Observation());
observationValidationData3.setEspece("Acer monsp. L.");
Contributeur contributeur3 = new Contributeur("2", "contributeur3", "test3", "contrib3test.com");
observationValidationData3.setContributeur(contributeur3);
Commentaire commentaire = new Commentaire(new Contributeur("3", "Benjamin", "Liens", "benjamin@liens.com"), new Date(), "Avec le temps...");
Commentaire commentaireBis = new Commentaire(new Contributeur("4", "Greg", "Duche", "greg@duche.com"), new Date(), "Pas d'accord avec Greg!");
commentaire.getListeCommentaires().add(commentaireBis);
observationValidationData3.ajouterCommentaire(commentaire);
observationValidationData3.setId("3");
observationValidationData2.ajouterVoteDetermination(voteDetermination);
observationValidationData3.setDate(new Date());
observationValidationDatas.add(observationValidationData3);
 
PropositionDetermination observationValidationData4 = new PropositionDetermination(new Observation());
observationValidationData4.setEspece("Acer aceras aus.");
Contributeur contributeur4 = new Contributeur("5", "Pierre", "Desproges", "contrib4test.com");
observationValidationData4.setContributeur(contributeur4);
Commentaire commentaire2 = new Commentaire(new Contributeur("6", "Greg","Duche", "gregoire@tela-botanica.org"), new Date(), "Public chéri mon amour...");
observationValidationData4.ajouterCommentaire(commentaire2);
observationValidationData4.setId("4");
observationValidationData4.ajouterVoteDetermination(voteDetermination);
observationValidationData4.setDate(new Date());
observationValidationDatas.add(observationValidationData4);
 
PropositionDetermination observationValidationData5 = new PropositionDetermination(new Observation());
observationValidationData5.setEspece("Acer monsp subsp. monsp.");
Contributeur contributeur5 = new Contributeur("7", "contributeur5", "nom", "contrib@nom.com");
observationValidationData5.setContributeur(contributeur5);
Commentaire commentaire3 = new Commentaire(new Contributeur("8", "tsdt", "emkj", "lkjlkje@teas"), new Date(), "Tout est affaire de décor...");
observationValidationData5.ajouterCommentaire(commentaire3);
observationValidationData5.setId("5");
observationValidationData5.ajouterVoteDetermination(voteDetermination);
observationValidationData5.setDate(new Date());
observationValidationDatas.add(observationValidationData5);
 
int numobs = 44120;
for (int i = 0; i < 40; i++) {
 
Observation observation = new Observation();
String auteur = auteurs.next();
observation.setAuteur(auteur);
observation.setNomRetenu(auteurObs.get(auteur));
 
numobs += i;
observation.setNumNomenclatural("num nomenclatural " + i);
observation.setDateReleve("28/09/2011");
observation.setFamille("famille " + i);
observation.setLocalite("localite " + i);
observation.setNomRetenu(auteurObs.get(auteur));
observation.setMotsClefs(motsClefs);
observation.setInterventionsForum(observationValidationDatas);
 
Image image = new Image();
image.setIdImage("id image " + i);
image.setUrlFormat("http://www.tela-botanica.org/appli:cel-img:0000" + String.valueOf(numobs) + "%s%.jpg");
image.setUrl("http://www.tela-botanica.org/appli:cel-img:0000" + String.valueOf(numobs) + "CRS.jpg");
image.setMiniature("http://www.tela-botanica.org/appli:cel-img:0000" + String.valueOf(numobs) + "XS.jpg");
observation.getImages().add(image);
image.setObservation(observation);
images.add(image);
 
// nombre d'images aléatoires
int nbImagesAssociees = (int) Math.round(Math.random() * 10);
for (int j = 0; j < nbImagesAssociees; j++) {
numobs++;
image = new Image();
image.setIdImage("id image " + i + j);
image.setUrlFormat("http://www.tela-botanica.org/appli:cel-img:0000" + String.valueOf(numobs) + "%s%.jpg");
image.setUrl("http://www.tela-botanica.org/appli:cel-img:0000" + String.valueOf(numobs) + "CRS.jpg");
image.setMiniature("http://www.tela-botanica.org/appli:cel-img:0000" + String.valueOf(numobs) + "XS.jpg");
observation.getImages().add(image);
image.setObservation(observation);
images.add(image);
}
 
VoteProtocole voteProtocole = new VoteProtocole();
voteProtocole.setProtocole(protocol1);
voteProtocole.setVote(3);
voteProtocole.setContributeur("aurelien");
voteProtocole.setDate(new Date());
 
// image.getVoteProtocoles().add(voteProtocole);
 
VoteProtocole voteProtocole2 = new VoteProtocole();
voteProtocole2.setProtocole(protocol2);
voteProtocole2.setVote(2);
voteProtocole2.setContributeur("jpm");
voteProtocole2.setDate(new Date());
 
// image.getVoteProtocoles().add(voteProtocole2);
 
observations.add(observation);
}
 
ajouterVotesAleatoires();
 
}
 
private void ajouterVotesAleatoires() {
for (InterventionForum validation : observationValidationDatas) {
 
if (validation instanceof PropositionDetermination) {
int nbVotesAjoutes = (int) Math.round(Math.random() * 20);
 
for (int i = 0; i < nbVotesAjoutes; i++) {
VoteDetermination vd = new VoteDetermination();
vd.setVote((int) Math.round(Math.random()));
vd.setDate(new Date());
vd.setContributeur("test");
 
((PropositionDetermination) validation).ajouterVoteDetermination(vd);
}
}
}
}
 
/*
* (non-Javadoc)
*
* @see org.tela_botanica.del.client.utils.ObservationService#getImages()
*/
public List<Image> getImages(int debut, int fin) {
List<Image> sousListe = new ArrayList<Image>();
for (int i = debut; i < fin; i++) {
if (images.get(i) != null) {
sousListe.add(images.get(i));
} else {
break;
}
}
return sousListe;
}
 
public List<Observation> getObservations(int debut, int fin) {
List<Observation> sousListe = new ArrayList<Observation>();
for (int i = debut; i < fin; i++) {
if (observations.get(i) != null) {
sousListe.add(observations.get(i));
} else {
break;
}
}
return sousListe;
}
 
/*
* (non-Javadoc)
*
* @see
* org.tela_botanica.del.client.utils.ObservationService#getVote(java.lang
* .String)
*/
@Override
public List<VoteProtocole> getVote(String idImage) {
for (Image image : images) {
if (image.getIdImage().equals(idImage)) {
return null;
// return image.getVoteProtocoles();
}
 
}
return new ArrayList<VoteProtocole>(0);
}
 
/*
* (non-Javadoc)
*
* @see org.tela_botanica.del.client.utils.ObservationService#
* getVoteByImageAndProtocol(java.lang.String, java.lang.String)
*/
@Override
public List<VoteProtocole> getVotePourImageEtProtocole(String idImage, String protocolName) {
 
List<VoteProtocole> voteProtocolesLocal = new ArrayList<VoteProtocole>();
 
int rand = (int) (Math.random() * 5);
for (int i = 0; i < rand; i++) {
VoteProtocole voteProtocole = new VoteProtocole();
voteProtocole.setProtocole(protocoles.get(0));
voteProtocole.setVote((int) (Math.random() * 5));
voteProtocole.setContributeur("aurelien");
voteProtocole.setDate(new Date());
 
VoteProtocole voteProtocole2 = new VoteProtocole();
voteProtocole2.setProtocole(protocoles.get(0));
voteProtocole2.setVote((int) (Math.random() * 5));
voteProtocole2.setContributeur("jpm");
voteProtocole2.setDate(new Date());
 
voteProtocolesLocal.add(voteProtocole);
voteProtocolesLocal.add(voteProtocole2);
}
return voteProtocolesLocal;
}
 
public static MockDatasource getInstance() {
if (instance == null) {
instance = new MockDatasource();
}
return instance;
}
 
@Override
public void getImagesEfloreParTaxon(String nomTaxon, ImagesParTaxonCallback callback) {
// TODO Auto-generated method stub
 
}
 
@Override
public void getImagesParTaxon(InformationsRecherche informationsRecherche, int debut, int fin, ImagesParTaxonCallback callback) {
// TODO Auto-generated method stub
 
}
 
@Override
public void getImagesParObservation(String observationId, ImagesParTaxonCallback callback) {
// TODO Auto-generated method stub
 
}
 
@Override
public void getProtocoles(ProtocolesCallback pc) {
// TODO Auto-generated method stub
}
 
@Override
public void getProtocole(String nomProtocole) {
// TODO Auto-generated method stub
}
 
@Override
public void modifierVote(String idImage, VoteProtocole voteProtocole,
VoteProtocoleCallback vpc) {
// TODO Auto-generated method stub
}
 
@Override
public void getObservation(String idObservation,
ObservationsCallback observationsCallback) {
// TODO Auto-generated method stub
}
 
@Override
public void ajouterProposition(PropositionDetermination proposition,
PropositionDeterminationCallBack callback) {
// TODO Auto-generated method stub
}
 
@Override
public void supprimerProposition(PropositionDetermination proposition,
SuppressionPropositionDeterminationCallback callback) {
// TODO Auto-generated method stub
}
 
@Override
public void getObservations(InformationsRecherche informationsRecherche,
int debut, int fin, String statut, ObservationsCallback callback) {
// TODO Auto-generated method stub
}
 
@Override
public void validerProposition(PropositionDetermination proposition,
ValidationPropositionCallback validationPropositionCallback) {
// TODO Auto-generated method stub
}
 
@Override
public void ajouterVote(String idImage, VoteProtocole voteProtocole,
AjoutVoteProtocoleCallback callback) {
// TODO Auto-generated method stub
}
 
@Override
public void supprimerVote(String idImage, VoteProtocole voteProtocole,
VoteProtocoleCallback vpc) {
// TODO Auto-generated method stub
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/test/composants/votes/MoyenneVotePresenteurTest.java
New file
0,0 → 1,104
package org.tela_botanica.del.test.composants.votes;
 
import static org.junit.Assert.assertEquals;
 
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.votes.moyennevotes.MoyenneVotePresenteur;
import org.tela_botanica.del.client.modeles.Image;
import org.tela_botanica.del.client.modeles.Protocole;
import org.tela_botanica.del.client.services.rest.VoteProtocoleService;
 
import com.google.gwt.user.client.ui.HasWidgets;
 
public class MoyenneVotePresenteurTest {
 
MoyenneVotePresenteur mvp;
HasWidgets container;
List<Protocole> tousLesProtocoles = new ArrayList<Protocole>();
MoyenneVotePresenteur.Vue vue;
Image imageCourante;
@Before
public void setUp() {
CacheClient.getInstance().getUtilisateur().setId(0+"");
Protocole protocol1 = new Protocole();
protocol1.setNom("esthétique");
protocol1.setId(0);
 
Protocole protocol2 = new Protocole();
protocol2.setNom("capitalisation de scan de feuilles");
protocol2.setId(1);
 
tousLesProtocoles.add(protocol1);
tousLesProtocoles.add(protocol2);
imageCourante = new Image();
Protocole protocole = tousLesProtocoles.get(0);
vue = Mockito.mock(MoyenneVotePresenteur.Vue.class,Mockito.RETURNS_DEEP_STUBS);
VoteProtocoleService voteProtocoleService=Mockito.mock(VoteProtocoleService.class);
mvp = new MoyenneVotePresenteur(imageCourante, protocole, vue, voteProtocoleService);
container = Mockito.mock(HasWidgets.class, Mockito.RETURNS_DEEP_STUBS);
mvp.go(container);
}
@Test
public void testerVoteMemeUtilisateur() {
// Un même utilisateur vote deux fois sur la même image, même protocole, en faisant des votes différents
assertEquals(1, imageCourante.getListeVotesProtocoles().size());
mvp.setValeurVoteUtilisateur(3);
mvp.enregistrerVote();
// la valeur du vote change mais le nombre de vote ne change pas, son vote est remplacé
mvp.setValeurVoteUtilisateur(1);
mvp.enregistrerVote();
assertEquals(1, imageCourante.getVotesProtocoles(0).size());
assertEquals(1, mvp.getValeurVoteTotal());
}
@Test
public void testerTroisVotesUtilisateursDifferents() {
// Trois utilisateur différents votent pour la même image et le même protocole
CacheClient.getInstance().getUtilisateur().setId(0+"");
assertEquals(1, imageCourante.getListeVotesProtocoles().size());
mvp.setValeurVoteUtilisateur(3);
mvp.enregistrerVote();
CacheClient.getInstance().getUtilisateur().setId(1+"");
mvp.setValeurVoteUtilisateur(1);
mvp.enregistrerVote();
assertEquals(2, imageCourante.getVotesProtocoles(0).size());
assertEquals(2, mvp.getValeurVoteTotal());
CacheClient.getInstance().getUtilisateur().setId(2+"");
mvp.setValeurVoteUtilisateur(5);
mvp.enregistrerVote();
assertEquals(3, imageCourante.getVotesProtocoles(0).size());
assertEquals(3, mvp.getValeurVoteTotal());
// Le premier utilisateur change d'avis et modifie son vote
CacheClient.getInstance().getUtilisateur().setId(0+"");
assertEquals(1, imageCourante.getListeVotesProtocoles().size());
mvp.setValeurVoteUtilisateur(5);
mvp.enregistrerVote();
// La moyenne des vote change mais le nombre de vote ne doit pas changer
assertEquals(3, imageCourante.getVotesProtocoles(0).size());
assertEquals(4, mvp.getValeurVoteTotal());
}
@Test
public void testerDeuxVotesMemeUtilisateursProtocolesDifferents() {
// Trois utilisateur différents votent pour la même image et le même protocole
CacheClient.getInstance().getUtilisateur().setId(0+"");
assertEquals(1, imageCourante.getListeVotesProtocoles().size());
mvp.setValeurVoteUtilisateur(3);
mvp.enregistrerVote();
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/test/composants/votes/BarreRepartitionVotePresenteurTest.java
New file
0,0 → 1,59
package org.tela_botanica.del.test.composants.votes;
 
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
 
import java.util.Date;
 
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.tela_botanica.del.client.composants.votes.barrerepartition.BarreRepartitionVotePresenteur;
import org.tela_botanica.del.client.composants.votes.barrerepartition.BarreRepartitionVotePresenteur.Vue;
import org.tela_botanica.del.client.modeles.Contributeur;
import org.tela_botanica.del.client.modeles.MoyenneVote;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.modeles.VoteDetermination;
import org.tela_botanica.del.client.services.CalculVoteDeterminationService;
import org.tela_botanica.del.client.services.rest.VoteDeterminationService;
 
public class BarreRepartitionVotePresenteurTest {
 
private BarreRepartitionVotePresenteur barreRepartitionVotePresenteur;
private BarreRepartitionVotePresenteur.Vue vue;
 
@Before
public void setUp() {
 
vue = mock(Vue.class, Mockito.RETURNS_DEEP_STUBS);
VoteDeterminationService voteDeterminationService = Mockito.mock(VoteDeterminationService.class);
barreRepartitionVotePresenteur = new BarreRepartitionVotePresenteur(vue, voteDeterminationService);
 
VoteDetermination voteDetermination = new VoteDetermination();
voteDetermination.setVote(1);
voteDetermination.setDate(new Date());
voteDetermination.setContributeur("benjamin");
 
Observation obs = new Observation();
PropositionDetermination propositionDetermination = new PropositionDetermination(obs);
propositionDetermination.setEspece("Iris lutescens subsp. lutescens");
propositionDetermination.setContributeur(new Contributeur("1", "contrib", "test", "contrib@test.com"));
propositionDetermination.setId("1");
propositionDetermination.ajouterVoteDetermination(voteDetermination);
propositionDetermination.setObservation(obs);
obs.ajouterPropositionDetermination(propositionDetermination);
 
MoyenneVote moyenneVote = CalculVoteDeterminationService.calculerVoteDetermination(propositionDetermination);
barreRepartitionVotePresenteur.afficherVotes(moyenneVote);
}
 
@Test
public void testVoter() {
assertEquals("Iris lutescens subsp. lutescens", barreRepartitionVotePresenteur.getMoyenneVote().getIntituleAssocie());
assertEquals(100, barreRepartitionVotePresenteur.getMoyenneVote().getScore());
barreRepartitionVotePresenteur.voter(false);
assertEquals(100, barreRepartitionVotePresenteur.getMoyenneVote().getScore());
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/test/composants/moteurrecherche/MoteurRecherchePresenteurTest.java
New file
0,0 → 1,494
package org.tela_botanica.del.test.composants.moteurrecherche;
 
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.formulaires.autocompletion.AutoCompletionComboBoxPresenteur;
import org.tela_botanica.del.client.composants.moteurrecherche.MoteurRecherchePresenteur;
import org.tela_botanica.del.client.composants.moteurrecherche.MoteurRecherchePresenteur.TypeMoteur;
import org.tela_botanica.del.client.config.Config;
import org.tela_botanica.del.client.modeles.ModeRecherche;
import org.tela_botanica.del.client.utils.UtilitairesAutoCompletionService;
 
 
import com.google.gwt.http.client.Response;
import com.google.gwt.user.client.ui.HasWidgets;
 
public class MoteurRecherchePresenteurTest {
 
MoteurRecherchePresenteur presenteurRechercheObservation;
MoteurRecherchePresenteur.Vue vueRechercheObservation;
AutoCompletionComboBoxPresenteur presenteurAutoCompletionTaxonsObservation;
AutoCompletionComboBoxPresenteur.Vue vueAutoCompletionTaxonsObservation;
HasWidgets container;
MoteurRecherchePresenteur presenteurRechercheImage;
MoteurRecherchePresenteur.Vue vueRechercheImage;
AutoCompletionComboBoxPresenteur presenteurAutoCompletionTaxonsImage;
AutoCompletionComboBoxPresenteur.Vue vueAutoCompletionImage;
AutoCompletionComboBoxPresenteur presenteurAutoCompletionCommunesImage;
AutoCompletionComboBoxPresenteur.Vue vueAutoCompletionCommunesImage;
AutoCompletionComboBoxPresenteur presenteurAutoCompletionCommunesObservation;
AutoCompletionComboBoxPresenteur.Vue vueAutoCompletionCommunesObservation;
Config config;
boolean rechercheObservationEffectuee = false;
boolean rechercheImageEffectuee = false;
private static String NOM_SCI_COMPLETION_SERVICE = "URL_FACTICE";
@Before
public void setUp() {
vueRechercheObservation = Mockito.mock(MoteurRecherchePresenteur.Vue.class, Mockito.RETURNS_MOCKS);
vueAutoCompletionTaxonsObservation = Mockito.mock(AutoCompletionComboBoxPresenteur.Vue.class, Mockito.RETURNS_MOCKS);
container = Mockito.mock(HasWidgets.class, Mockito.RETURNS_MOCKS);
presenteurAutoCompletionTaxonsObservation = new AutoCompletionComboBoxPresenteur(vueAutoCompletionTaxonsObservation, NOM_SCI_COMPLETION_SERVICE) {
@Override
protected String[] parserResultatRequete(Response response) {
// TODO Auto-generated method stub
return null;
}
};
vueAutoCompletionCommunesObservation = Mockito.mock(AutoCompletionComboBoxPresenteur.Vue.class, Mockito.RETURNS_MOCKS);
presenteurAutoCompletionCommunesObservation = new AutoCompletionComboBoxPresenteur(vueAutoCompletionCommunesObservation, NOM_SCI_COMPLETION_SERVICE) {
protected String effectuerPreTraitementChaineRequete(String requete) {
return requete;
}
@Override
protected void surSelectionSuggestion(String suggestion) {
String[] tableauCommuneDpt = suggestion.split(" ");
if (tableauCommuneDpt.length == 2) {
setValeur(tableauCommuneDpt[0]);
}
}
 
@Override
protected String[] parserResultatRequete(Response response) {
return UtilitairesAutoCompletionService.parserRetourSimple(response);
}
};
this.config = Mockito.mock(Config.class, Mockito.RETURNS_MOCKS);
Mockito.when(config.getUrl("nomSciCompletionService")).thenReturn(NOM_SCI_COMPLETION_SERVICE);
presenteurRechercheObservation = new MoteurRecherchePresenteur(
presenteurAutoCompletionTaxonsObservation,
presenteurAutoCompletionCommunesObservation,
vueRechercheObservation,
ModeRecherche.MODE_OBSERVATION,
config) {
public void lancerRecherche() {
chercher();
}
};
vueRechercheImage = Mockito.mock(MoteurRecherchePresenteur.Vue.class, Mockito.RETURNS_MOCKS);
vueAutoCompletionImage = Mockito.mock(AutoCompletionComboBoxPresenteur.Vue.class ,Mockito.RETURNS_MOCKS);
presenteurAutoCompletionTaxonsImage = new AutoCompletionComboBoxPresenteur(vueAutoCompletionImage, NOM_SCI_COMPLETION_SERVICE) {
@Override
protected String[] parserResultatRequete(Response response) {
// TODO Auto-generated method stub
return null;
}
};
vueAutoCompletionCommunesImage = Mockito.mock(AutoCompletionComboBoxPresenteur.Vue.class ,Mockito.RETURNS_MOCKS);
presenteurAutoCompletionCommunesImage = new AutoCompletionComboBoxPresenteur(vueAutoCompletionCommunesImage, NOM_SCI_COMPLETION_SERVICE) {
protected String effectuerPreTraitementChaineRequete(String requete) {
return requete;
}
@Override
protected void surSelectionSuggestion(String suggestion) {
String[] tableauCommuneDpt = suggestion.split(" ");
if(tableauCommuneDpt.length == 2) {
setValeur(tableauCommuneDpt[0]);
}
}
 
@Override
protected String[] parserResultatRequete(Response response) {
return UtilitairesAutoCompletionService.parserRetourSimple(response);
}
};
presenteurRechercheImage = new MoteurRecherchePresenteur(
presenteurAutoCompletionTaxonsImage,
presenteurAutoCompletionCommunesImage,
vueRechercheImage,
ModeRecherche.MODE_IMAGE,
config) {
public void lancerRecherche() {
chercher();
}
};
}
private void chercher() {
rechercheObservationEffectuee = true;
rechercheImageEffectuee = true;
}
//+------------------------------------------------------------------------------------------------------+
// OBSERVATIONS
@Test
public void testTypeMoteurParDefautEstSimpleObs() {
assertEquals(TypeMoteur.SIMPLE, presenteurRechercheObservation.getTypeMoteur());
}
@Test
public void testModeRecherche() {
assertEquals(ModeRecherche.MODE_IMAGE, presenteurRechercheImage.getMode());
assertEquals(ModeRecherche.MODE_OBSERVATION, presenteurRechercheObservation.getMode());
}
@Test
public void testObsRechercheSimpleNeRetournePasLesChampsAvancee() {
presenteurRechercheObservation.go(container);
Mockito.when(vueRechercheObservation.getValeurRechercheSimple()).thenReturn("Essai");
Mockito.when(vueRechercheObservation.getContientMots()).thenReturn("");
Mockito.when(presenteurAutoCompletionTaxonsObservation.getValeur()).thenReturn("Acer monsp.");
Mockito.when(vueRechercheObservation.getDepartement()).thenReturn("34");
Mockito.when(vueRechercheObservation.getGenre()).thenReturn("Acer");
Mockito.when(vueRechercheObservation.getMotCle()).thenReturn("Fruit, fleur, feuille");
Mockito.when(vueRechercheObservation.getDate()).thenReturn("10/02/2004");
Mockito.when(presenteurAutoCompletionCommunesObservation.getValeur()).thenReturn("Montpellier");
Mockito.when(vueRechercheObservation.getFamille()).thenReturn("Asteracae");
Mockito.when(vueRechercheObservation.getMotCle()).thenReturn("fleur, tige, épine");
Mockito.when(vueRechercheObservation.getAuteur()).thenReturn("Hubert de Linné");
presenteurRechercheObservation.setTypeMoteur(TypeMoteur.SIMPLE);
presenteurRechercheObservation.collecterInfosRecherche();
presenteurRechercheObservation.afficherRequeteEtLancerRecherche();
assertTrue(rechercheObservationEffectuee);
assertEquals("Essai", CacheClient.getInstance().getInformationsRechercheObservation().getRechercheLibre());
assertEquals(null, CacheClient.getInstance().getInformationsRechercheObservation().getTaxon());
assertEquals(null, CacheClient.getInstance().getInformationsRechercheObservation().getDepartement());
assertEquals(null, CacheClient.getInstance().getInformationsRechercheObservation().getGenre());
assertEquals(null, CacheClient.getInstance().getInformationsRechercheObservation().getMotClef());
assertEquals(null, CacheClient.getInstance().getInformationsRechercheObservation().getDate());
assertEquals(null, CacheClient.getInstance().getInformationsRechercheObservation().getCommune());
assertEquals(null, CacheClient.getInstance().getInformationsRechercheObservation().getFamille());
assertEquals(null, CacheClient.getInstance().getInformationsRechercheObservation().getMotClef());
assertEquals(null, CacheClient.getInstance().getInformationsRechercheObservation().getAuteur());
}
@Test
public void testObsRechercheAvanceeUtiliseChampContientMots() {
Mockito.when(vueRechercheObservation.getValeurRechercheSimple()).thenReturn("Simple");
Mockito.when(vueRechercheObservation.getContientMots()).thenReturn("Avancee");
Mockito.when(vueRechercheObservation.getGenre()).thenReturn("Acer");
presenteurRechercheObservation.go(container);
presenteurRechercheObservation.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheObservation.collecterInfosRecherche();
presenteurRechercheObservation.afficherRequeteEtLancerRecherche();
assertTrue(rechercheObservationEffectuee);
assertEquals("Avancee", CacheClient.getInstance().getInformationsRechercheObservation().getRechercheLibre());
assertEquals("Acer", CacheClient.getInstance().getInformationsRechercheObservation().getGenre());
}
@Test
public void testLancerRechercheLibreObs() {
presenteurRechercheObservation.go(container);
Mockito.when(vueRechercheObservation.getValeurRechercheSimple()).thenReturn("Essai");
presenteurRechercheObservation.collecterInfosRecherche();
presenteurRechercheObservation.afficherRequeteEtLancerRecherche();
assertTrue(rechercheObservationEffectuee);
assertEquals("Essai", CacheClient.getInstance().getInformationsRechercheObservation().getRechercheLibre());
}
@Test
public void testLancerRechercheDepartementObs() {
presenteurRechercheObservation.go(container);
Mockito.when(vueRechercheObservation.getDepartement()).thenReturn("34");
presenteurRechercheObservation.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheObservation.collecterInfosRecherche();
presenteurRechercheObservation.afficherRequeteEtLancerRecherche();
assertTrue(rechercheObservationEffectuee);
assertEquals("34", CacheClient.getInstance().getInformationsRechercheObservation().getDepartement());
}
@Test
public void testLancerRechercheTaxonObs() {
presenteurRechercheObservation.go(container);
Mockito.when(presenteurAutoCompletionTaxonsObservation.getValeur()).thenReturn("Acer monsp.");
presenteurRechercheObservation.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheObservation.collecterInfosRecherche();
presenteurRechercheObservation.afficherRequeteEtLancerRecherche();
assertTrue(rechercheObservationEffectuee);
assertEquals("Acer monsp.", CacheClient.getInstance().getInformationsRechercheObservation().getTaxon());
}
@Test
public void testLancerRechercheGenreObs() {
presenteurRechercheObservation.go(container);
Mockito.when(vueRechercheObservation.getGenre()).thenReturn("Acer");
presenteurRechercheObservation.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheObservation.collecterInfosRecherche();
presenteurRechercheObservation.afficherRequeteEtLancerRecherche();
assertTrue(rechercheObservationEffectuee);
assertEquals("Acer", CacheClient.getInstance().getInformationsRechercheObservation().getGenre());
}
@Test
public void testLancerRechercheMotCleObs() {
presenteurRechercheObservation.go(container);
Mockito.when(vueRechercheObservation.getMotCle()).thenReturn("Fruit, fleur, feuille");
presenteurRechercheObservation.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheObservation.collecterInfosRecherche();
presenteurRechercheObservation.afficherRequeteEtLancerRecherche();
assertTrue(rechercheObservationEffectuee);
assertEquals("Fruit, fleur, feuille", CacheClient.getInstance().getInformationsRechercheObservation().getMotClef());
}
@Test
public void testLancerRechercheDateObs() {
presenteurRechercheObservation.go(container);
Mockito.when(vueRechercheObservation.getDate()).thenReturn("10/02/2004");
presenteurRechercheObservation.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheObservation.collecterInfosRecherche();
presenteurRechercheObservation.afficherRequeteEtLancerRecherche();
assertTrue(rechercheObservationEffectuee);
assertEquals("10/02/2004", CacheClient.getInstance().getInformationsRechercheObservation().getDate());
}
@Test
public void testLancerRechercheCommuneObs() {
presenteurRechercheObservation.go(container);
Mockito.when(presenteurAutoCompletionCommunesObservation.getValeur()).thenReturn("Montpellier");
presenteurRechercheObservation.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheObservation.collecterInfosRecherche();
presenteurRechercheObservation.afficherRequeteEtLancerRecherche();
assertTrue(rechercheObservationEffectuee);
assertEquals("Montpellier", CacheClient.getInstance().getInformationsRechercheObservation().getCommune());
}
@Test
public void testLancerRechercheFamilleObs() {
presenteurRechercheObservation.go(container);
Mockito.when(vueRechercheObservation.getFamille()).thenReturn("Asteracae");
presenteurRechercheObservation.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheObservation.collecterInfosRecherche();
presenteurRechercheObservation.afficherRequeteEtLancerRecherche();
assertTrue(rechercheObservationEffectuee);
assertEquals("Asteracae", CacheClient.getInstance().getInformationsRechercheObservation().getFamille());
}
@Test
public void testLancerRechercheTagObs() {
presenteurRechercheObservation.go(container);
Mockito.when(vueRechercheObservation.getMotCle()).thenReturn("fleur, tige, épine");
presenteurRechercheObservation.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheObservation.collecterInfosRecherche();
presenteurRechercheObservation.afficherRequeteEtLancerRecherche();
assertTrue(rechercheObservationEffectuee);
assertEquals("fleur, tige, épine", CacheClient.getInstance().getInformationsRechercheObservation().getMotClef());
}
@Test
public void testLancerRechercheAuteurObs() {
presenteurRechercheObservation.go(container);
Mockito.when(vueRechercheObservation.getAuteur()).thenReturn("Hubert de Linné");
presenteurRechercheObservation.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheObservation.collecterInfosRecherche();
presenteurRechercheObservation.afficherRequeteEtLancerRecherche();
assertTrue(rechercheObservationEffectuee);
assertEquals("Hubert de Linné", CacheClient.getInstance().getInformationsRechercheObservation().getAuteur());
}
//+------------------------------------------------------------------------------------------------------+
// IMAGES
@Test
public void testTypeMoteurParDefautEstSimpleImage() {
assertEquals(TypeMoteur.SIMPLE, presenteurRechercheImage.getTypeMoteur());
}
@Test
public void testLancerRechercheLibreImage() {
presenteurRechercheImage.go(container);
Mockito.when(vueRechercheImage.getValeurRechercheSimple()).thenReturn("Essai");
presenteurRechercheImage.collecterInfosRecherche();
presenteurRechercheImage.afficherRequeteEtLancerRecherche();
assertTrue(rechercheImageEffectuee);
assertEquals("Essai", CacheClient.getInstance().getInformationsRechercheImage().getRechercheLibre());
}
@Test
public void testImageLancerRechercheSimpleNeRetournePasLesChampsAvancee() {
Mockito.when(vueRechercheImage.getValeurRechercheSimple()).thenReturn("Essai");
Mockito.when(presenteurAutoCompletionCommunesImage.getValeur()).thenReturn("Acer monsp.");
Mockito.when(vueRechercheImage.getDepartement()).thenReturn("34");
Mockito.when(vueRechercheImage.getGenre()).thenReturn("Acer");
Mockito.when(vueRechercheImage.getMotCle()).thenReturn("Fruit, fleur, feuille");
Mockito.when(vueRechercheImage.getDate()).thenReturn("10/02/2004");
Mockito.when(presenteurAutoCompletionCommunesImage.getValeur()).thenReturn("Montpellier");
Mockito.when(vueRechercheImage.getFamille()).thenReturn("Asteracae");
Mockito.when(vueRechercheImage.getMotCle()).thenReturn("fleur, tige, épine");
Mockito.when(vueRechercheImage.getAuteur()).thenReturn("Hubert de Linné");
presenteurRechercheImage.go(container);
presenteurRechercheImage.setTypeMoteur(TypeMoteur.SIMPLE);
presenteurRechercheImage.collecterInfosRecherche();
presenteurRechercheImage.afficherRequeteEtLancerRecherche();
assertTrue(rechercheImageEffectuee);
assertEquals("Essai", CacheClient.getInstance().getInformationsRechercheImage().getRechercheLibre());
assertEquals(null, CacheClient.getInstance().getInformationsRechercheImage().getTaxon());
assertEquals(null, CacheClient.getInstance().getInformationsRechercheImage().getDepartement());
assertEquals(null, CacheClient.getInstance().getInformationsRechercheImage().getGenre());
assertEquals(null, CacheClient.getInstance().getInformationsRechercheImage().getMotClef());
assertEquals(null, CacheClient.getInstance().getInformationsRechercheImage().getDate());
assertEquals(null, CacheClient.getInstance().getInformationsRechercheImage().getCommune());
assertEquals(null, CacheClient.getInstance().getInformationsRechercheImage().getFamille());
assertEquals(null, CacheClient.getInstance().getInformationsRechercheImage().getMotClef());
assertEquals(null, CacheClient.getInstance().getInformationsRechercheImage().getAuteur());
}
@Test
public void testImageRechercheAvanceeUtiliseChampContientMots() {
Mockito.when(vueRechercheImage.getValeurRechercheSimple()).thenReturn("Simple");
Mockito.when(vueRechercheImage.getContientMots()).thenReturn("Avancee");
Mockito.when(vueRechercheImage.getGenre()).thenReturn("Acer");
presenteurRechercheImage.go(container);
presenteurRechercheImage.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheImage.collecterInfosRecherche();
presenteurRechercheImage.afficherRequeteEtLancerRecherche();
assertTrue(rechercheImageEffectuee);
assertEquals("Avancee", CacheClient.getInstance().getInformationsRechercheImage().getRechercheLibre());
assertEquals("Acer", CacheClient.getInstance().getInformationsRechercheImage().getGenre());
}
@Test
public void testLancerRechercheDepartementImage() {
presenteurRechercheImage.go(container);
Mockito.when(vueRechercheImage.getDepartement()).thenReturn("34");
presenteurRechercheImage.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheImage.collecterInfosRecherche();
presenteurRechercheImage.afficherRequeteEtLancerRecherche();
assertTrue(rechercheImageEffectuee);
assertEquals("34", CacheClient.getInstance().getInformationsRechercheImage().getDepartement());
}
@Test
public void testLancerRechercheTaxonImage() {
presenteurRechercheImage.go(container);
Mockito.when(presenteurAutoCompletionTaxonsImage.getValeur()).thenReturn("Acer monsp.");
presenteurRechercheImage.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheImage.collecterInfosRecherche();
presenteurRechercheImage.afficherRequeteEtLancerRecherche();
assertTrue(rechercheImageEffectuee);
assertEquals("Acer monsp.", CacheClient.getInstance().getInformationsRechercheImage().getTaxon());
}
@Test
public void testLancerRechercheGenreImage() {
presenteurRechercheImage.go(container);
Mockito.when(vueRechercheImage.getGenre()).thenReturn("Acer");
presenteurRechercheImage.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheImage.collecterInfosRecherche();
presenteurRechercheImage.afficherRequeteEtLancerRecherche();
assertTrue(rechercheImageEffectuee);
assertEquals("Acer", CacheClient.getInstance().getInformationsRechercheImage().getGenre());
}
@Test
public void testLancerRechercheMotCleImage() {
presenteurRechercheImage.go(container);
Mockito.when(vueRechercheImage.getMotCle()).thenReturn("Fruit, fleur, feuille");
presenteurRechercheImage.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheImage.collecterInfosRecherche();
presenteurRechercheImage.afficherRequeteEtLancerRecherche();
assertTrue(rechercheImageEffectuee);
assertEquals("Fruit, fleur, feuille", CacheClient.getInstance().getInformationsRechercheImage().getMotClef());
}
@Test
public void testLancerRechercheDateImage() {
presenteurRechercheImage.go(container);
Mockito.when(vueRechercheImage.getDate()).thenReturn("10/02/2004");
presenteurRechercheImage.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheImage.collecterInfosRecherche();
presenteurRechercheImage.afficherRequeteEtLancerRecherche();
assertTrue(rechercheImageEffectuee);
assertEquals("10/02/2004", CacheClient.getInstance().getInformationsRechercheImage().getDate());
}
@Test
public void testLancerRechercheCommuneImage() {
presenteurRechercheImage.go(container);
Mockito.when(presenteurAutoCompletionCommunesImage.getValeur()).thenReturn("Montpellier");
presenteurRechercheImage.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheImage.collecterInfosRecherche();
presenteurRechercheImage.afficherRequeteEtLancerRecherche();
assertTrue(rechercheImageEffectuee);
assertEquals("Montpellier", CacheClient.getInstance().getInformationsRechercheImage().getCommune());
}
@Test
public void testLancerRechercheFamilleImage() {
presenteurRechercheImage.go(container);
Mockito.when(vueRechercheImage.getFamille()).thenReturn("Asteracae");
presenteurRechercheImage.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheImage.collecterInfosRecherche();
presenteurRechercheImage.afficherRequeteEtLancerRecherche();
assertTrue(rechercheImageEffectuee);
assertEquals("Asteracae", CacheClient.getInstance().getInformationsRechercheImage().getFamille());
}
@Test
public void testLancerRechercheTagImage() {
presenteurRechercheImage.go(container);
Mockito.when(vueRechercheImage.getMotCle()).thenReturn("fleur, tige, épine");
presenteurRechercheImage.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheImage.collecterInfosRecherche();
presenteurRechercheImage.afficherRequeteEtLancerRecherche();
assertTrue(rechercheImageEffectuee);
assertEquals("fleur, tige, épine", CacheClient.getInstance().getInformationsRechercheImage().getMotClef());
}
@Test
public void testLancerRechercheAuteurImage() {
presenteurRechercheImage.go(container);
Mockito.when(vueRechercheImage.getAuteur()).thenReturn("Hubert de Linné");
presenteurRechercheImage.setTypeMoteur(TypeMoteur.AVANCEE);
presenteurRechercheImage.collecterInfosRecherche();
presenteurRechercheImage.afficherRequeteEtLancerRecherche();
assertTrue(rechercheImageEffectuee);
assertEquals("Hubert de Linné", CacheClient.getInstance().getInformationsRechercheImage().getAuteur());
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/test/composants/formulaires/FormulaireCommentaireTest.java
New file
0,0 → 1,69
package org.tela_botanica.del.test.composants.formulaires;
 
import static org.junit.Assert.*;
 
import java.util.Date;
 
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.tela_botanica.del.client.composants.formulaires.formulairecommentaire.FormulaireCommentairePresenteur;
import org.tela_botanica.del.client.composants.formulaires.formulairecommentaire.FormulaireCommentairePresenteur.Vue;
import org.tela_botanica.del.client.modeles.Commentaire;
import org.tela_botanica.del.client.modeles.Contributeur;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.services.rest.CommentaireService;
 
public class FormulaireCommentaireTest {
 
FormulaireCommentairePresenteur presenteurFormulaireCommentairePourObservation;
FormulaireCommentairePresenteur presenteurFormulaireCommentairePourPossesseurCommentaire;
 
Commentaire comm;
 
Observation obs;
 
@Before
public void setUp() {
 
obs = new Observation();
comm = new Commentaire(new Contributeur("1", "Peronnet", "Aurélien", "aurelien@tela-botanica.org"), new Date(), "Ceci est une chaine de charactères");
obs.getInterventionsForum().add(comm);
 
Vue vue1 = Mockito.mock(FormulaireCommentairePresenteur.Vue.class, Mockito.RETURNS_MOCKS);
Mockito.when(vue1.getCommentaire().getText()).thenReturn("Ceci est un commentaire");
Mockito.when(vue1.getPrenom()).thenReturn("Georges");
Mockito.when(vue1.getNom()).thenReturn("Abitbol");
 
CommentaireService commentaireService = Mockito.mock(CommentaireService.class);
presenteurFormulaireCommentairePourObservation = new FormulaireCommentairePresenteur(obs, commentaireService, vue1);
 
Vue vue2 = Mockito.mock(FormulaireCommentairePresenteur.Vue.class, Mockito.RETURNS_MOCKS);
Mockito.when(vue2.getCommentaire().getText()).thenReturn("Ceci est un commentaire");
Mockito.when(vue2.getPrenom()).thenReturn("Georges");
Mockito.when(vue2.getNom()).thenReturn("Abitbol");
 
presenteurFormulaireCommentairePourPossesseurCommentaire = new FormulaireCommentairePresenteur(comm, commentaireService, vue2);
}
 
@Test
public void testAjoutCommentaireSurObservation() {
assertEquals(1, obs.getInterventionsForum().size());
 
presenteurFormulaireCommentairePourObservation.surValidationCommentaire();
assertEquals(1, obs.getInterventionsForum().size());
}
 
@Test
public void testAjoutCommentaireSurPossesseurCOmmentaire() {
// Les deux ligne suivantes désignent normalement le même objet, qui ne
// possède pas de commentaire
// au début
assertEquals(comm.getListeCommentaires().size(), 0);
assertEquals(obs.getInterventionsForum().get(0).getListeCommentaires().size(), 0);
 
presenteurFormulaireCommentairePourPossesseurCommentaire.surValidationCommentaire();
assertEquals(obs.getInterventionsForum().size(), 1);
assertEquals(obs.getInterventionsForum().get(0).getListeCommentaires().size(), 1);
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/test/composants/identification/FormulaireIdentificationPresenteurTest.java
New file
0,0 → 1,66
package org.tela_botanica.del.test.composants.identification;
 
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.tela_botanica.del.client.cache.CacheClient;
import org.tela_botanica.del.client.composants.formulaires.identification.FormulaireIdentificationPresenteur;
import org.tela_botanica.del.client.modeles.Utilisateur;
import org.tela_botanica.del.client.services.rest.UtilisateurService;
import org.tela_botanica.del.client.services.rest.async.UtilisateurCallback;
 
public class FormulaireIdentificationPresenteurTest {
FormulaireIdentificationPresenteur.Vue vue;
FormulaireIdentificationPresenteur presenteur;
Utilisateur utilisateurDepart;
@Before
public void setUp() throws Exception {
utilisateurDepart = new Utilisateur("gregoire@tela-botanica.org");
utilisateurDepart.setIdentifie(true);
utilisateurDepart.setCourriel("gregoire@tela-botanica.org");
utilisateurDepart.setNom("Duché");
utilisateurDepart.setPrenom("Grégoire");
vue = Mockito.mock(FormulaireIdentificationPresenteur.Vue.class, Mockito.RETURNS_MOCKS);
presenteur = new FormulaireIdentificationPresenteur(vue, new UtilisateurService() {
@Override
public void obtenirUtilisateur(UtilisateurCallback callback) {
}
@Override
public void connecterUtilisateur(String login, String motDePasse, UtilisateurCallback callback) {
Utilisateur utilisateur = new Utilisateur(login);
utilisateur.setCourriel(login);
utilisateur.setIdentifie(true);
CacheClient.getInstance().setUtilisateur(utilisateur);
}
 
@Override
public void deconnecterUtilisateur(UtilisateurCallback callback) {
// TODO Auto-generated method stub
}
});
}
 
@Test
public void loginOk() {
presenteur.connecterUtilisateur(utilisateurDepart.getId(), "test");
Utilisateur utilisateurCache = CacheClient.getInstance().getUtilisateur();
assertEquals(utilisateurDepart.getCourriel(), utilisateurCache.getCourriel());
assertEquals(true, utilisateurCache.estIdentifie());
}
@Test
public void deconnecter() {
presenteur.deconnecterUtilisateur();
Utilisateur utilisateurCache = CacheClient.getInstance().getUtilisateur();
assertEquals(null, utilisateurCache.getId());
assertEquals(false, utilisateurCache.estIdentifie());
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/test/composants/pagination/PaginationPresenteurTest.java
New file
0,0 → 1,137
package org.tela_botanica.del.test.composants.pagination;
 
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
 
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.tela_botanica.del.client.composants.pagination.PaginationPresenteur;
 
import com.google.gwt.event.dom.client.HasChangeHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.ui.HasWidgets;
 
public class PaginationPresenteurTest {
 
/**
* Presenteur utilisé pour le test de synchro pagination
*/
PaginationPresenteur paginationHautPresenteur;
/**
* Presenteur utilisé pour le test de synchro pagination
*/
PaginationPresenteur paginationBasPresenteur;
 
/**
* Presenteur utilisé seul qui ne doit pas réagir au évènements lancés par
* les deux autres
*/
PaginationPresenteur paginationPresenteurSeul;
 
@Before
public void setUp() {
PaginationPresenteur.Vue vueBas = creerMockVuePaginationPresenteurBasique();
this.paginationBasPresenteur = new PaginationPresenteur(vueBas, 100, 10, 1) {
 
@Override
public void chargerElements(int debut, int fin) {
// TODO Auto-generated method stub
 
}
 
@Override
public void actualiserPasCache(int pas) {
// TODO Auto-generated method stub
 
}
};
 
PaginationPresenteur.Vue vueHaut = creerMockVuePaginationPresenteurBasique();
this.paginationHautPresenteur = new PaginationPresenteur(vueHaut, 100, 10, 1) {
 
@Override
public void actualiserPasCache(int pas) {
}
 
@Override
public void chargerElements(int debut, int fin) {
// TODO Auto-generated method stub
 
}
};
 
PaginationPresenteur.Vue vueSeule = creerMockVuePaginationPresenteurBasique();
this.paginationPresenteurSeul = new PaginationPresenteur(vueSeule, 100, 10, 1) {
 
@Override
public void actualiserPasCache(int pas) {
}
 
@Override
public void chargerElements(int debut, int fin) {
// TODO Auto-generated method stub
 
}
};
 
HasWidgets containerMock = Mockito.mock(HasWidgets.class);
 
paginationHautPresenteur.setGroupePagination("pagination_synchro");
paginationBasPresenteur.setGroupePagination("pagination_synchro");
 
paginationHautPresenteur.go(containerMock);
paginationBasPresenteur.go(containerMock);
 
paginationPresenteurSeul.go(containerMock);
}
 
@Test
public void testSynchronisationChangementPageCourante() {
 
assertEquals(1, paginationHautPresenteur.getPageCourante());
assertEquals(1, paginationBasPresenteur.getPageCourante());
 
paginationBasPresenteur.allerALapageSuivante();
assertEquals(2, paginationHautPresenteur.getPageCourante());
}
 
@Test
public void testSynchronisationChangementPas() {
paginationBasPresenteur.changerPas(20);
assertEquals(1, paginationBasPresenteur.getPageCourante());
assertEquals(20, paginationHautPresenteur.getPas());
}
 
@Test
public void testGroupePaginationDifferents() {
paginationPresenteurSeul.allerALapageSuivante();
assertEquals(2, paginationPresenteurSeul.getPageCourante());
 
paginationBasPresenteur.allerAlaDernierePage();
assertEquals(10, paginationHautPresenteur.getPageCourante());
assertEquals(10, paginationBasPresenteur.getPageCourante());
 
assertEquals(2, paginationPresenteurSeul.getPageCourante());
}
 
private PaginationPresenteur.Vue creerMockVuePaginationPresenteurBasique() {
 
PaginationPresenteur.Vue vueMock = Mockito.mock(PaginationPresenteur.Vue.class);
HasChangeHandlers saisiePageCourante = Mockito.mock(HasChangeHandlers.class);
HasChangeHandlers selecteurPas = Mockito.mock(HasChangeHandlers.class);
HasClickHandlers boutonPrecedent = Mockito.mock(HasClickHandlers.class);
HasClickHandlers boutonSuivant = Mockito.mock(HasClickHandlers.class);
HasClickHandlers boutonPremierePage = Mockito.mock(HasClickHandlers.class);
HasClickHandlers boutonDernierePage = Mockito.mock(HasClickHandlers.class);
 
when(vueMock.getSaisiePageCourante()).thenReturn(saisiePageCourante);
when(vueMock.getSelecteurPas()).thenReturn(selecteurPas);
when(vueMock.getBoutonPrecedent()).thenReturn(boutonPrecedent);
when(vueMock.getBoutonSuivant()).thenReturn(boutonSuivant);
when(vueMock.getBoutonPremierePage()).thenReturn(boutonPremierePage);
when(vueMock.getBoutonDernierePage()).thenReturn(boutonDernierePage);
 
return vueMock;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/test/composants/motsclesimage/MotsClesImageTest.java
New file
0,0 → 1,81
package org.tela_botanica.del.test.composants.motsclesimage;
 
import static org.junit.Assert.*;
 
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
 
import org.junit.Before;
import org.junit.Test;
import org.tela_botanica.del.client.modeles.MotCle;
import org.tela_botanica.del.client.utils.StringUtils;
 
public class MotsClesImageTest {
List<MotCle> motsCles;
List<String> motClesCelAFiltrer;
 
@Before
public void setUp() {
String chaineMotsClesCelAFiltrer = "fleur,feuille,ecorce,fruit,port,defiphoto";
this.motClesCelAFiltrer = new ArrayList<String>();
String[] tabMotsClesCelAFiltrer = chaineMotsClesCelAFiltrer.split(",");
for (int i = 0; i < tabMotsClesCelAFiltrer.length; i++) {
this.motClesCelAFiltrer.add(StringUtils.normaliser(tabMotsClesCelAFiltrer[i]));
}
motsCles = new ArrayList<MotCle>();
}
 
@Test
public void testFiltreMotClesCelAvecAccents() {
MotCle mc1 = new MotCle("1", "1", "écorce");
MotCle mc2 = new MotCle("2", "1", "pôrt");
MotCle mc3 = new MotCle("3", "1", "ucorce");
MotCle mc4 = new MotCle("4", "1", "Défi Photo");
MotCle mc5 = new MotCle("5", "1", "FeuIlle");
MotCle mc6 = new MotCle("6", "1", "fruIT");
motsCles.add(mc1);
motsCles.add(mc2);
motsCles.add(mc3);
motsCles.add(mc4);
motsCles.add(mc5);
motsCles.add(mc6);
List<String> resultat = afficherMotsClesCel(motsCles, motClesCelAFiltrer);
assertEquals(5, resultat.size());
}
@Test
public void testNormalisation() {
String avecEspaces = "mot cle espaces";
String sansEspaces = "motcleespaces";
 
assertEquals(StringUtils.normaliser(avecEspaces), StringUtils.normaliser(sansEspaces));
String avecAccents = "motcléaccentué";
String sansAccents = "motcleaccentue";
 
assertEquals(StringUtils.normaliser(avecAccents), StringUtils.normaliser(sansAccents));
String avecEspacesAccents = "mot clé èspâces";
String sansEspacesAccents = "motcleespaces";
 
assertEquals(StringUtils.normaliser(avecEspacesAccents), StringUtils.normaliser(sansEspacesAccents));
}
private List<String> afficherMotsClesCel(List<MotCle> motsClesCelImages, List<String> motsClesCelAFiltrer) {
List<String> motsClesCel = new ArrayList<String>();
for (Iterator<MotCle> iterator = motsClesCelImages.iterator(); iterator.hasNext();) {
String mot = iterator.next().getMotCle();
if(!mot.trim().isEmpty() && motsClesCelAFiltrer.contains(StringUtils.normaliser(mot))) {
motsClesCel.add(mot);
}
}
return motsClesCel;
}
}
/tags/v1.1-helium/src/org/tela_botanica/del/test/modeles/MoyenneVoteTest.java
New file
0,0 → 1,41
package org.tela_botanica.del.test.modeles;
 
import static org.junit.Assert.*;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
 
import org.junit.Test;
import org.tela_botanica.del.client.modeles.MoyenneVote;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
 
public class MoyenneVoteTest {
 
@Test
public void testCompareTo() {
PropositionDetermination propositionDetermination = new PropositionDetermination(new Observation());
MoyenneVote mv1 = new MoyenneVote(100, propositionDetermination);
PropositionDetermination propositionDetermination2 = new PropositionDetermination(new Observation());
MoyenneVote mv2 = new MoyenneVote(75, propositionDetermination2);
PropositionDetermination propositionDetermination3 = new PropositionDetermination(new Observation());
MoyenneVote mv3 = new MoyenneVote(50, propositionDetermination3);
PropositionDetermination propositionDetermination4 = new PropositionDetermination(new Observation());
MoyenneVote mv4 = new MoyenneVote(50, propositionDetermination4);
int mv1SuperieurMv2 = mv1.compareTo(mv2);
assertEquals(-1, mv1SuperieurMv2);
int mv3InferieurMv2 = mv3.compareTo(mv2);
assertEquals(1, mv3InferieurMv2);
int mv4EgalMv3 = mv4.compareTo(mv3);
assertEquals(0, mv4EgalMv3);
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/test/modeles/PropositionDeterminationTest.java
New file
0,0 → 1,156
package org.tela_botanica.del.test.modeles;
 
import static org.junit.Assert.*;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
 
import org.junit.Before;
import org.junit.Test;
import org.tela_botanica.del.client.modeles.Commentaire;
import org.tela_botanica.del.client.modeles.Contributeur;
import org.tela_botanica.del.client.modeles.Observation;
import org.tela_botanica.del.client.modeles.PropositionDetermination;
import org.tela_botanica.del.client.modeles.VoteDetermination;
 
 
public class PropositionDeterminationTest {
PropositionDetermination propositionDetermination;
VoteDetermination voteDetermination1;
Commentaire commentaireInitial;
Date dateInitiale;
ArrayList<Commentaire> commentairesInitiaux = new ArrayList<Commentaire>();
Map<String, VoteDetermination> votesDeterminationsInitiaux = new HashMap<String, VoteDetermination>();
@Before
public void setUp() {
propositionDetermination = new PropositionDetermination(new Observation());
Contributeur contributeur = new Contributeur("1", "peronnet", "Aurélien", "aurelien@tela-botanica.org");
propositionDetermination.setContributeur(contributeur);
propositionDetermination.setId("5");
dateInitiale = new Date();
propositionDetermination.setDate(dateInitiale);
commentaireInitial = new Commentaire(contributeur, new Date(), "Oui c'est interessant");
commentairesInitiaux.add(commentaireInitial);
propositionDetermination.setListeCommentaires(commentairesInitiaux);
propositionDetermination.setEspece("Acer monsp. L.");
voteDetermination1 = new VoteDetermination();
voteDetermination1.setVote(1);
voteDetermination1.setDate(new Date());
voteDetermination1.setContributeur("benjamin");
votesDeterminationsInitiaux.put("benjamin", voteDetermination1);
propositionDetermination.setVotesDeterminations(votesDeterminationsInitiaux);
}
@Test
public void testAjouterVoteDetermination() {
assertEquals(1, propositionDetermination.getVotesDeterminations().size());
VoteDetermination voteDeterminationTest = new VoteDetermination();
voteDeterminationTest.setVote(1);
voteDeterminationTest.setDate(new Date());
voteDeterminationTest.setContributeur("gregoire");
propositionDetermination.ajouterVoteDetermination(voteDeterminationTest);
assertEquals(2, propositionDetermination.getVotesDeterminations().size());
VoteDetermination voteDeterminationTest2 = new VoteDetermination();
voteDeterminationTest2.setVote(0);
voteDeterminationTest2.setDate(new Date());
voteDeterminationTest2.setContributeur("gregoire");
propositionDetermination.ajouterVoteDetermination(voteDeterminationTest2);
// la taille ne doit pas avoir changé après l'ajout du vote de Grégoire car le contributeur
// est la clé la map (i.e. 1 vote par personne pour une determination)
assertEquals(2, propositionDetermination.getVotesDeterminations().size());
assertEquals(0, propositionDetermination.getVotesDeterminations().get("gregoire").getVote());
}
 
@Test
public void testGetContributeur() {
assertEquals("Aurélien", propositionDetermination.getContributeur().getPrenom());
}
 
@Test
public void testSetContributeur() {
Contributeur contributeurTest = new Contributeur("1", "duche", "gregoire", "gregoire@tela-botanica.org");
propositionDetermination.setContributeur(contributeurTest);
assertEquals("gregoire", propositionDetermination.getContributeur().getPrenom());
}
 
@Test
public void testGetId() {
assertEquals("5", propositionDetermination.getId());
}
 
@Test
public void testSetId() {
propositionDetermination.setId("325");
assertEquals("325", propositionDetermination.getId());
}
 
@Test
public void testGetDate() {
assertEquals(dateInitiale, propositionDetermination.getDate());
}
 
@Test
public void testSetDate() {
Date dateTest = new Date();
propositionDetermination.setDate(dateTest);
assertEquals(dateTest, propositionDetermination.getDate());
}
 
@Test
public void testGetCommentaires() {
assertEquals(1, propositionDetermination.getListeCommentaires().size());
assertEquals("Aurélien", propositionDetermination.getListeCommentaires().get(0).getContributeur().getPrenom());
}
 
@Test
public void testSetCommentaires() {
ArrayList<Commentaire> listeVide = new ArrayList<Commentaire>();
propositionDetermination.setListeCommentaires(listeVide);
assertEquals(0, propositionDetermination.getListeCommentaires().size());
}
 
@Test
public void testAjouterCommentaire() {
propositionDetermination.setListeCommentaires(commentairesInitiaux);
assertEquals(1, propositionDetermination.getListeCommentaires().size());
Contributeur contributeur = new Contributeur("1", "Peronnet", "Aurélien", "aurelien@tela-botanica.org");
Commentaire nouveauCommentaire = new Commentaire(contributeur, new Date(), "Tout est beau, tout est joyeux, je suis une fleur");
propositionDetermination.ajouterCommentaire(nouveauCommentaire);
assertEquals(2, propositionDetermination.getListeCommentaires().size());
assertEquals("Aurélien", propositionDetermination.getListeCommentaires().get(1).getContributeur().getPrenom());
}
 
@Test
public void testGetEspece() {
assertEquals("Acer monsp. L.", propositionDetermination.getEspece());
}
 
@Test
public void testSetEspece() {
propositionDetermination.setEspece("Acer monsp. subsp. monsp.");
assertEquals("Acer monsp. subsp. monsp.", propositionDetermination.getEspece());
}
 
@Test
public void testGetVotesDeterminations() {
assertEquals(1, propositionDetermination.getVotesDeterminations().size());
assertEquals(voteDetermination1, propositionDetermination.getVotesDeterminations().get("benjamin"));
}
 
@Test
public void testSetVotesDeterminations() {
HashMap<String, VoteDetermination> votesDeterminationVides = new HashMap<String, VoteDetermination>();
propositionDetermination.setVotesDeterminations(votesDeterminationVides);
assertEquals(0,propositionDetermination.getVotesDeterminations().size());
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/test/modeles/ImageTest.java
New file
0,0 → 1,40
package org.tela_botanica.del.test.modeles;
 
import static org.junit.Assert.*;
 
import org.junit.Before;
import org.junit.Test;
import org.tela_botanica.del.client.modeles.Image;
import org.tela_botanica.del.client.modeles.Observation;
 
public class ImageTest {
Image testImage;
Observation testObservation;
@Before
public void setUp() {
testImage = new Image();
testObservation = new Observation();
testImage.setObservation(testObservation);
}
@Test
public void testEstADeterminerCarNomRetenuVide() {
testObservation.setNomRetenu("");
assertEquals(testImage.estADeterminer(), true);
}
@Test
public void testEstADeterminerCarTagImageADeterminer() {
testImage.ajouterMotsClef("aDeterminer");
assertEquals(testImage.estADeterminer(), true);
}
@Test
public void testEstADeterminerTagObservationADeterminer() {
testObservation.ajouterMotsClef("aDeterminer");
assertEquals(testImage.estADeterminer(), true);
}
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/test/DelTestSuite.java
New file
0,0 → 1,26
package org.tela_botanica.del.test;
 
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
import org.tela_botanica.del.test.composants.pagination.PaginationPresenteurTest;
import org.tela_botanica.del.test.composants.votes.BarreRepartitionVotePresenteurTest;
import org.tela_botanica.del.test.modeles.MoyenneVoteTest;
import org.tela_botanica.del.test.modeles.PropositionDeterminationTest;
import org.tela_botanica.del.test.services.CalculVoteDeterminationServiceTest;
import org.tela_botanica.del.test.vues.identiplante.MoteurIdentiplantePresenteurTest;
import org.tela_botanica.del.test.vues.identiplante.ResultatIdentiplanteTest;
 
@RunWith(Suite.class)
@SuiteClasses({
MoteurIdentiplantePresenteurTest.class,
PaginationPresenteurTest.class,
MoyenneVoteTest.class,
PropositionDeterminationTest.class,
CalculVoteDeterminationServiceTest.class,
BarreRepartitionVotePresenteurTest.class,
ResultatIdentiplanteTest.class
})
public class DelTestSuite {
 
}
/tags/v1.1-helium/src/org/tela_botanica/del/Del-test.gwt.xml
New file
0,0 → 1,6
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to="del">
<inherits name="org.tela_botanica.del.Del" />
<set-property name="user.agent" value="gecko1_8" />
<set-property name="locale" value="default" />
</module>
/tags/v1.1-helium/src/org/tela_botanica/del/Del.gwt.xml
New file
0,0 → 1,35
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to="del">
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User' />
<inherits name='org.cobogw.gwt.user.User' />
 
 
<!--Defines all possible locales we'll use-->
<extend-property name="locale" values="fr,en"/>
<!--Defines default locale-->
<set-property-fallback name="locale" value="fr"/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<inherits name='com.google.gwt.user.theme.standard.Standard' />
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
 
<!-- Other module inherits -->
<inherits name="com.google.gwt.activity.Activity" />
<inherits name="com.google.gwt.place.Place" />
 
<!-- Specify the app entry point class. -->
<entry-point class='org.tela_botanica.del.client.Del' />
 
<!-- UIBinder allows to design GWT UI's declarative via XML. -->
<inherits name='com.google.gwt.uibinder.UiBinder' />
<!-- Specify the paths for translatable code -->
<source path='client' />
<source path='shared' />
 
</module>
/tags/v1.1-helium/server.defaut.properties
New file
0,0 → 1,5
server-url=www.tela-botanica.org
server-login=xxxxxx
server-password=xxxxxx
server-dir=/www/eflore-test/del/
webservices-root-url=http://www.tela-botanica.org/eflore-test/del/jrest
/tags/v1.1-helium/war/del.php
New file
0,0 → 1,46
<!doctype html>
<html>
<head>
<title>IdentiPlante</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<base href="<?= dirname($_SERVER['PHP_SELF'])."/"; ?>" />
<!-- Fichier JS de configuration spécifique à l'application -->
<script type="text/javascript" language="javascript" src="config/config.js"></script>
<script type="text/javascript" language="javascript" src="config/apropos.js"></script>
<!-- Le script ci-dessous charger vos modules compilés. Ajoutez les méta-tags GWT avant cette ligne. -->
<script type="text/javascript" language="javascript" src="del/del.nocache.js"></script>
<link type="text/css" rel="stylesheet" href="del.css">
</head>
<!-- Le corps peut contenir du HTML ou peut rester vide si vous voulez créer une UI complêtement dynamique -->
<body>
<noscript>
<p style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
<span class="attention">ATTENTION : </span>
il semblerait que le Javascript ne soit pas activé sur votre navigateur.
Veuillez l'activer pour utiliser cette application.
</p>
</noscript>
<div id="zoneEntete">
</div>
<div id="main">
<div id="zoneTitre"></div>
<div id="zoneLiens"></div>
</div>
<div id="contenu"></div>
<!-- OPTIONAL: inclure la ligne ci-dessous si vous utilisez le supprot de l'historique du navigateur -->
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
<div id="zoneFooter"><br /><hr />Projet financ&eacute; par : <br /><br />
<a class="logo_ue" href="http://europa.eu/index_fr.htm" target="_blank"></a>
<a class="logo_lr" href="http://www.laregion.fr/" target="_blank"></a>
<a class="logo_nd" href="http://www.fondation-natureetdecouvertes.com/" target="_blank"></a>
<a class="logo_nh" href="http://www.fondation-nicolas-hulot.org/" target="_blank"></a>
</div>
</body>
</html>
/tags/v1.1-helium/war/index.html
New file
0,0 → 1,9
<html>
<head>
<title>Redirection en html</title>
<meta http-equiv="refresh" content="0;url=del.php" />
</head>
<body>
<p><a href="del.html">Si la redirection ne se fait pas automatiquement, cliquez sur ce lien.</a></p>
</body>
</html>
/tags/v1.1-helium/war/del.css
New file
0,0 → 1,772
/* La ligne suivante ne sert qu'à régler le bug d'affichage des listes déroulantes */
select {
background: #FFF;
}
/** Add css rules here for your application. */
body,html {
height: 100%;
}
 
body div {
font-family:arial;
}
 
/** Example rules used by the template application (remove for your app) */
h1 {
font-size: 2em;
font-weight: bold;
color: #777777;
margin: 0;
text-align: center;
}
 
/*#titre {background:url(/img/logo.png) no-repeat; height:100px; border:solid 1px red; width:250px; text-align:left; padding-top:50px}*/
.sendButton {
display: block;
font-size: 16pt;
}
 
/** Most GWT widgets already have a style name defined */
.gwt-DialogBox {
width: 400px;
}
 
.dialogVPanel {
margin: 5px;
}
 
.serverResponseLabelError {
color: red;
}
 
/** Erreur dans un formulaire de type texte **/
.erreurFormTexte, .erreurFormTexte input {
background-color: red !important;
}
 
/** Set ids using widget.getElement().setId("idOfElement") */
#closeButton {
margin: 15px 6px 6px;
}
 
#zoneTitre {
width:45%;
margin-top:13px;
}
#zoneLiens {
clear:both;
}
#zoneTitre h1 {
font-size:72px;
}
 
 
.titre2 {
color: #FD8C13;
font-size: 13px;
margin: 20px 0 10px;
padding: 0 0 0 25px;
text-transform: none;
font-weight: bold;
background: url(./img/troisCarre.png) no-repeat 0 8px;
}
 
.boutonPlus {
border: none;
color: rgba(0, 0, 0, 0);
background: url("./img/zoom_in.png");
width: 16px;
height: 16px;
cursor: pointer;
}
 
.boutonMoins {
border: none;
color: rgba(0, 0, 0, 0);
background: url("./img/zoom_out.png");
width: 16px;
height: 16px;
cursor: pointer;
}
 
#navigation {
}
 
#navigation>div>div {
}
 
#navigation>div>div:hover {
}
 
#navigation a {
}
 
#main {
width:1000px;
margin:0 auto;
}
 
#contenu a {
border-bottom: 1px dotted #95AE5D;
color: #598000;
}
 
#contenu a:hover {
border-bottom: 1px dotted #95AE5D;
color: #FD8C13;
}
 
.labelLien {
border-bottom: 1px dotted #95AE5D;
color: #598000;
cursor:pointer;
}
.labelLien:hover {
border-bottom: 1px dotted #95AE5D;
color: #FD8C13;
}
 
.lien {
color: blue;
text-decoration: underline;
cursor: pointer
}
 
.titre {
color: #FD8C13;
font-size: 15px;
margin: 20px 0 10px;
padding: 0 0 0 25px;
text-transform: uppercase;
font-weight: bold;
background: url(./img/troisCarre.png) no-repeat 0 8px;
}
 
.titre3 {
color: #FD8C13;
font-size: 15px;
margin: 20px 0 10px;
font-weight: bold;
}
 
.titre-minuscule {
color: #FD8C13;
font-size: 15px;
margin: 20px 0 10px;
padding: 0 0 0 25px;
font-weight: bold;
background: url(./img/troisCarre.png) no-repeat 0 8px;
}
 
.sousTitre {
font-size: 15px;
font-weight: bold
}
 
.petit {
font-size: 11px;
color: #888
}
 
.gris {
color: #888
}
 
.gras {
font-weight: bold
}
 
.plein {
width: 100%;
}
 
.tiers {
width: 30%
}
 
.quart {
width: 25%;
}
 
.actif {
background: #8EB533
}
 
.inactif {
background: white
}
 
.gauche {
float: left
}
 
.droite {
float: right
}
 
.nettoyage {
clear: both
}
 
hr {
border: none;
border-bottom: solid 1px #DDD;
border-top: solid 1px #AAA
}
 
.gwt-SuggestBoxPopup {
z-index: 10000
}
 
.fenetreDefilante {
position: fixed;
margin: auto
}
 
.overlay {
background-color: #777;
cursor: pointer;
display: block;
opacity: 0.7;
left: 0;
top: 0;
position: fixed;
width: 100%;
z-index: 1100;
height: 100%
}
 
.overlayContenu {
cursor: pointer;
display: block;
opacity: 1;
left: 0;
top: 0;
position: fixed;
width: 100%;
z-index: 1200;
height: 100%
}
 
.fermerOverlay {
z-index: 1210;
position: fixed;
width: 30px;
height: 30px;
background: url(./img/close.png) no-repeat 5px 0;
border: none;
color: white;
font-weight: bold;
cursor: pointer;
border: 1px dotted #95AE5D;
border-width: 0 0 1px 0;
padding-right: 30px
}
 
.precedentOverlay:hover {
opacity: 1;
}
 
.precedentOverlay {
display: block;
z-index: 1210;
position: fixed;
width: 30px;
height: 40px;
background: url(./img/precedent_overlay.png) no-repeat 50px 170px;
border: none;
color: white;
font-weight: bold;
cursor: pointer;
margin-top: -170px;
padding-bottom: 200px;
padding-left: 200px;
padding-top: 200px;
opacity: 0;
}
 
.suivantOverlay:hover {
opacity: 1;
}
 
.suivantOverlay {
display: block;
z-index: 1210;
position: fixed;
width: 30px;
height: 40px;
background: url(./img/suivant_overlay.png) no-repeat 90px 170px;
border: none;
color: white;
font-weight: bold;
cursor: pointer;
margin-top: -170px;
padding-bottom: 200px;
padding-right: 200px;
padding-top: 200px;
opacity: 0;
margin-left: -150px;
}
 
.acceder-outil {
background: url("./img/telaBlancJaune.png") no-repeat scroll 0 0 #ECCB12;
text-decoration: none;
border: medium none;
border-radius: 10px 10px 10px 10px;
color: #6C6865;
font-size: 14px;
padding: 4px 10px 4px 30px;
cursor: pointer;
display: inline-block;
}
 
.acceder-outil:hover {
color: #FD8C13;
}
 
#contenu a.acceder-aide {
color:white;
}
.acceder-aide {
background: none repeat scroll 0 0 #3d5fbf;
border: medium none;
border-radius: 10px 10px 10px 10px;
color: white;
cursor: pointer;
display: inline-block;
font-size: 14px;
padding: 4px 10px;
text-decoration: none;
}
 
.acceder-aide:hover {
border-bottom: 1px dotted #95AE5D;
color: #FD8C13;
}
 
.colonne {
float: left;
}
 
.ligne {
clear: left;
}
 
.ombre-forte {
box-shadow: 2px 2px 2px #666;
-moz-box-shadow: 2px 2px 2px #666;
-webkit-box-shadow: 2px 2px 2px #666;
}
 
.ombre-faible {
box-shadow: 2px 2px 2px #DDD;
-moz-box-shadow: 2px 2px 2px #DDD;
-webkit-box-shadow: 2px 2px 2px #DDD;
}
 
.limiteMin {
min-width:870px;
}
 
.limiteMax {
max-width:1000px;
margin:0 auto;
}
 
.arrondi {
border-radius:10px;
-moz-border-radius:10px;
-webkit-border-radius:10px;
}
 
.arrondi-faible {
border-radius:3px;
-moz-border-radius:3px;
-webkit-border-radius:3px;
}
 
.bouton {
background: none repeat scroll 0 0 white;
border: 1px solid #99C242;
border-radius: 10px 10px 10px 10px;
box-shadow: 1px 2px 2px #AAAAAA;
color: #598000;
cursor: pointer;
font-size: 0.9em;
font-weight: bold;
padding: 5px;
}
 
.bouton:hover {
background:#8EB533;
color:#FFF;
}
 
.bouton-petit {
background: none repeat scroll 0 0 white;
border: 1px solid #99C242;
box-shadow: 1px 2px 2px #AAAAAA;
color: #598000;
cursor: pointer;
font-size: 11px;
font-weight: bold;
padding: 1px;
width:100px;
margin:0 5px;
}
 
.bouton-petit:hover {
background:#8EB533;
color:#FFF;
}
 
.votePrisEnCompteOui {
background:#8EB533;
position:absolute;
font-size:11px;
padding:5px;
margin-top:-30px;
border-radius:10px;
}
 
.votePrisEnCompteNon, .voteSupprime {
background:#f06a6a;
position:absolute;
font-size:11px;
padding:5px;
margin-top:-30px;
border-radius:10px;
}
 
.boutonVoteOuiDesactive {
background-image: url("img/pouce_haut_desactive.png") !important;
color:#999999;
cursor: default !important;
}
 
.boutonVoteNonDesactive {
background-image: url("img/pouce_bas_desactive.png") !important;
color:#999999;
cursor: default !important;
}
 
.chapeau {
color: #6C6865;
font-family: arial;
font-size: 13px;
font-weight: bold;
letter-spacing: 0;
line-height: 18px;
text-transform: none;
font-style:italic;
}
 
.enfant {
background:#EEE;
margin-left:20px;
clear:both;
border-left:solid 1px;
padding-left:5px;
border-color:#DDD
}
 
.image_determinee {
/*background: #333;*/
}
 
.image_non_determinee {
background: #CF1313 !important;
}
.suiteImages {
background:url(./img/suiteImages.png) 3px 0 no-repeat;
cursor:pointer;
color:rgba(0, 0, 0, 0)
}
 
.propositionInitiale {
color:#8EB533;
font-weight:bold;
}
 
.etoiles {
height: 26px;
margin-left: 38px;
margin-top: -2px;
width: 26px;
}
 
.etoiles_0 {
background:url("./img/0_etoiles.png") no-repeat; border:none; padding-left:16px; padding-top:16px; margin-left:5px,
}
.etoiles_1 {
background:url("./img/1_etoiles.png") no-repeat; border:none; padding-left:16px; padding-top:16px; margin-left:5px,
}
.etoiles_2 {
background:url("./img/2_etoiles.png") no-repeat; border:none; padding-left:16px; padding-top:16px; margin-left:5px,
}
.etoiles_3 {
background:url("./img/3_etoiles.png") no-repeat; border:none; padding-left:16px; padding-top:16px; margin-left:5px;
}
.etoiles_4 {
background:url("./img/4_etoiles.png") no-repeat; border:none; padding-left:16px; padding-top:16px; margin-left:5px;
}
.etoiles_5 {
background:url("./img/5_etoiles.png") no-repeat; border:none; padding-left:16px; padding-top:16px; margin-left:5px;
}
 
.boutonOK {
background:url("./img/tick.png") no-repeat;
width:15px;
height:15px;
display:block;
margin-top:2px;
border:none;
cursor:pointer;
}
 
.enligne {
display:inline;
}
 
.aide {
background:url(./img/information.png) no-repeat;
padding-left:20px;
}
 
.lienListe {
background:url('./img/traitTela.jpg') no-repeat 0 0px;
cursor:pointer;
padding-left:31px;
padding-bottom:5px;
padding-top:2px;
border:none;
}
 
.nombreVotes {
background:url('./img/user.png') no-repeat;
cursor: pointer;
}
 
#contenu .lienRss a{
padding-right:20px;
background:url('./img/rss.png') no-repeat right center;
cursor:pointer;
padding-bottom:1px;
border:none;
}
 
.invisible {
visibility:hidden;
}
 
.motCleCel {
display: inline-block;
margin-right: 3px;
border: 1px solid grey;
background-color: #B1BEBE;
padding-left: 2px;
padding-right: 2px;
line-height: 20px;
border-radius: 5px;
opacity:1;
color: black;
}
 
 
/** FROM TELA */
.importance1 {
margin:10px 0px 25px 0px;
background-color:#eaedcd;
padding:8px;
font-family:arial;
font-size:11px;
color:#3a3633;
border-radius:10px;
-moz-border-radius:10px;
-webkit-border-radius:10px;
box-shadow:7px 7px 11px #555;
-moz-box-shadow:2px 2px 5px #aaa;
-webkit-box-shadow:7px 7px 11px #aaa;
filter:progid:DXImageTransform.Microsoft.Shadow(color='#aaaaaa', Direction=135, Strength=4);/* pour ie8 */
zoom:1;/* pour ie8 */
}
 
.traitTela li {
background: url("http://www.tela-botanica.org/sites/commun/generique/images/traitTela.jpg") no-repeat scroll 0 6px transparent;
font-family: arial;
font-size: 12px;
font-weight: bold;
color:#777;
list-style: none outside none;
padding: 10px 0 0 30px;
}
.connect {
width:130px;
margin:0;
padding:0;
}
 
.contenuCentre {
text-align:center;
}
 
/* Logos partenaires */
.logo_tela {
padding-bottom:35px;
padding-left:70px;
background:url('./img/logos/tela.jpg');
}
 
.logo_pn {
padding-bottom:35px;
padding-left:263px;
background:url('./img/logos/pn.jpg');
}
 
.logo_ue {
padding-bottom:59px;
padding-left:103px;
background:url('./img/logos/ue.jpg');
}
 
.logo_lr {
padding-bottom:59px;
padding-left:47px;
background:url('./img/logos/lr.jpg');
}
 
.logo_nd {
padding-bottom:55px;
padding-left:148px;
background:url('./img/logos/nd.jpg');
}
 
 
.logo_nh {
padding-bottom:46px;
padding-left:59px;
background:url('./img/logos/fnh.png');
}
.logo_nh:hover {
padding-bottom:46px;
padding-left:59px;
background:url('./img/logos/fnh-hover.png');
}
 
 
.logo_tela:hover {
background:url('./img/logos/tela_hover.jpg');
}
.logo_pn:hover {
background:url('./img/logos/pn_hover.jpg');
}
.logo_ue:hover {
background:url('./img/logos/ue_hover.jpg');
}
.logo_lr:hover {
background:url('./img/logos/lr_hover.jpg');
}
.logo_nd:hover {
background:url('./img/logos/nd_hover.jpg');
}
 
#zoneFooter{
width:1000px;
margin:0 auto;
text-align:center;
color:#555;
font-family:arial;
font-size:11px;
font-weight:bold;
margin-top:30px;
}
 
#zoneFooter a {
margin-right:30px;
}
 
.pictoplante-contact {
font-weight: normal;
}
 
.pictoplante-contact a {
color: green;
text-decoration : none;
}
 
.pictoplante-contact a:hover {
color: #FD8C13;
text-decoration : none;
}
 
#zoneEntete {
width:1000px;
margin:0 auto;
min-height:230px;
}
 
#zoneEntete .acceder-aide {
color:white;
}
 
#zoneEntete .acceder-outil {
color:inherit;
}
 
.zone-onglets {
margin-bottom:5px;
width:100%;
height:31px;
text-align:left;
border:solid 1px #AAA;
border-width:0 0 1px 0;
padding-left:5px;
}
 
.onglet {
border:solid 1px #AAA;
border-width:1px;
padding:3px 15px;
padding-top:6px;
padding-left:25px;
border-radius:12px 12px 0 0;
width:150px;
float:left;
background:#C2C0AD;
cursor:pointer;
height:21px;
font-size:16px;
color:#598000
}
 
.onglet * {
cursor:pointer;
}
 
.onglet:hover {
background:#d0ccaa;
}
 
.onglet-actif {
font-weight:bold;
background:white;
color:#FD8C13;
text-transform:uppercase;
}
 
.elementMasque {
background-color: #777;
cursor: default;
display: block;
opacity: 0.7;
left: 0;
top: 0;
position: relative;
width: 100%;
z-index: 1100;
height: 100%
}
/tags/v1.1-helium/war/img/tick.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/tick.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/identiplante_mini.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/identiplante_mini.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/pouce_haut.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/pouce_haut.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/search_icon.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/search_icon.gif
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/pouce_bas.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/pouce_bas.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/logos/ue_hover.jpg
Cannot display: file marked as a binary type.
svn:mime-type = image/jpeg
/tags/v1.1-helium/war/img/logos/ue_hover.jpg
New file
Property changes:
Added: svn:mime-type
+image/jpeg
\ No newline at end of property
/tags/v1.1-helium/war/img/logos/lr.jpg
Cannot display: file marked as a binary type.
svn:mime-type = image/jpeg
/tags/v1.1-helium/war/img/logos/lr.jpg
New file
Property changes:
Added: svn:mime-type
+image/jpeg
\ No newline at end of property
/tags/v1.1-helium/war/img/logos/pn.jpg
Cannot display: file marked as a binary type.
svn:mime-type = image/jpeg
/tags/v1.1-helium/war/img/logos/pn.jpg
New file
Property changes:
Added: svn:mime-type
+image/jpeg
\ No newline at end of property
/tags/v1.1-helium/war/img/logos/fnh.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/logos/fnh.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/logos/fnh-hover.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/logos/fnh-hover.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/logos/lr_hover.jpg
Cannot display: file marked as a binary type.
svn:mime-type = image/jpeg
/tags/v1.1-helium/war/img/logos/lr_hover.jpg
New file
Property changes:
Added: svn:mime-type
+image/jpeg
\ No newline at end of property
/tags/v1.1-helium/war/img/logos/pn_hover.jpg
Cannot display: file marked as a binary type.
svn:mime-type = image/jpeg
/tags/v1.1-helium/war/img/logos/pn_hover.jpg
New file
Property changes:
Added: svn:mime-type
+image/jpeg
\ No newline at end of property
/tags/v1.1-helium/war/img/logos/nd.jpg
Cannot display: file marked as a binary type.
svn:mime-type = image/jpeg
/tags/v1.1-helium/war/img/logos/nd.jpg
New file
Property changes:
Added: svn:mime-type
+image/jpeg
\ No newline at end of property
/tags/v1.1-helium/war/img/logos/nd_hover.jpg
Cannot display: file marked as a binary type.
svn:mime-type = image/jpeg
/tags/v1.1-helium/war/img/logos/nd_hover.jpg
New file
Property changes:
Added: svn:mime-type
+image/jpeg
\ No newline at end of property
/tags/v1.1-helium/war/img/logos/tela.jpg
Cannot display: file marked as a binary type.
svn:mime-type = image/jpeg
/tags/v1.1-helium/war/img/logos/tela.jpg
New file
Property changes:
Added: svn:mime-type
+image/jpeg
\ No newline at end of property
/tags/v1.1-helium/war/img/logos/tela_hover.jpg
Cannot display: file marked as a binary type.
svn:mime-type = image/jpeg
/tags/v1.1-helium/war/img/logos/tela_hover.jpg
New file
Property changes:
Added: svn:mime-type
+image/jpeg
\ No newline at end of property
/tags/v1.1-helium/war/img/logos/ue.jpg
Cannot display: file marked as a binary type.
svn:mime-type = image/jpeg
/tags/v1.1-helium/war/img/logos/ue.jpg
New file
Property changes:
Added: svn:mime-type
+image/jpeg
\ No newline at end of property
/tags/v1.1-helium/war/img/comment.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/comment.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/last.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/last.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/icon_minus.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/icon_minus.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/close.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/close.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/rss.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/rss.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/telaBlancJaune.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/telaBlancJaune.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/ajouter.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/ajouter.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/precedent_overlay.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/precedent_overlay.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/icones_tags/plantscan_new.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/icones_tags/plantscan_new.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/icones_tags/fleur.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/icones_tags/fleur.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/icones_tags/ecorce.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/icones_tags/ecorce.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/icones_tags/defiphoto.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/icones_tags/defiphoto.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/icones_tags/port.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/icones_tags/port.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/icones_tags/feuille.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/icones_tags/feuille.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/icones_tags/fruit.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/icones_tags/fruit.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/icones_tags/planche.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/icones_tags/planche.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/icones_tags/rameau.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/icones_tags/rameau.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/zoom_out.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/zoom_out.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/prev.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/prev.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/suiteImages.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/suiteImages.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/identiplante.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/identiplante.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/loupe.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/loupe.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/traitTela.jpg
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/traitTela.jpg
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/information.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/information.png
New file
Property changes:
Added: svn:executable
+*
\ No newline at end of property
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/cancel.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/cancel.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/cross.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/cross.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/fleche-bas.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/fleche-bas.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/suivant_overlay.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/suivant_overlay.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/Minus.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/Minus.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/pouce_haut_hover.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/pouce_haut_hover.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/petit_carre.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/petit_carre.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/pasdephoto.jpg
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/pasdephoto.jpg
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/pouce_bas_hover.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/pouce_bas_hover.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/tagger.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/tagger.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/zoom_in.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/zoom_in.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/lightbulb.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/lightbulb.png
New file
Property changes:
Added: svn:executable
+*
\ No newline at end of property
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/icon_plus.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/icon_plus.gif
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/troisCarre.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/troisCarre.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/fleurs/fleur0.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/fleurs/fleur0.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/fleurs/fleur1.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/fleurs/fleur1.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/fleurs/fleur2.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/fleurs/fleur2.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/fleurs/fleur3.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/fleurs/fleur3.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/fleurs/fleur4.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/fleurs/fleur4.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/fleurs/fleur5.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/fleurs/fleur5.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/user.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/user.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/next.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/next.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/pouce_haut_desactive.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/pouce_haut_desactive.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/wait.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/wait.gif
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/fleche-haut.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/fleche-haut.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/img/carre_orange.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/carre_orange.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/pouce_bas_desactive.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/pouce_bas_desactive.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/first.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
/tags/v1.1-helium/war/img/first.png
New file
Property changes:
Added: svn:mime-type
+image/png
\ No newline at end of property
/tags/v1.1-helium/war/img/add.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/tags/v1.1-helium/war/img/add.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/tags/v1.1-helium/war/config/apropos.defaut.js
New file
0,0 → 1,14
var apropos = {
appliNom:"Déterminations En Ligne",
appliCode:"DEL",
appliVersionCode:"0.1",
appliVersionNom:"Linné",
developpeurs:"Delphine CAUQUIL, Grégoire DUCHÉ, Benjamin LIENS, Jean-Pascal MILCENT, Aurélien PERONNET",
traducteurs:"",
testeurs:"Jennifer CARRÉ, Marie PICARD",
licence:"GPL v3 et CECILL v2",
dateHeureCompilation:"",
revisionGlobale:"",
revisionGlobaleServices:"",
versionJavaCompilation:""
};
/tags/v1.1-helium/war/config/config.defaut.js
New file
0,0 → 1,21
var configuration = {
serviceBaseUrl:"http://www.tela-botanica.org/eflore-test/del/services/0.1/",
serviceUtilisateursBaseUrl:"http://api-test.tela-botanica.org/service:del:0.1/",
bogueUrl:"http://www.tela-botanica.net/suivi/index.php?project=41",
commentaireUrl:"http://www.tela-botanica.org/wikini/eflore-test/wakka.php?wiki=AideDelCommentaire",
delUrl:"http://www.tela-botanica.org/appli:del",
identiplanteUrl:"http://www.tela-botanica.org/appli:identiplante",
pictofloraUrl:"http://www.tela-botanica.org/appli:pictoflora",
appliSaisieUrl: "http://www.tela-botanica.org/widget:cel:saisie?tag-img=aDeterminer&tag-obs=aDeterminer",
appliSaisieProjetUrl: "http://www.tela-botanica.org/widget:cel:saisie?tag-img={projet}&tag-obs={projet}",
annuaireUrl : "http://www.tela-botanica.org/profil:",
efloreTaxonUrl : "http://www.tela-botanica.org/referentiel-nn-num_nom",
efloreUrl : "http://www.tela-botanica.org/eflore-test/consultation/index.php?referentiel=bdtfx",
ouvragesFloreUrl : "http://www.tela-botanica.org/page:ouvrages_flore",
bonnierPdaUrl : "http://www.tela-botanica.org/eflore-test/bonnierpda",
clesDeterminationUrl : "http://www.tela-botanica.org/page:menu_379",
rssUrl : "http://www.tela-botanica.org/eflore-test/del/services/0.1/syndication/commentaires/rss2?navigation.depart=0&navigation.limite=150",
iconeTagBaseUrl : "http://www.tela-botanica.org/eflore-test/del/img/icones_tags/",
urlProfil : "http://www.tela-botanica.org/profil:",
urlImages : "http://www.tela-botanica.org/appli:cel-img:"
};
/tags/v1.1-helium/war/config
New file
Property changes:
Added: svn:ignore
+apropos.js
+config.js
/tags/v1.1-helium/war/identiplante.php
New file
0,0 → 1,51
<!doctype html>
<html>
<head>
<title>IdentiPlante</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<base href="<?= dirname($_SERVER['PHP_SELF'])."/"; ?>" />
<!-- Fichier JS de configuration spécifique à l'application -->
<script type="text/javascript" language="javascript" src="config/config.js"></script>
<script type="text/javascript" language="javascript" src="config/apropos.js"></script>
<!-- Le script ci-dessous charger vos modules compilés. Ajoutez les méta-tags GWT avant cette ligne. -->
<script type="text/javascript" language="javascript" src="del/del.nocache.js"></script>
<link type="text/css" rel="stylesheet" href="del.css">
</head>
<!-- Le corps peut contenir du HTML ou peut rester vide si vous voulez créer une UI complêtement dynamique -->
<body>
<noscript>
<p style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
<span class="attention">ATTENTION : </span>
il semblerait que le Javascript ne soit pas activé sur votre navigateur.
Veuillez l'activer pour utiliser cette application.
</p>
</noscript>
<div id="zoneEntete">
</div>
<div id="main">
<div id="zoneTitre"></div>
<div id="zoneLiens"></div>
</div>
<div id="contenu"></div>
<!-- OPTIONAL: inclure la ligne ci-dessous si vous utilisez le supprot de l'historique du navigateur -->
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
<div id="zoneFooter"><br /><hr />
<span class="pictoplante-contact">
Vous avez remarqué un bug ou voulez nous suggérer des améliorations? Contactez-nous à
<a href="mailto:identiplante_remarques@tela-botanica.org">identiplante_remarques@tela-botanica.org</a>
</span><br/><br/>
Projet financ&eacute; par : <br /><br />
<a class="logo_ue" href="http://europa.eu/index_fr.htm" target="_blank"></a>
<a class="logo_lr" href="http://www.laregion.fr/" target="_blank"></a>
<a class="logo_nd" href="http://www.fondation-natureetdecouvertes.com/" target="_blank"></a>
<a class="logo_nh" href="http://www.fondation-nicolas-hulot.org/" target="_blank"></a>
</div>
</body>
</html>
/tags/v1.1-helium/war/pictoflora.php
New file
0,0 → 1,51
<!doctype html>
<html>
<head>
<title>Pictoflora</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<base href="<?= dirname($_SERVER['PHP_SELF'])."/"; ?>" />
<!-- Fichier JS de configuration spécifique à l'application -->
<script type="text/javascript" language="javascript" src="config/config.js"></script>
<script type="text/javascript" language="javascript" src="config/apropos.js"></script>
<!-- Le script ci-dessous charger vos modules compilés. Ajoutez les méta-tags GWT avant cette ligne. -->
<script type="text/javascript" language="javascript" src="del/del.nocache.js"></script>
<link type="text/css" rel="stylesheet" href="del.css">
</head>
<!-- Le corps peut contenir du HTML ou peut rester vide si vous voulez créer une UI complêtement dynamique -->
<body>
<noscript>
<p style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
<span class="attention">ATTENTION : </span>
il semblerait que le Javascript ne soit pas activé sur votre navigateur.
Veuillez l'activer pour utiliser cette application.
</p>
</noscript>
<div id="zoneEntete">
</div>
<div id="main">
<div id="zoneTitre"></div>
<div id="zoneLiens"></div>
</div>
<div id="contenu"></div>
<!-- OPTIONAL: inclure la ligne ci-dessous si vous utilisez le supprot de l'historique du navigateur -->
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
<div id="zoneFooter"><br /><hr />
<span class="pictoplante-contact">
Vous avez remarqué un bug ou voulez nous suggérer des améliorations? Contactez-nous à
<a href="mailto:pictoflora_remarques@tela-botanica.org">pictoflora_remarques@tela-botanica.org</a>
</span><br/><br/>
Projet financ&eacute; par : <br /><br />
<a class="logo_ue" href="http://europa.eu/index_fr.htm" target="_blank"></a>
<a class="logo_lr" href="http://www.laregion.fr/" target="_blank"></a>
<a class="logo_nd" href="http://www.fondation-natureetdecouvertes.com/" target="_blank"></a>
<a class="logo_nh" href="http://www.fondation-nicolas-hulot.org/" target="_blank"></a>
</div>
</body>
</html>
/tags/v1.1-helium/war
New file
Property changes:
Added: svn:ignore
+WEB-INF
+del
/tags/v1.1-helium
New file
Property changes:
Added: svn:mergeinfo
Merged /branches/v1.0-hydrogene:r1507
Added: svn:ignore
+local.properties
+.settings
+.classpath
+.project
+gwt-unitCache
+DelTestSuite.launch
+www-test
+server.properties
+.buildpath