Subversion Repositories eFlore/Applications.del

Compare Revisions

Ignore whitespace Rev 1890 → Rev 1891

/tags/v1.5-carbone/services/modules/0.1/Images.php
New file
0,0 → 1,227
<?php
// declare(encoding='UTF-8');
/**
* Classe principale de chargement des sous-services "images" de DEL.
*
* Cette classe se charge toujours de :
* - vérifier l'existance des ressources (services) demandés
* - vérifier la cohérence et le format des paramêtres passées dans l'url
* En fonction, de la compléxité du service, elle peut :
* - dans un premier temps, exécuter directement les actions : consulter, ajouter, modifier, supprimer.
* - dans un second temps, charger dynamiquement d'éventuelles sous-classes du service en fonction des ressources présentes dans l'URL.
*
* URLs possibles :
* GET :
* http://localhost/del/services/0.1/images/ => toutes les images : classe ListeImages
* http://localhost/del/services/0.1/images/#idImg/votes => tous les votes d'une image (#idImg) classés par protocole : classe VotesImage
*
* Non Implémenté : http://localhost/del/services/0.1/images/#id => une image donnée => en test pour remplacer les appels à eflore/cel
* Non Implémenté : http://localhost/del/services/0.1/images/#id/votes?protocole=#id => tous les votes d'une image et d'un protocole donné
*
* PUT :
* http://localhost/del/services/0.1/images/#idImg => ajouter un vote sur une image donnée (#idImg)
*
* POST :
* http://localhost/del/services/0.1/images/#idImg => modifier un vote sur une image donnée (#idImg)
*
* DELETE :
* http://localhost/del/services/0.1/images/#idImg => supprimer une image donnée (#idImg)
* http://localhost/del/services/0.1/images/#idImg/votes/#idVote => supprimer un vote (#idVote) d'une image donnée (#idImg)
*
* @category DEL
* @package Services
* @subpackage Images
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
restore_error_handler();
restore_exception_handler();
error_reporting(E_ALL);
 
class Images extends RestService {
 
private $conteneur;
private $cheminCourant;
private $parametres = array();
private $ressources = array();
private $methode;
private $serviceNom = 'images';
private $sousServiceNom;
 
/** Indique si oui (true) ou non (false), on veut utiliser les paramètres bruts. */
protected $utilisationParametresBruts = true;
 
public function __construct() {
$this->conteneur = new Conteneur();
$this->cheminCourant = dirname(__FILE__).DS;
}
 
public function consulter($ressources, $parametres) {
$this->methode = 'consulter';
$this->initialiserRessourcesEtParametres($ressources, $parametres);
return $this->executerService();
}
 
public function ajouter($ressources, $requeteDonnees) {
$this->methode = 'ajouter';
$this->initialiserRessourcesEtParametres($ressources, $requeteDonnees);
return $this->executerService();
}
 
public function modifier($ressources, $requeteDonnees) {
$this->methode = 'modifier';
$this->initialiserRessourcesEtParametres($ressources, $requeteDonnees);
return $this->executerService();
}
 
public function supprimer($ressources) {
$this->methode = 'supprimer';
$this->initialiserRessourcesEtParametres($ressources);
return $this->executerService();
}
 
private function initialiserRessourcesEtParametres($ressources, $parametres = array()) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function executerService() {
$resultat = $this->traiterRessources();
if ($resultat === true || $resultat === false) {
return $resultat;
}
 
$reponseHttp = new ReponseHttp();
$reponseHttp->setResultatService($resultat);
$reponseHttp->emettreLesEntetes();
return $reponseHttp->getCorps();
}
 
private function traiterRessources() {
$this->analyserRessources();
$retour = $this->initialiserService();
return $retour;
}
 
private function analyserRessources() {
if ($this->methode == 'consulter') {
$this->analyserRessoucesConsultation();
} else if ($this->methode == 'modifier' || $this->methode == 'ajouter') {
$this->analyserRessoucesModification();
} else if ($this->methode == 'supprimer') {
$this->analyserRessoucesSuppression();
}
if ($this->sousServiceNom == null) {
$this->lancerMessageErreurRessource();
}
}
 
private function analyserRessoucesConsultation() {
if (count($this->ressources) == 0) {
$this->sousServiceNom = 'liste-images';
} else if (count($this->ressources) == 2) {
if ($this->etreRessourceIdentifiant(0) && $this->verifierRessourceValeur(1, 'votes')) {
$this->sousServiceNom = 'votes-image';
}
}
}
 
private function analyserRessoucesModification() {
if (count($this->ressources) == 2) {
if ($this->etreRessourceIdentifiant(0) && $this->verifierRessourceValeur(1, 'votes')) {
$this->sousServiceNom = 'votes-image';
}
}
}
 
private function analyserRessoucesSuppression() {
if (count($this->ressources) == 1 && $this->etreRessourceIdentifiant(0)) {
$this->sousServiceNom = 'liste-images';
} else if (count($this->ressources) == 3) {
if ($this->etreRessourceIdentifiant(0) && $this->verifierRessourceValeur(1, 'votes') && $this->etreRessourceIdentifiant(2) ) {
$this->sousServiceNom = 'votes-image';
}
}
}
 
private function etreRessourceIdentifiant($num) {
$presenceId = false;
if (isset($this->ressources[$num]) && is_numeric($this->ressources[$num])) {
$presenceId = true;
}
return $presenceId;
}
 
private function verifierRessourceValeur($num, $valeur) {
$ok = false;
if (isset($this->ressources[$num]) && $this->ressources[$num] == $valeur) {
$ok = true;
}
return $ok;
}
 
private function lancerMessageErreurRessource() {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
$message = "La ressource demandée '$ressource' ".
"n'est pas disponible pour le service ".$this->serviceNom." !\n".
$this->getDoc();
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
 
public function getDoc() {
return "Les URLs disponibles sont : \n".
" * en GET : \n".
" - images => toutes les images\n".
" - images/#idImg/votes => tous les votes d'une image (#idImg) classés par protocole\n".
" * en PUT : \n".
" - /images/#idImg/votes => ajouter un vote sur une image donnée (#idImg)\n".
" * en POST : \n".
" - /images/#idImg/votes => modifier un vote sur une image donnée (#idImg)\n".
" * en DELETE : \n".
" - /images/#idImg => supprimer une image donnée (#idImg)\n".
" - /images/#idImg/votes/#idVote => supprimer un vote (#idVote) d'une image donnée (#idImg)";
}
 
private function initialiserService() {
$classe = $this->obtenirNomClasseService($this->sousServiceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->serviceNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
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)) {
$ressource = implode('/', $this->ressources);
$msg = "Le classe '$classe' correspondant à la ressource '$ressource' ".
"n'existe pas dans le service '{$this->serviceNom}' !\n".$this->getDoc();
throw new Exception($msg, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
}
return $retour;
}
 
private function obtenirNomClasseService($mot) {
$classeNom = str_replace(' ', '', ucwords(strtolower(str_replace('-', ' ', $mot))));
return $classeNom;
}
}
/tags/v1.5-carbone/services/modules/0.1/utilisateurs/Deconnecter.php
New file
0,0 → 1,33
<?php
// declare(encoding='UTF-8');
/**
* Permet de déconnecter un utilisateur de DEL.
*
* @category DEL
* @package Services
* @subpackage Utilisateurs
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
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
return $this->getUtilisateurAnonyme();
}
}
/tags/v1.5-carbone/services/modules/0.1/utilisateurs/Identification.php
New file
0,0 → 1,38
<?php
// declare(encoding='UTF-8');
/**
* Permt de gérer "l'identification" anonyme.
*
* @category DEL
* @package Services
* @subpackage Utilisateurs
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
class Identification 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->getUtilisateurIdentifie();
if ($utilisateur != null) {
$utilisateur['connecte'] = true;
} else {
$utilisateur = $this->getUtilisateurAnonyme();
}
 
$resultat = new ResultatService();
$resultat->corps = $utilisateur;
return $resultat;
}
}
/tags/v1.5-carbone/services/modules/0.1/utilisateurs/Connecter.php
New file
0,0 → 1,47
<?php
// declare(encoding='UTF-8');
/**
* Permet de connecter un utilisateur à DEL.
*
* @category DEL
* @package Services
* @subpackage Utilisateurs
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
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);
$this->verifierUtilisateur($utilisateur);
$utilisateur = $this->completerInfosUtilisateur($utilisateur);
$this->poserCookieUtilisateur($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 == false) {
$msg = "Accès non autorisé";
throw new Exception($msg, RestServeur::HTTP_CODE_ACCES_NON_AUTORISE);
}
}
}
/tags/v1.5-carbone/services/modules/0.1/utilisateurs/Preferences.php
New file
0,0 → 1,108
<?php
// declare(encoding='UTF-8');
/**
* Permet la gestion des préférences utilisateur.
*
* @category DEL
* @package Services
* @subpackage Utilisateurs
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
 
class Preferences {
 
private $conteneur;
private $bdd;
 
public function __construct(Conteneur $conteneur) {
session_start();
$this->conteneur = $conteneur;
$this->bdd = $this->conteneur->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];
 
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
$resultat->corps = $this->obtenirPreferencesUtilisateur($id_utilisateur);
return $resultat;
}
 
private function obtenirPreferencesUtilisateur($id_utilisateur) {
$requete = 'SELECT * '.
'FROM del_utilisateur_infos '.
'WHERE id_utilisateur = '.$this->bdd->proteger($id_utilisateur).' '.
' -- '.__FILE__.' : '.__LINE__;
$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 initialiserInfosUtilisateur($id_utilisateur) {
$preferences_defaut = $this->obtenirTableauPreferenceDefaut();
$prefsEncodeesP = $this->bdd->proteger(json_encode($preferences_defaut));
$idUtilisateurP = $this->bdd->proteger($id_utilisateur);
$requete = 'INSERT INTO del_utilisateur_infos '.
'(id_utilisateur, admin, preferences, date_premiere_utilisation )'.
"VALUES ($idUtilisateurP, 0, $prefsEncodeesP, NOW()) ".
'ON DUPLICATE KEY UPDATE date_premiere_utilisation = NOW() '.
' -- '.__FILE__.' : '.__LINE__;
return $this->bdd->executer($requete);
}
 
private function obtenirTableauPreferenceDefaut() {
return array('mail_notification_mes_obs' => '1', 'mail_notification_toutes_obs' => '0');
}
 
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'));
}
 
/**
* 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 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).' '.
' -- '.__FILE__.' : '.__LINE__;
$resultat = $this->bdd->executer($requete);
return $resultat;
}
}
/tags/v1.5-carbone/services/modules/0.1/Nomstaxons.php
New file
0,0 → 1,135
<?php
// declare(encoding='UTF-8');
/**
* Classe principale de chargement des sous-services Noms et Taxons utilisés par DEL.
*
* @category DEL
* @package Services
* @subpackage NomsTaxons
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
class Nomstaxons extends RestService {
 
private $parametres = array();
private $ressources = array();
private $methode = null;
private $serviceNom = 'nomstaxons';
private $sousServiceNom = null;
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';
$this->initialiserRessourcesEtParametres($ressources, $parametres);
return $this->executerService();
}
 
private function initialiserRessourcesEtParametres($ressources, $parametres = array()) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function executerService() {
$reponseHttp = new ReponseHttp();
try {
$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 traiterRessources() {
$this->analyserRessources();
$retour = $this->initialiserService();
return $retour;
}
 
private function analyserRessources() {
if ($this->methode == 'consulter') {
if (count($this->ressources) == 0
&& $this->verifierPresenceParametre('masque.nom')
&& $this->verifierPresenceParametre('masque.referentiel')) {
$this->sousServiceNom = 'liste-taxons';
}
}
if ($this->sousServiceNom == null) {
$this->lancerMessageErreurRessource();
}
}
 
private function verifierPresenceParametre($cle) {
if (isset($this->parametres[$cle]) && trim($this->parametres[$cle]) == '') {
$message = "Le service demandé '{$this->serviceNom}' ".
"nécessite l'utilisation de paramètres (non vide) : masque.nom & masque.referentiel\n";
throw new Exception($message, RestServeur::HTTP_CODE_ECHEC_CONDITION);
}
return true;
}
 
private function lancerMessageErreurRessource() {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
$message = "La ressource demandée '$ressource' ".
"n'est pas disponible pour le service ".$this->serviceNom." !\n".
"Les URLs disponibles sont : \n".
" - en GET : nomstaxons (paramètres : masque.nom & masque.referentiel) \n";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
 
private function initialiserService() {
$classe = $this->obtenirNomClasseService($this->sousServiceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->serviceNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
 
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
require_once $chemin;
$service = new $classe($this->conteneur);
if ($this->methode == 'consulter') {
$retour = $service->consulter();
} else {
$message = "Le sous-service '{$this->sousServiceNom}' du service '{$this->serviceNom}' ".
"ne possède pas de méthode '{$this->methode}' !";
$code = RestServeur::HTTP_NON_IMPLEMENTE;
throw new Exception($message, $code);
}
}
}
 
if (is_null($service)) {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
$message = "Le classe '$classe' correspondant à la ressource '$ressource' ".
"est introuvable par le service '{$this->serviceNom}' !";
$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.5-carbone/services/modules/0.1/statistiques/StatistiquesParAnnee.php
New file
0,0 → 1,302
<?php
/**
* Statistiques par année sur l'utilisation de Identiplante / Pictoflora
*
* @see Documentation : <http://www.tela-botanica.org/wikini/DevInformatiques/wakka.php?wiki=AppliDelStats>
*
* @category DEL
* @package Services
* @subpackage Statistiques
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
class StatistiquesParAnnee {
 
private $conteneur;
private $contexte;
private $navigation;
private $bdd;
 
private $annee = null;
private $type = 'tout';
private $methode = '';
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->contexte = $conteneur->getContexte();
$this->navigation = $conteneur->getNavigation();
$this->bdd = $this->conteneur->getBdd();
}
 
public function consulter() {
$this->intitialiserParametresEtRessources();
$this->verifierPreRequis();
 
$resultat = new ResultatService();
$resultat->corps = call_user_func(array($this, $this->methode));
return $resultat;
}
 
private function intitialiserParametresEtRessources() {
$this->type = $this->contexte->getRessource(2) != null ? $this->contexte->getRessource(2) : $this->type;
$this->methode = $this->obtenirNomMethode($this->type);
$this->annee =(int) $this->contexte->getQS('annee') != null ? intval($this->contexte->getQS('annee')) : null;
}
 
private function verifierPreRequis() {
$erreurs = array();
 
if ($this->annee != null && !is_int($this->annee)) {
$erreurs[] = "Le paramètre 'annee' doit être un entier.";
}
 
if (method_exists($this, $this->obtenirNomMethode($this->type)) === false) {
$erreurs[] = "Les stats de type '{$this->type}' n'existent pas.";
}
 
if (!empty($erreurs)) {
$msg = "Erreur de configuration :\n".implode("\n", $erreurs)."\n\n".Statistiques::getDoc();
throw new Exception($msg, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
}
}
 
private function obtenirNomMethode($mot) {
$classeNom = 'get'.str_replace(' ', '', ucwords(strtolower(str_replace('-', ' ', $mot))));
return $classeNom;
}
 
// retourne toutes les stats pour l'année spécifiée
private function getTout() {
$obsIdentifieesFinAnneePlus = $this->getPourcentageObsIdentifieesFinAnneePlus();
$participants = $this->getParticipants();
 
return array(
'annee' => $this->annee,
'moyenneObsSansNomParMois' => $this->getMoyenneObsSansNomParMois(),
'moyenneObsIdentifieesParMois' => $this->getMoyenneObsIdentifieesParMois(),
'pourcentageObsIdentifieesEnFinDAnnee' => $this->getPourcentageObsIdentifieesFinAnnee(),
'pourcentageObsIdentifieesEnFinDAnneePlusPlus' => $obsIdentifieesFinAnneePlus['pourcentage'],
'moyenneActionsParJour' => $this->getMoyenneActionsParJour(),
'personnesEnvoyantUnePropositionParMois' => $participants['nombre']
);
}
 
// proxy pour le widget de stats
private function getObservations() {
return $this->getTout();
}
 
// Retourne le nombre moyen d'observations non identifiées envoyées par mois, pour l'année $annee
private function getMoyenneObsSansNomParMois() {
$sqlTableTmp = "SELECT COUNT(*) AS compte, ".
" CONCAT(YEAR(date_transmission),'-',MONTH(date_transmission)) AS anneemois ".
"FROM del_observation ".
"WHERE (mots_cles_texte LIKE '%aDeterminer%' ".
"OR certitude = 'aDeterminer' ".
"OR certitude = 'douteux' ".
// Obs n'ayant pas de nom_sel_nn (détermination non choisie parmi le référentiel)
"OR nom_sel_nn IS NULL ".
"OR nom_sel_nn = 0 ".
"OR id_observation IN ({$this->getSqlObsSansNom()}) ".
') '.
(($this->annee !== null) ? "AND YEAR(date_transmission) = '{$this->annee}' " : '').
'GROUP BY anneemois '.
'ORDER BY anneemois DESC ';
 
$requete = "SELECT AVG(parMois.compte) AS moyenne FROM ($sqlTableTmp) AS parMois ".
' -- '.__FILE__.' : '.__LINE__;
$resultat = $this->bdd->recupererTous($requete);
return intval($resultat[0]['moyenne']);
}
 
private function getSqlObsSansNom() {
$sqlObsSansNom = "SELECT DISTINCT ce_observation ".
"FROM del_commentaire ".
"WHERE proposition_initiale = 1 ".
"AND (nom_sel_nn IS NULL OR nom_sel_nn = '') ";
return $sqlObsSansNom;
}
 
// Retourne la moyenne par mois sur l'année en cours, des propositions marquées comme "retenues"
// dont le dernier vote est dans l'année considérée (comptées en groupant par mois du dernier vote)
private function getMoyenneObsIdentifieesParMois() {
// Compte et date du dernier vote des propositions marquées comme "retenues"
$sqlTableTmp1 = "SELECT COUNT(*), MAX(dcv.date) AS maxdate ".
"FROM del_commentaire AS dc ".
" LEFT JOIN del_commentaire_vote dcv ON dcv.ce_proposition = dc.id_commentaire ".
" WHERE proposition_retenue = 1 ".
" GROUP BY dc.id_commentaire ".
(($this->annee !== null) ? "HAVING MAX(YEAR(dcv.date)) = '{$this->annee}' " : '');
 
$sqlTableTmp2 = 'SELECT COUNT(*) AS valideesparmois, '.
" CONCAT(YEAR(maxdate), '-', MONTH(maxdate)) AS anneemois ".
"FROM ($sqlTableTmp1) AS temp ".
"GROUP BY anneemois ";
 
$requete = "SELECT AVG(valideesparmois) AS moyenne FROM ($sqlTableTmp2) AS temp2 ".
' -- '.__FILE__.' : '.__LINE__;
 
$resultat = $this->bdd->recupererTous($requete);
return intval($resultat[0]['moyenne']);
}
 
// Version améliorée mais non optimale (prend en compte les consensus non validés)
// @TODO on devrait croiser les IDS pour ne pas prendre en compte les obs validées ou en
// consensus, mais qui datent des années précédentes
// @ACHTUNG mache pas, dépasse les 100% (voir Wiki)
private function getPourcentageObsIdentifieesFinAnneePlus() {
// Obs ayant atteint un consensus cette année
$requete = "SELECT COUNT(*) AS nombre ".
"FROM (SELECT id_observation, id_commentaire, id_vote, nbvotes ".
"FROM (SELECT do.id_observation, dc.id_commentaire, dcv.id_vote, COUNT(dcv.id_vote) AS nbvotes ".
"FROM del_commentaire AS dc ".
" LEFT JOIN del_observation AS do ON (do.id_observation = dc.ce_observation) ".
" LEFT JOIN del_commentaire_vote AS dcv ON (dc.id_commentaire = dcv.ce_proposition) ".
"AND dcv.valeur = 1 ".
"AND dc.proposition_retenue = 0 ".
"GROUP BY dc.id_commentaire ".
(($this->annee != null) ? " HAVING MAX(YEAR(dcv.date)) = '{$this->annee}' " : '').
" ) AS temp ".
"GROUP BY id_observation ".
") AS temp2 ".
' -- '.__FILE__.' : '.__LINE__;
$obsEnConsensus = $this->bdd->recupererTous($requete);
$oc = intval($obsEnConsensus[0]['nombre']);
 
// Obs ayant une "proposition retenue" cette année
$requete = "SELECT COUNT(*) AS nombre ".
"FROM (SELECT COUNT(DISTINCT id_observation), MAX(dcv.date) AS maxdate ".
"FROM del_commentaire AS dc ".
" LEFT JOIN del_commentaire_vote AS dcv ON (dcv.ce_proposition = dc.id_commentaire) ".
" LEFT JOIN del_observation AS do ON (do.id_observation = dc.ce_observation) ".
"WHERE proposition_retenue = 1 ".
(($this->annee != null) ? "AND YEAR(do.date_transmission) = '{$this->annee}' " : '').
"GROUP BY dc.id_commentaire ".
(($this->annee != null) ? "HAVING MAX(YEAR(dcv.date)) = '{$this->annee}' " : '').
") as temp ".
' -- '.__FILE__.' : '.__LINE__;
$nbObsValidees = $this->bdd->recupererTous($requete);
$ov = intval($nbObsValidees[0]['nombre']);
 
// Nombre d'obs sans nom soumises cette année
$requete = "SELECT COUNT(*) AS nombre ".
"FROM del_observation ".
"WHERE (mots_cles_texte LIKE '%aDeterminer%' ".
"OR certitude = 'aDeterminer' ".
"OR certitude = 'douteux' ".
"OR nom_sel_nn IS NULL ".
"OR nom_sel_nn = 0 ".
"OR id_observation IN ({$this->getSqlObsSansNom()})".
') '.
(($this->annee != null) ? "AND YEAR(date_transmission) = '{$this->annee}' " : '').
' -- '.__FILE__.' : '.__LINE__;
$nbObsSansNom = $this->bdd->recupererTous($requete);
$osn = intval($nbObsSansNom[0]['nombre']);
 
return array(
'observationsEnConsensus' => $oc,
'observationsValidees' => $ov,
'observationsSansNom' => $osn,
'pourcentage' => ($osn == 0 ? 0 : round(((($oc + $ov) / $osn) * 100), 2))
);
}
 
private function getPourcentageObsIdentifieesFinAnnee() {
$requete = "SELECT ( ".
"SELECT COUNT(*) FROM ( ".
"SELECT COUNT(DISTINCT id_observation), MAX(dcv.date) AS maxdate ".
"FROM del_commentaire AS dc ".
" LEFT JOIN del_commentaire_vote AS dcv ON (dcv.ce_proposition = dc.id_commentaire) ".
" LEFT JOIN del_observation AS do ON (do.id_observation = dc.ce_observation) ".
"WHERE proposition_retenue = 1 ".
(($this->annee != null) ? "AND YEAR(do.date_transmission) = '{$this->annee}' " : '').
"GROUP BY dc.id_commentaire ".
(($this->annee != null) ? "HAVING MAX(YEAR(dcv.date)) = '{$this->annee}' " : '').
") AS temp)".
" / ".
"(SELECT COUNT(*) ".
"FROM del_observation ".
"WHERE (mots_cles_texte LIKE '%aDeterminer%' ".
"OR certitude = 'aDeterminer' ".
"OR certitude = 'douteux' ".
"OR nom_sel_nn IS NULL ".
"OR nom_sel_nn = 0 ".
"OR id_observation IN ( ".
"SELECT DISTINCT ce_observation ".
"FROM del_commentaire ".
"WHERE proposition_initiale = 1 ".
"AND (nom_sel_nn IS NULL OR nom_sel_nn = '') ".
") ".
") ".
(($this->annee != null) ? "AND YEAR(date_transmission) = '{$this->annee}' " : '').
") * 100 AS pourcentage ".
' -- '.__FILE__.' : '.__LINE__;
$resultat = $this->bdd->recupererTous($requete);
return floatval($resultat[0]['pourcentage']);
}
 
// Retourne la moyenne sur l'année du nombre d'actions (commentaire ou vote) par jour
private function getMoyenneActionsParJour() {
// nombre de commentaires sur l'année
$sqlNbreCommentaires = 'SELECT COUNT(*) FROM del_commentaire '.
($this->annee != null ? "WHERE YEAR(date) = '{$this->annee}' " : '');
 
// nombre de votes sur l'année
$sqlNbreVotes = 'SELECT COUNT(*) FROM del_commentaire_vote '.
($this->annee != null ? "WHERE YEAR(date) = '{$this->annee}' " : '');
 
// nombre de jours écoulés dans l'année*
$sqlNbreJours = "SELECT 365 * (YEAR(now()) - MIN(YEAR(date)) + 1) FROM del_commentaire_vote WHERE YEAR(date) != 0 ";
if ($this->annee != null) {
$sqlNbreJours = "SELECT IF(YEAR(CURDATE()) = '{$this->annee}', DAYOFYEAR(CURDATE()), 365) ";
}
 
// nombre d'actions / nombre de jours
$requete = "SELECT ((($sqlNbreCommentaires) + ($sqlNbreVotes)) / ($sqlNbreJours)) AS moyenne ".
' -- '.__FILE__.' : '.__LINE__;
 
$resultat = $this->bdd->recupererTous($requete);
return intval($resultat[0]['moyenne']);
}
 
// Retourne le nombre et la liste des personnes ayant sur l'année une moyenne de participation par mois >= 1
private function getParticipants() {
// Faire la moyenne par utilisateur et par mois
$requete = "SELECT cal.nbmois, SUM(somme) / cal.nbmois as moyenne, ce_utilisateur, utilisateur_courriel ".
"FROM ".
// Compter le nombre de participations pour chaque utilisateur à chaque mois de cette année
"(SELECT COUNT(*) as somme, CONCAT(YEAR(date),'-',MONTH(date)) AS anneemois, ".
"ce_utilisateur, utilisateur_courriel, id_commentaire ".
"FROM del_commentaire ".
"WHERE ce_proposition = '' ".
"AND nom_sel_nn != '' ".
"AND nom_sel_nn IS NOT NULL ".
(($this->annee != null) ? " AND YEAR(date) = '{$this->annee}' " : '').
"GROUP BY anneemois, ce_utilisateur, utilisateur_courriel) AS ppm, ".
// Trouver le nombre de mois différents lors desquels les utilisateurs ont participé, cette année
// Pour l'année en cours par ex, retournera 2 si on est en février (voire un au début du mois).
"(SELECT COUNT(distinct CONCAT(YEAR(date),'-',MONTH(date))) AS nbmois ".
"FROM del_commentaire ".
"WHERE ce_proposition = '' ".
(($this->annee != null) ? "AND YEAR(date) = '{$this->annee}' " : '').
"AND nom_sel_nn != '' ".
"AND nom_sel_nn IS NOT NULL) AS cal ".
"GROUP BY ce_utilisateur, utilisateur_courriel ".
"HAVING SUM(somme) / cal.nbmois >= 1 ".
"ORDER BY moyenne ".
' -- '.__FILE__.' : '.__LINE__;
 
$resultat = $this->bdd->recupererTous($requete);
$cpt = count($resultat);
$retour = array(
'nombre' => intval($cpt),
'donnees' => $resultat
);
return $retour;
}
}
/tags/v1.5-carbone/services/modules/0.1/Observations.php
New file
0,0 → 1,227
<?php
// declare(encoding='UTF-8');
/**
* Classe principale de chargement des services Observations.
*
* URLs possibles :
* GET :
* http://localhost/service:del:0.1/observations
* toutes les observations (infos obs, infos images, infos propositions, infos nb commentaires)
*
* http://localhost/service:del:0.1/observations?retour.format=widget
* toutes les infos des observations pour le Widget DEL
*
* http://localhost/service:del:0.1/observations/#idObs
* une observation donnée et ses images, SANS LES propositions & nombre de commentaire*
*
* http://localhost/service:del:0.1/observations/#idObs/#idVote/vote
* toutes les infos sur les votes d'une proposition
*
* PUT :
* http://localhost/service:del:0.1/observations/#idObs/#idCommentaire/vote
* ajoute un vote (+ ou -) pour une obs et une proposition donnée
*
* POST :
* http://localhost/service:del:0.1/observations/#idObs
* utilisé seulement par les admins pour modifier une obs depuis DEL (dépublication des obs)
*
* http://localhost/service:del:0.1/observations/#idObs/#idCommentaire/vote
* modifie un vote (+ ou -) pour une obs et une proposition donnée
*
* @category DEL
* @package Services
* @subpackage Observations
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
 
class Observations extends RestService {
 
private $parametres = array();
private $ressources = array();
private $methode = null;
private $serviceNom = 'observations';
private $sousServiceNom = null;
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';
$this->initialiserRessourcesEtParametres($ressources, $parametres);
return $this->executerService();
}
 
public function ajouter($ressources, $requeteDonnees) {
$this->methode = 'ajouter';
$this->initialiserRessourcesEtParametres($ressources, $requeteDonnees);
return $this->executerService();
}
 
public function modifier($ressources, $requeteDonnees) {
$this->methode = 'modifier';
$this->initialiserRessourcesEtParametres($ressources, $requeteDonnees);
return $this->executerService();
}
 
private function executerService() {
$reponseHttp = new ReponseHttp();
try {
$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 = array()) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function traiterRessources() {
$this->analyserRessources();
$retour = $this->initialiserService();
return $retour;
}
 
private function analyserRessources() {
if ($this->methode == 'consulter') {
$this->analyserRessoucesConsultation();
} else if ($this->methode == 'modifier' || $this->methode == 'ajouter') {
$this->analyserRessoucesModification();
}
}
 
private function analyserRessoucesConsultation() {
if (count($this->ressources) == 0) {
// http://localhost/service:del:0.1/observations
$this->sousServiceNom = 'liste-observations';
} else if (count($this->ressources) == 1) {
if ($this->etreRessourceIdentifiant(0)) {
// http://localhost/service:del:0.1/observations/#idObs
$this->sousServiceNom = 'observation-details';
}
} else if (count($this->ressources) == 3) {
if ($this->etreRessourceIdentifiant(0) && $this->etreRessourceIdentifiant(1) && $this->verifierRessourceValeur(2, 'vote')) {
// http://localhost/service:del:0.1/observations/#idObs/#idProposition/vote/
$this->sousServiceNom = 'vote-observation';
}
}
 
if ($this->sousServiceNom == null) {
$this->lancerMessageErreurRessource();
}
}
 
private function analyserRessoucesModification() {
if (count($this->ressources) == 1) {
if ($this->methode == 'modifier' && $this->etreRessourceIdentifiant(0)) {
// http://localhost/service:del:0.1/observations/#idObs
$this->sousServiceNom = 'observation-details';
}
} else if (count($this->ressources) == 3) {
if ($this->etreRessourceIdentifiant(0) && $this->etreRessourceIdentifiant(1) && $this->verifierRessourceValeur(2, 'vote')) {
// http://localhost/service:del:0.1/observations/#idObs/#idProposition/vote/
$this->sousServiceNom = 'vote-observation';
}
}
 
if ($this->sousServiceNom == null) {
$this->lancerMessageErreurRessource();
}
}
 
private function etreRessourceIdentifiant($num) {
$presenceId = false;
if (isset($this->ressources[$num]) && is_numeric($this->ressources[$num])) {
$presenceId = true;
}
return $presenceId;
}
 
private function verifierRessourceValeur($num, $valeur) {
$ok = false;
if (isset($this->ressources[$num]) && $this->ressources[$num] == $valeur) {
$ok = true;
}
return $ok;
}
 
private function verifierParametreValeur($cle, $valeur) {
$ok = false;
if (isset($this->parametres[$cle]) && $this->ressources[$cle] == $valeur) {
$ok = true;
}
return $ok;
}
 
private function lancerMessageErreurRessource() {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
$message = "La ressource demandée '$ressource' ".
"n'est pas disponible pour le service ".$this->serviceNom." !\n".
"Les URLs disponibles sont : \n".
" - en GET : observations, observations/#idObs/#idProposition/vote \n".
" - en POST : observations/#id, observations/#idObs/#idProposition/vote \n".
" - en PUT : observations/#idObs/#idProposition/vote \n";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
 
private function initialiserService() {
$classe = $this->obtenirNomClasseService($this->sousServiceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->serviceNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
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);
} else {
$message = "Le sous-service '{$this->sousServiceNom}' du service '{$this->serviceNom}' ".
"ne possède pas de méthode '{$this->methode}' !";
$code = RestServeur::HTTP_NON_IMPLEMENTE;
throw new Exception($message, $code);
}
}
}
 
if (is_null($service)) {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
$message = "Le classe '$classe' correspondant à la ressource '$ressource' ".
"n'existe pas dans le service '{$this->serviceNom}' !";
$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.5-carbone/services/modules/0.1/images/VotesImage.php
New file
0,0 → 1,270
<?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 DEL
* @package Services
* @subpackage Images
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
 
class VotesImage {
 
private $conteneur;
private $navigation;
private $bdd;
private $mapping = array();
private $ressources;
private $parametres;
 
public function __construct(Conteneur $conteneur) {
$this->conteneur = $conteneur;
$this->navigation = $conteneur->getNavigation();
$this->bdd = $this->conteneur->getBdd();
 
$this->mapping = $this->conteneur->getParametreTableau('votes.mapping');
}
 
/**
* 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->ressources = $ressources;
$this->parametres = $parametres;
 
// 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->navigation->getEntete(), 'resultats' => $votes);
return $resultat;
}
 
private function chargerVotes() {
$idImgP = $this->bdd->proteger($this->ressources[0]);
$idProtocoleP = isset($this->parametres['protocole']) ? $this->bdd->proteger($this->parametres['protocole']) : null;
$requete = 'SELECT * FROM del_image_vote '.
"WHERE ce_image = $idImgP ".
($idProtocoleP != null ? "AND ce_protocole = $idProtocoleP " : '').
' -- '.__FILE__.' : '.__LINE__;
$resultats = $this->bdd->recupererTous($requete);
return $this->formaterVotes($resultats);
}
 
private function compterVotes() {
$requete = 'SELECT FOUND_ROWS() AS nbre -- '.__FILE__.' : '.__LINE__;
$resultats = $this->bdd->recuperer($requete);
return (int) $resultats['nbre'];
}
 
private function formaterVotes($votes) {
$retour = array();
foreach ($votes as $vote) {
foreach ($vote as $champ => $valeur) {
$attribut = $this->mapping[$champ];
$retour[$vote['id_vote']][$attribut] = $valeur;
}
}
return $retour;
}
 
public function ajouter($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
 
$this->verifierParametresAjoutModif();
$idVote = $this->ajouterVote();
if ($idVote) {
self::updateStats($this->bdd, $this->ressources[0], $this->parametres['protocole']);
 
$resultat = new ResultatService();
$resultat->corps = array('id_vote' => $idVote);
return $resultat;
}
return false;
}
 
private function ajouterVote() {
$idImgP = $this->bdd->proteger($this->ressources[0]);
$idProtocoleP = $this->bdd->proteger($this->parametres['protocole']);
$idUtilisateurP = $this->bdd->proteger($this->parametres['utilisateur']);
$valeurP = $this->bdd->proteger($this->parametres['valeur']);
 
$requete = 'INSERT INTO del_image_vote (ce_image, ce_protocole, ce_utilisateur, valeur, date) '.
"VALUES ( $idImgP, $idProtocoleP, $idUtilisateurP, $valeurP, NOW()) ".
' -- '.__FILE__.' : '.__LINE__;
 
$resultat = $this->bdd->executer($requete);
if ($resultat === false) {
$msg = "Un problème est survenu lors de l'ajout d'un vote.";
throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
} else if ($resultat === 0) {
$msg = "Aucun vote ne correspond au critères fournis : ".
"idImg -> $idImgP, id_protocole -> $idProtocoleP et id_utilisateur -> $idUtilisateurP.";
throw new Exception($msg, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
}
// ATTENTION : idVote doit être récupéré avant toute nouvelle requete !
$idVote = $this->bdd->recupererIdDernierAjout();
return $idVote;
}
 
public function verifierParametresAjoutModif() {
$erreurs = array();
if (!is_numeric($this->ressources[0])) {
$erreurs[] = "Le paramètre indiquant l'identifiant de l'image doit être numérique.";
}
 
if (!isset($this->parametres['utilisateur'])) {
$erreurs[] = "Paramètre 'utilisateur' manquant.";
}
 
if (!isset($this->parametres['protocole'])) {
$erreurs[] = "Paramètre 'id_protocole' manquant.";
} else {
if (!is_numeric($this->parametres['protocole'])) {
$erreurs[] = "Le paramètre 'protocole' doit être numérique.";
}
}
 
if (!isset($this->parametres['valeur'])) {
$erreurs[] = "Paramètre 'valeur' manquant.";
} else {
if (!is_numeric($this->parametres['valeur'])) {
$erreurs[] = "Le paramètre 'valeur' doit être numérique.";
}
}
 
if (!empty($erreurs)) {
$msg = "Erreur lors de la configuration : \n".implode("\n", $erreurs);
throw new Exception($msg, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
}
}
 
public function modifier($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
$this->verifierParametresAjoutModif();
$resultat = $this->modifierVote();
if ($resultat > 0) {
self::updateStats($this->bdd, $this->ressources[0],$this->parametres['protocole']);
return 'ok';
}
}
 
public function modifierVote() {
$valeurP = $this->bdd->proteger($this->parametres['valeur']);
$idImgP = $this->bdd->proteger($this->ressources[0]);
$idProtocoleP = $this->bdd->proteger($this->parametres['protocole']);
$idUtilisateurP = $this->bdd->proteger($this->parametres['utilisateur']);
$requete = 'UPDATE del_image_vote '.
"SET valeur = $valeurP, date = NOW() ".
"WHERE ce_image = $idImgP AND ce_protocole = $idProtocoleP AND ce_utilisateur = $idUtilisateurP ".
' -- '.__FILE__.' : '.__LINE__;
 
$resultat = $this->bdd->executer($requete);
if ($resultat === false) {
$msg = "Un erreur est survenu lors de la tentative de modification du vote.";
throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
} else if ($resultat === 0) {
$msg = "Aucun vote ne correspond au critères fournis : ".
"idImg -> $idImgP, id_protocole -> $idProtocoleP et id_utilisateur -> $idUtilisateurP.";
throw new Exception($msg, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
}
return $resultat;
}
 
public function supprimer($ressources) {
$this->ressources = $ressources;
$this->verifierParametresSuppression();
$idVoteP = $this->bdd->proteger($this->ressources[2]);
 
$voteInfos = $this->recupererInfosVote($idVoteP);
$this->verifierAutorisationSuppression($voteInfos);
 
$resultat = $this->supprimerVote($idVoteP);
if ($resultat > 0) {
$idImg = $this->ressources[0];
self::updateStats($this->bdd, $idImg, $voteInfos['id_protocole']);
return 'ok';
}
}
 
public function verifierParametresSuppression() {
$erreurs = array();
if (!isset($this->ressources[0])) {
$erreurs[] = "Le paramètre indiquant l'identifiant de l'image est obligatoire.";
} else {
if (!is_numeric($this->ressources[0])) {
$erreurs[] = "Le paramètre indiquant l'identifiant de l'image doit être numérique.";
}
}
if (!isset($this->ressources[2])) {
$erreurs[] = "Le paramètre indiquant l'identifiant du vote est obligatoire.";
} else {
if (!is_numeric($this->ressources[2])) {
$erreurs[] = "Le paramètre indiquant l'identifiant du vote doit être numérique.";
}
}
 
if (!empty($erreurs)) {
$msg = 'Erreur lors de la configuration : '."\n".implode("\n", $erreurs);
throw new Exception($msg, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
}
}
 
private function recupererInfosVote($idVoteP) {
$requete = 'SELECT id_vote, ce_protocole AS id_protocole, ce_utilisateur AS id_utilisateur '.
'FROM del_image_vote '.
"WHERE id_vote = $idVoteP ".
' -- '.__FILE__.' : '.__LINE__;
 
$infos = $this->bdd->recuperer($requete);
if ($infos === false) {
$msg = "Aucun vote ne correspond à l'identifiant $idVoteP.";
throw new Exception($msg, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
}
return $infos;
}
 
private function verifierAutorisationSuppression($voteInfos) {
$controle_acces = $this->conteneur->getControleAcces();
$utilisateur = $controle_acces->getInfosUtilisateurConnecte();
 
if (isset($utilisateur['id_utilisateur']) &&
$utilisateur['id_utilisateur'] != $voteInfos['id_utilisateur'] &&
$controle_acces->getIdAnonymeTemporaire() != $voteInfos['id_utilisateur']) {
$message = "Vous n'êtes pas autorisé à supprimer le vote : {$voteInfos['id_vote']}";
throw new Exception($message, RestServeur::HTTP_CODE_ACCES_NON_AUTORISE);
}
}
 
private function supprimerVote($idVoteP) {
$requete = "DELETE FROM del_image_vote WHERE id_vote = $idVoteP ".' -- '.__FILE__.' : '.__LINE__;
$resultat = $this->bdd->executer($requete);
if ($resultat === false) {
$msg = "Impossible de supprimer le vote $idVoteP.";
throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
}
return $resultat;
}
 
// intermédiaire pour la méthode contenue dans "Commun"
static function updateStats($db, $id_image, $id_protocole) {
return TelaBotanica\Del\Commun\Stats::updateStats($db, $id_image, $id_protocole);
}
}
/tags/v1.5-carbone/services/modules/0.1/images/ListeImages.php
New file
0,0 → 1,163
<?php
// declare(encoding='UTF-8');
/**
* Listes des images avec leurs infos liées.
*
* 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
*
* @category DEL
* @package Services
* @subpackage Images
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
 
//restore_error_handler();
//restore_exception_handler();
//error_reporting(E_ALL);
class ListeImages {
 
private $conteneur;
private $bdd;
private $filtrage;
private $sql;
private $navigation;
private $paramsFiltres = array();
private $mappings = array();
private $idsImagesOrdonnees = array();
private $infosImages = array();
private $infosImagesOrdonnees = array();
 
public function __construct(Conteneur $conteneur) {
$this->conteneur = $conteneur;
$this->bdd = $this->conteneur->getBdd();
$this->filtrage = $this->conteneur->getParametresFiltrage();
$this->sql = $this->conteneur->getSql();
$this->navigation = $this->conteneur->getNavigation();
 
$this->mappings['observations'] = $this->conteneur->getParametreTableau('observations.mapping');
$this->mappings['images'] = $this->conteneur->getParametreTableau('images.mapping');
}
 
public function consulter($ressources, $parametres) {
$this->paramsFiltres = $this->filtrage->filtrerUrlParamsAppliImg();
$this->sql->setAppli(Sql::APPLI_IMG);
$this->sql->setParametres($this->paramsFiltres);
$this->sql->ajouterContraintes();
$this->sql->ajouterConstrainteAppliImg();
$this->sql->definirOrdreSqlAppliImg();
 
$this->idsImagesOrdonnees = $this->getIdImages();
$this->navigation->setTotal($this->sql->getTotalLignesTrouvees());
 
// Ce n'est pas la peine de continuer s'il n'y a pas eu de résultats
$resultat = new ResultatService();
$resultat->corps = array('entete' => $this->navigation->getEntete(), 'resultats' => array());
if (count($this->idsImagesOrdonnees) > 0) {
$this->infosImages = $this->getInfosImages();
$this->infosImagesOrdonnees = $this->formaterImages();
 
// Chargement des votes pour ces images et pour *tous* les protocoles
$votes = $this->sql->getVotesDesImages($this->idsImagesOrdonnees);
if ($votes) {
// ATTENTION : $images est récupéré par référence !
$this->sql->ajouterInfosVotesProtocoles($votes, $this->infosImagesOrdonnees);
}
 
$resultat->corps = array(
'entete' => $this->navigation->getEntete(),
'resultats' => array_values($this->infosImagesOrdonnees));
}
return $resultat;
}
 
private function getIdImages() {
$requete = 'SELECT SQL_CALC_FOUND_ROWS DISTINCT di.id_image '.
'FROM del_image AS di '.
$this->sql->getJoin().
'WHERE '.$this->sql->getWhere().
$this->sql->getGroupBy().
$this->sql->getOrderBy().
$this->sql->getLimit().
' -- '.__FILE__.':'.__LINE__;
// TODO : si le DISCTINCT dans la requête pose des pb de perf, supprimer les doublons d'id à l'aide de PHP
//Debug::printr($requete);
$resultats = $this->bdd->recupererTous($requete);
$idImgs = array();
if ($resultats !== false ) {
foreach ($resultats as $resultat) {
$idImgs[] = $resultat['id_image'];
}
}
return $idImgs;
}
 
private function getInfosImages() {
$obsChamps = $this->sql->getAliasDesChamps($this->mappings['observations'], null, 'do');
$imgChamps = $this->sql->getAliasDesChamps($this->mappings['images'], null, 'di');
$idImgsConcat = implode(',', $this->idsImagesOrdonnees);
 
$requete = "SELECT $obsChamps, $imgChamps ".
'FROM del_image AS di '.
' LEFT JOIN del_observation AS do ON (di.ce_observation = do.id_observation) '.
"WHERE di.id_image IN ($idImgsConcat) ".
'-- '.__FILE__.':'.__LINE__;
//Debug::printr($requete);
return $this->bdd->recupererTous($requete);
}
 
// cf Observation::reformateObservationSimpleIndex() et ListeObservations::reformateObservation()
// (trop de variétés de formatage, à unifier côté client pour unifier côté backend ...)
private function formaterImages() {
$urlImgTpl = $this->conteneur->getParametre('cel_img_url_tpl');
$imageFormat = isset($this->paramsFiltres['format']) ? $this->paramsFiltres['format'] : 'XL';
$obsFormatees = array_flip($this->idsImagesOrdonnees);// Permet de garder l'ordre de sortie !
foreach ($this->infosImages as $infos) {
$id = $infos['id_image'];
// 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' => $id,
'binaire.href' => sprintf($urlImgTpl, $infos['id_image'], $imageFormat),
'mots_cles_texte' => isset($infos['mots_cles_texte']) ? $infos['mots_cles_texte'] : null,
);
unset($infos['id_image'], $infos['mots_cles_texte']);
 
$obsFormatees[$id] = $image;
$obsFormatees[$id]['observation'] = $infos;
$obsFormatees[$id]['protocoles_votes'] = array();
}
return $obsFormatees;
}
 
/**
* Supprime une image directement dans le CEL en faisant un appel à un web service du CEL.
* Utilisé uniquement par les admins.
*
* @param array $ressources tableau des informations contenues dans l'url après le nom du service
* @param array $parametres contenu du post
* @return mixed Chaine "OK" (en majuscule) en cas de succès, booléen "false" en cas d'échec
*/
public function supprimer($ressources) {
$controlAcces = $this->conteneur->getControleAcces();
$controlAcces->etreUtilisateurAvecDroitAdmin();
 
$urlServiceBase = $this->conteneur->getParametre('urlServiceCelImage');
$idImage = $ressources[0];
$url = $urlServiceBase.$idImage;
 
$clientHttp = $this->conteneur->getRestClient();
$retourCel = $clientHttp->supprimer($url);
$retour = preg_match('/^OK$/i', $retourCel) ? 'OK' : false;
return $retour;
}
}
/tags/v1.5-carbone/services/modules/0.1/nomstaxons/ListeTaxons.php
New file
0,0 → 1,71
<?php
// declare(encoding='UTF-8');
/**
* Web service récupèrant une liste de noms de taxons suivant un référentiel et un masque donné.
*
* @category DEL
* @package Services
* @subpackage NomsTaxons
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
 
class ListeTaxons {
 
private $conteneur;
private $navigation;
private $bdd;
 
private $resultatsBruts = array();
private $resultats = array();
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->navigation = $this->conteneur->getNavigation();
$this->bdd = $this->conteneur->getBdd();
}
 
public function consulter() {
$this->chargerNoms();
$this->formaterResultats();
$this->mettreAJourEnteteResultats();
 
$resultat = new ResultatService();
$resultat->corps = array('entete' => $this->navigation->getEntete(), 'resultats' => $this->resultats);
return $resultat;
}
 
private function chargerNoms() {
$referentiel = $this->navigation->getFiltre('masque.referentiel');
if ($referentiel != 'tous') {
$requete = urlencode($this->navigation->getFiltre('masque.nom'));
$url = sprintf($this->conteneur->getParametre('nomstaxons.url_autocompletion_tpl'), $referentiel, $requete);
$restClient = $this->conteneur->getRestClient();
$resultatJson = $restClient->consulter($url);
$this->resultatsBruts =(array) json_decode($resultatJson, true);
}
}
 
private function formaterResultats() {
if (isset($this->resultatsBruts['resultat'])) {
foreach ($this->resultatsBruts['resultat'] as $info) {
$this->resultats[] = array(
"nn" => $info['num_nom'],
"ns" => $info['nom_sci_complet'],
"retenu" => ($info['retenu'] === "true" ? true : false)
);
}
}
}
 
private function mettreAJourEnteteResultats() {
$total = count($this->resultats);
$this->navigation->setTotal($total);
$this->navigation->setSansLimite();
}
}
/tags/v1.5-carbone/services/modules/0.1/Syndication.php
New file
0,0 → 1,175
<?php
// declare(encoding='UTF-8');
/**
* Classe principale de chargement des sous-services de syndication.
*
* @category DEL
* @package Services
* @subpackage Syndication
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
class Syndication extends RestService {
 
private $parametres = array();
private $ressources = array();
private $conteneur;
private $methode = null;
private $sousServiceNom = null;
private $cheminCourant = null;
 
private $serviceNom = 'syndication';
private $format = 'atom';
private $squelette_dossier = null;
 
/** Indique si oui (true) ou non (false), on veut utiliser les paramètres bruts. */
protected $utilisationParametresBruts = true;
 
public function __construct() {
$this->conteneur = new Conteneur();
$this->cheminCourant = dirname(__FILE__).DS;
$this->squelette_dossier = dirname(__FILE__).DS.$this->serviceNom.DS.'squelettes'.DS;
$this->formats_autorises = $this->conteneur->getParametreTableau('syndication.formats');
}
 
public function consulter($ressources, $parametres) {
$this->methode = 'consulter';
$this->initialiserRessourcesEtParametres($ressources, $parametres);
$this->verifierRessourcesEtParametres();
$this->format = isset($this->parametres['format']) ? $this->parametres['format'] : $this->format;
return $this->executerService();
}
 
private function initialiserRessourcesEtParametres($ressources, $parametres = array()) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function verifierRessourcesEtParametres() {
if (isset($this->parametres['format']) && !in_array($this->parametres['format'], $this->formats_autorises)) {
$msg = "Vous devez indiquer un format de flux valide.\n".$this->getDoc();
throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
}
}
 
private function executerService() {
$reponseHttp = new ReponseHttp();
try {
$donnees = $this->traiterRessources();
$resultat = $this->creerResultatService($donnees);
$reponseHttp->setResultatService($resultat);
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
}
$reponseHttp->emettreLesEntetes();
$corps = $reponseHttp->getCorps();
return $corps;
}
 
private function traiterRessources() {
$this->analyserRessources();
$retour = $this->initialiserService();
return $retour;
}
 
private function analyserRessources() {
if ($this->methode == 'consulter') {
if (isset($this->ressources[0])) {
$this->sousServiceNom = $this->ressources[0];
}
}
if ($this->sousServiceNom == null) {
$this->lancerMessageErreurRessource();
}
}
 
private function lancerMessageErreurRessource() {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
$message = "La ressource demandée '$ressource' ".
"n'est pas disponible pour le service {$this->serviceNom} !\n".
$this->getDoc();
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
 
public function getDoc() {
$formatsAutorises = implode(', ', $this->formats_autorises);
return "Les URLs disponibles pour ce service sont :\n".
" * en GET :\n".
" - syndication/commentaires\n".
" - syndication/tags\n".
" - syndication/votes-par-protocole\n".
" Paramètres : \n".
" - format : $formatsAutorises";
}
 
private function initialiserService() {
$classe = $this->obtenirNomClasseService($this->sousServiceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->serviceNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
 
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
require_once $chemin;
$service = new $classe($this->conteneur);
if ($this->methode == 'consulter') {
$retour = $service->consulter();
} else {
$message = "Le sous-service '{$this->sousServiceNom}' du service '{$this->serviceNom}' ".
"ne possède pas de méthode '{$this->methode}' !";
$code = RestServeur::HTTP_NON_IMPLEMENTE;
throw new Exception($message, $code);
}
}
}
 
if (is_null($service)) {
$ressource = $this->serviceNom.'/'.implode('/', $this->ressources);
$message = "Le classe '$classe' correspondant à la ressource '$ressource' ".
"est introuvable par le service '{$this->serviceNom}' !\n".
$this->getDoc();
$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;
}
 
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;
}
 
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.5-carbone/services/modules/0.1/Plantnet.php
New file
0,0 → 1,83
<?php
// declare(encoding='UTF-8');
/**
* Classe principale de chargement des sous-services de Plantnet.
*
* @category DEL
* @package Services
* @subpackage Plantnet
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Samuel DUFOUR-KOWALSKI <samuel.dufour@cirad.fr>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
class PlantNet extends RestService {
 
private $parametres = array();
private $ressources = array();
private $methode = null;
private $projetNom = 'plantnet';
private $serviceNom = 'changements';
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';
$reponseHttp = new ReponseHttp();
try {
$this->ressources = $ressources;
$this->parametres = $parametres;
 
$this->conteneur = new Conteneur($this->parametres);
 
$resultat = $this->initialiserService();
$reponseHttp->setResultatService($resultat);
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
}
$reponseHttp->emettreLesEntetes();
return $reponseHttp->getCorps();
}
 
/*------------------------------------------------------------------------------------------------------------------
CONFIGURATION DU SERVICE
------------------------------------------------------------------------------------------------------------------*/
private function initialiserService() {
$classe = $this->obtenirNomClasseService($this->serviceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->projetNom.DS.$classe.'.php';
$retour = '';
$service = null;
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
require_once $chemin;
$service = new $classe($this->conteneur);
$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 obtenirNomClasseService($mot) {
$classeNom = str_replace(' ', '', ucwords(strtolower(str_replace('-', ' ', $mot))));
return $classeNom;
}
}
/tags/v1.5-carbone/services/modules/0.1/Determinations.php
New file
0,0 → 1,143
<?php
// declare(encoding='UTF-8');
/**
* Classe principale de chargement des sous-services concernant les "déterminations" dans DEL.
*
* URLs possibles :
* GET :
* http://localhost/del/services/0.1/determinations/images-determinations-probables =>
*
* POST :
* http://localhost/del/services/0.1/determinations/valider-determination/#idProposition => Permet d'accepter une proposition donnée
*
* @category DEL
* @package Services
* @subpackage Determinations
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
class Determinations extends RestService {
 
private $parametres = array();
private $ressources = array();
private $methode = null;
private $serviceNom = 'determinations';
private $sousServiceNom = null;
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';
$this->initialiserRessourcesEtParametres($ressources, $parametres);
return $this->executerService();
}
 
public function modifier($ressources, $requeteDonnees) {
$this->methode = 'modifier';
$this->initialiserRessourcesEtParametres($ressources, $requeteDonnees);
return $this->executerService();
}
 
private function initialiserRessourcesEtParametres($ressources, $parametres = array()) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function executerService() {
$reponseHttp = new ReponseHttp();
try {
$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 traiterRessources() {
$this->analyserRessources();
$retour = $this->initialiserService();
return $retour;
}
 
private function analyserRessources() {
if ($this->methode == 'consulter') {
if ($this->ressources[0] == 'images-determinations-probables') {
$this->sousServiceNom = 'liste-images-determinations-probables';
}
} else if ($this->methode == 'modifier') {
if ($this->ressources[0] == 'valider-determination') {
$this->sousServiceNom = 'valider-determination';
}
}
 
if ($this->sousServiceNom == null) {
$this->lancerMessageErreurRessource();
}
}
 
private function lancerMessageErreurRessource() {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
$message = "La ressource demandée '$ressource' ".
"n'est pas disponible pour le service ".$this->serviceNom." !\n".
"Les URLs disponibles sont : \n".
" - en GET : determinations/images-determinations-probables \n".
" - en POST : determinations/valider-determination";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
 
private function initialiserService() {
$classe = $this->obtenirNomClasseService($this->sousServiceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->serviceNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
require_once $chemin;
$service = new $classe($this->conteneur);
if ($this->methode == 'consulter') {
$retour = $service->consulter($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)) {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
$message = "Le classe '$classe' correspondant à la ressource '$ressource' ".
"n'existe pas dans le service '{$this->serviceNom}' !";
$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.5-carbone/services/modules/0.1/Communes.php
New file
0,0 → 1,133
<?php
// declare(encoding='UTF-8');
/**
* Classe principale de chargement des sous-services d'accès aux infos sur les communes.
*
* @category DEL
* @package Services
* @subpackage Communes
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
class Communes extends RestService {
 
private $parametres = array();
private $ressources = array();
private $methode = null;
private $serviceNom = 'communes';
private $sousServiceNom = null;
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';
$this->initialiserRessourcesEtParametres($ressources, $parametres);
return $this->executerService();
}
 
private function initialiserRessourcesEtParametres($ressources, $parametres = array()) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function executerService() {
$reponseHttp = new ReponseHttp();
try {
$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 traiterRessources() {
$this->analyserRessources();
$retour = $this->initialiserService();
return $retour;
}
 
private function analyserRessources() {
if ($this->methode == 'consulter') {
if (count($this->ressources) == 0 && $this->verifierPresenceParametre('masque.nom')) {
$this->sousServiceNom = 'liste-communes';
}
}
if ($this->sousServiceNom == null) {
$this->lancerMessageErreurRessource();
}
}
 
private function verifierPresenceParametre($cle) {
if (isset($this->parametres[$cle]) && trim($this->parametres[$cle]) == '') {
$message = "Le service demandé '{$this->serviceNom}' ".
"nécessite l'utilisation d'un paramètre (non vide) : masque.nom \n";
throw new Exception($message, RestServeur::HTTP_CODE_ECHEC_CONDITION);
}
return true;
}
 
private function lancerMessageErreurRessource() {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
$message = "La ressource demandée '$ressource' ".
"n'est pas disponible pour le service ".$this->serviceNom." !\n".
"Les URLs disponibles sont : \n".
" - en GET : communes (paramètres : masque.nom) \n";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
 
private function initialiserService() {
$classe = $this->obtenirNomClasseService($this->sousServiceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->serviceNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
 
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
require_once $chemin;
$service = new $classe($this->conteneur);
if ($this->methode == 'consulter') {
$retour = $service->consulter();
} else {
$message = "Le sous-service '{$this->sousServiceNom}' du service '{$this->serviceNom}' ".
"ne possède pas de méthode '{$this->methode}' !";
$code = RestServeur::HTTP_NON_IMPLEMENTE;
throw new Exception($message, $code);
}
}
}
 
if (is_null($service)) {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
$message = "Le classe '$classe' correspondant à la ressource '$ressource' ".
"est introuvable par le service '{$this->serviceNom}' !";
$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.5-carbone/services/modules/0.1/Commentaires.php
New file
0,0 → 1,168
<?php
// declare(encoding='UTF-8');
/**
* Classe principale de chargement des sous-services concernant les commentaires.
*
* URLs possibles :
*
* GET :
* http://localhost/del/services/0.1/commentaires => liste tous les commentaires
* http://localhost/del/services/0.1/commentaires/#id => retourne le contenu d'un commentaire d'id #id
*
* PUT :
* http://localhost/del/services/0.1/commentaires => Ajoute un nouveau commentaire
*
* DELETE :
* http://localhost/del/services/0.1/commentaires/#id => supprime le commentaire d'id #id
*
* @category DEL
* @package Services
* @subpackage Commentaires
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
class Commentaires extends RestService {
 
private $parametres = array();
private $ressources = array();
private $methode = null;
private $serviceNom = 'commentaires';
private $sousServiceNom = null;
private $cheminCourant = null;
private $erreur = 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';
$this->initialiserRessourcesEtParametres($ressources, $parametres);
return $this->executerService();
}
 
public function ajouter($ressources, $requeteDonnees) {
$this->methode = 'ajouter';
$this->initialiserRessourcesEtParametres($ressources, $requeteDonnees);
return $this->executerService();
}
 
public function supprimer($ressources) {
$this->methode = 'supprimer';
$this->initialiserRessourcesEtParametres($ressources);
return $this->executerService();
}
 
private function initialiserRessourcesEtParametres($ressources, $parametres = array()) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function executerService() {
$reponseHttp = new ReponseHttp();
try {
$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 traiterRessources() {
$this->analyserRessources();
$retour = $this->initialiserService();
return $retour;
}
 
private function analyserRessources() {
if ($this->methode == 'consulter') {
if (!isset($this->ressources) || empty($this->ressources)) {
$this->sousServiceNom = 'liste-commentaires';
} else if (isset($this->ressources[0]) && count($this->ressources) == 1 && is_numeric($this->ressources[0])) {
$this->sousServiceNom = 'commentaire-details';
}
} else if ($this->methode == 'ajouter') {
$this->sousServiceNom = 'ajouter-commentaire';
} else if ($this->methode == 'supprimer') {
if (isset($this->ressources[0]) && count($this->ressources) == 1 && is_numeric($this->ressources[0])) {
$this->sousServiceNom = 'supprimer-commentaire';
} else {
$this->erreur = "L'identifiant du commentaire est obligatoire et doit être un entier.";
}
}
 
if ($this->sousServiceNom == null) {
$this->lancerMessageErreurRessource();
}
}
 
private function lancerMessageErreurRessource() {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
if ($this->erreur != null) {
$message = $this->erreur;
} else {
$message = "La ressource demandée '$ressource' ".
"n'est pas disponible pour le service ".$this->serviceNom." !\n".
"Les URLs disponibles sont : \n".
" - en GET : commentaires, commentaires/#id \n".
" - en PUT : commentaires".
" - en DELETE : commentaires/#id\n".
"#id représente un nombre entier identifiant un commentaire.";
}
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
 
private function initialiserService() {
$classe = $this->obtenirNomClasseService($this->sousServiceNom);
//echo $this->sousServiceNom.':'.$classe."\n";
//echo 'Ressources :'.print_r($this->ressources, true);
//echo 'Parametres :'.print_r($this->parametres, true);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->serviceNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
require_once $chemin;
$service = new $classe($this->conteneur);
if ($this->methode == 'consulter') {
$retour = $service->consulter($this->ressources);
} elseif ($this->methode == 'ajouter') {
$retour = $service->ajouter($this->parametres);
} elseif ($this->methode == 'supprimer') {
$retour = $service->supprimer($this->ressources);
}
}
}
 
if (is_null($service)) {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
$message = "Le classe '$classe' correspondant à la ressource '$ressource' ".
"n'existe pas dans le service '{$this->serviceNom}' !";
$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.5-carbone/services/modules/0.1/observations/ListeObservations.php
New file
0,0 → 1,245
<?php
// declare(encoding='UTF-8');
/**
* Web service récupèrant toutes les observations et, pour chacune d'elle, les images qui lui sont associées.
*
* ATTENTION : le web service commence par récupérer seulement les id des obs (1er requete SQL), puis dans une
* deuxième requête SQL récupère les informations complémentaires. Il s'avère qu'en procédant ainsi le web service
* est 3 fois plus rapide !
*
* @category DEL
* @package Services
* @subpackage Observations
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
class ListeObservations {
 
private $conteneur;
private $bdd;
private $navigation;
private $filtrage;
private $sql;
 
private $mappings = array();
private $paramsFiltres = array();
 
private $idsObsOrdonnees = array();
private $infosObs = array();
private $infosObsOrdonnee = array();
 
 
public function __construct(Conteneur $conteneur) {
$this->conteneur = $conteneur;
$this->conteneur->chargerConfiguration('config_departements_bruts.ini');
 
$this->bdd = $this->conteneur->getBdd();
$this->filtrage = $this->conteneur->getParametresFiltrage();
$this->sql = $this->conteneur->getSql();
$this->navigation = $this->conteneur->getNavigation();
 
$this->mappings['votes'] = $this->conteneur->getParametreTableau('votes.mapping');
$this->mappings['commentaires'] = $this->conteneur->getParametreTableau('commentaires.mapping');
}
 
public function consulter($ressources, $parametres) {
$this->paramsFiltres = $this->filtrage->filtrerUrlParamsAppliObs();
$this->sql->setAppli(Sql::APPLI_OBS);
$this->sql->setParametres($this->paramsFiltres);
$this->sql->ajouterContraintes();
$this->sql->ajouterConstrainteAppliObs();
$this->sql->definirOrdreSqlAppliObs();
 
$this->idsObsOrdonnees = $this->getIdObs();
$this->navigation->setTotal($this->sql->getTotalLignesTrouvees());
 
// Ce n'est pas la peine de continuer s'il n'y a pas eu de résultats
$resultat = new ResultatService();
$resultat->corps = array('entete' => $this->navigation->getEntete(), 'resultats' => array());
if (count($this->idsObsOrdonnees) > 0) {
 
// 2) récupération des données nécessaires pour ces observations (obs + images)
$this->infosObs = $this->getInfosObs();
 
// 3) suppression, merge des données en tableau assez représentatif du futur JSON en output
$this->infosObsOrdonnees = $this->formaterObservations();
 
// 4) Ajouter commentaires + votes à $this->infosObsOrdonnees
$this->chargerDeterminations();
 
$resultat->corps = array(
'entete' => $this->navigation->getEntete(),
//'resultats' => array_values($this->infosObsOrdonnees));
// TODO : renvoyer un vrai tableau et non un objet
'resultats' => $this->infosObsOrdonnees);
}
return $resultat;
}
 
// 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
*/
private function getIdObs() {
$requete = 'SELECT SQL_CALC_FOUND_ROWS id_observation '.
'FROM del_observation AS do '.
$this->sql->getJoin().
'WHERE '.$this->sql->getWhere().
$this->sql->getGroupBy().
$this->sql->getOrderBy().
$this->sql->getLimit().
' -- '.__FILE__.':'.__LINE__;
//Debug::printr($requete);
$resultats = $this->bdd->recupererTous($requete);
 
$idObs = array();
if ($resultats !== false ) {
foreach ($resultats as $resultat) {
$idObs[] = $resultat['id_observation'];
}
}
return $idObs;
}
 
/**
* Après avoir récupérer seulement les ids dans une première requête, nous récupérons maintenant les infos.
* Le web service est ainsi 3 fois plus rapide.
*/
private function getInfosObs() {
$idsObsConcat = implode(',', $this->idsObsOrdonnees);
$requete = "SELECT 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, do.mots_cles_texte, '.
'do.date_transmission, do.commentaire, '.
'do.ce_utilisateur AS `auteur.id`, do.prenom_utilisateur AS `auteur.prenom`, '.
'do.nom_utilisateur AS `auteur.nom`, do.courriel_utilisateur AS `auteur.courriel`, '.
'id_image, date_prise_de_vue AS `date`, hauteur, largeur, nom_original '.
'FROM del_observation AS do '.
' LEFT JOIN del_image AS di ON (do.id_observation = di.ce_observation) '.
"WHERE id_observation IN ($idsObsConcat) ".
' -- '.__FILE__.':'.__LINE__;
return $this->bdd->recupererTous($requete);
}
 
/**
* Les informations étant extraites d'une vue dont les infos des obs sont dupliquées pour chaque image,
* il nous faut maintenant récupérer qu'une seule fois les données d'observations et y intégrer les données
* des images.
*/
private function formaterObservations() {
$observations = array_map('array_filter', $this->infosObs);
$obsFormatees = array_flip($this->idsObsOrdonnees);// Permet de garder l'ordre de sortie !
foreach ($observations as $obs) {
$this->nettoyerAuteur($obs);
 
$id = $obs['id_observation'];
$obsFormatees[$id] = $obs;
 
$image = $this->extraireInfosImage($obs);
$obsFormatees[$id]['images'][] = $image;
}
return $obsFormatees;
}
 
private function nettoyerAuteur(&$obs) {
// 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($obs['auteur.id']) || !is_numeric($obs['auteur.id'])) {
$obs['auteur.id'] = "0";
}
if (!isset($obs['auteur.nom'])) {
$obs['auteur.nom'] = '[inconnu]';
}
}
 
private function extraireInfosImage(&$obs) {
$champsImageAffichables = array('id_image', 'date', 'hauteur' , 'largeur', 'nom_original');
$image = array_intersect_key($obs, array_flip($champsImageAffichables));
$urlImgTpl = $this->conteneur->getParametre('cel_img_url_tpl');
$image['binaire.href'] = sprintf($urlImgTpl, $image['id_image'], 'XL');
 
unset($obs['id_image'], $obs['date'], $obs['hauteur'], $obs['largeur'], $obs['nom_original']);
return $image;
}
 
/**
* 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() {
$idObsConcat = implode(',', $this->idsObsOrdonnees);
$requete = 'SELECT * '.
'FROM del_commentaire AS dc '.
'WHERE dc.nom_sel IS NOT NULL '.
"AND ce_observation IN ($idObsConcat) ".
'-- '.__FILE__.':'.__LINE__;
 
$propositions = $this->bdd->recupererTous($requete);
if ($propositions) {
foreach ($propositions as $proposition) {
$idObs = $proposition['ce_observation'];
$idComment = $proposition['id_commentaire'];
$comment = $this->formaterDetermination($idComment, $proposition);
if ($comment) {
$this->infosObsOrdonnees[$idObs]['commentaires'][$idComment] = $comment;
}
}
}
}
 
private function formaterDetermination($propositionId, $propositionInfos) {
if (!$propositionInfos) return NULL;
 
$propositionFormatee = array();
foreach ($this->mappings['commentaires'] as $nomChamp => $nomAttributJson) {
if (isset($propositionInfos[$nomChamp])) {
$propositionFormatee[$nomAttributJson] = $propositionInfos[$nomChamp];
}
}
 
// Charger les votes sur les déterminations
$requete = "SELECT * FROM del_commentaire_vote WHERE ce_proposition = $propositionId".
'-- '.__FILE__.':'.__LINE__;
$resultatsVotes = $this->bdd->recupererTous($requete);
foreach ($resultatsVotes as $vote) {
$propositionFormatee['votes'][$vote['id_vote']] = $this->formaterVote($vote);
}
 
$propositionFormatee['nb_commentaires'] = $this->chargerNombreCommentaire($propositionId);
 
return $propositionFormatee;
}
 
/**
* Formater un vote en fonction du fichier de configuration config_votes.ini
* @param $votes array()
*/
private function formaterVote($vote) {
$voteFormate = array();
foreach ($vote as $nomChamp => $valeur) {
$voteFormate[$this->mappings['votes'][$nomChamp]] = $valeur;
}
return $voteFormate;
}
 
private function chargerNombreCommentaire($propositionId) {
$requete = 'SELECT COUNT( id_commentaire ) AS nb '.
'FROM del_commentaire '.
"WHERE ce_proposition = $propositionId ".
'GROUP BY ce_proposition '.
'-- '.__FILE__.':'.__LINE__;
$commentaires = $this->bdd->recuperer($requete);
return $commentaires ? $commentaires['nb'] : 0;
}
}
/tags/v1.5-carbone/services/modules/0.1/observations/ObservationDetails.php
New file
0,0 → 1,204
<?php
// declare(encoding='UTF-8');
/**
* Web service retournant toutes les infos d'une observation donnée :
* images, votes sur image et protocole, commentaires, votes sur commentaires, ...
*
* @category DEL
* @package Services
* @subpackage Observations
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
class ObservationDetails {
 
private $conteneur;
private $bdd;
private $sql;
private $idObs;
private $protocole;
private $observation;
private $mappings = array();
 
public function __construct(Conteneur $conteneur) {
$this->conteneur = $conteneur;
$this->bdd = $this->conteneur->getBdd();
$this->sql = $this->conteneur->getSql();
 
$this->mappings['observations'] = $this->conteneur->getParametreTableau('observations.mapping');
$this->mappings['images'] = $this->conteneur->getParametreTableau('images.mapping');
$this->mappings['votes'] = $this->conteneur->getParametreTableau('votes.mapping');
$this->mappings['commentaires'] = $this->conteneur->getParametreTableau('commentaires.mapping');
// les deux alias suivants sont particuliers afin d'éviter un conflit d'alias lors des jointures avec del_commentaire_vote
$this->mappings['commentaires']['ce_utilisateur'] = '__auteur_com';
$this->mappings['commentaires']['date'] = '__date_com';
}
 
public function consulter($ressources, $parametres) {
$this->idObs = $ressources[0];
$this->protocole = isset($parametres['protocole']) && is_numeric($parametres['protocole']) ? intval($parametres['protocole']) : null;
 
$infos = $this->getInfosObservationEtImages();
if (! $infos) {
$message = "Aucune observation ne possède d'identifiant '{$this->idObs}'.";
throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
}
$this->formaterObservation($infos);
 
// 3) charge les données de votes et protocoles associés aux images
 
if ($this->observation['images']) {
$idsImages = array_keys($this->observation['images']);
$votes = $this->sql->getVotesDesImages($idsImages, $this->protocole);
$this->sql->ajouterInfosVotesProtocoles($votes, $this->observation['images']);
}
 
// 4) charge les commentaires et les votes associés -> modifie/créé $observation['commentaires']
$commentaires = $this->getCommentaires();
$this->ajouterCommentaires($commentaires);
 
// désindexe le tableau (tel qu'apparement attendu par les applis), c'est une exception
// TODO : corriger l'appli cliente pour utiliser les index puis supprimer cette ligne
$this->observation['images'] = array_values($this->observation['images']);
 
// autre élément de post-processing: le ce_utilisateur de l'observation non-numeric...
$this->nettoyerAuteur();
 
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
$resultat->corps = $this->observation;
return $resultat;
}
 
private function getInfosObservationEtImages() {
$obsChamps = $this->sql->getAliasDesChamps($this->mappings['observations'], null, 'do');
$imgChamps = $this->sql->getAliasDesChamps($this->mappings['images'], null, 'di');
 
// champs de l'annuaire (del_utilisateur): id_utilisateur prenom, nom, courriel
$annuaireChamps = implode(', ', array(
"IFNULL(du.prenom, do.prenom_utilisateur) AS `auteur.prenom`",
"IFNULL(du.nom, do.nom_utilisateur) AS `auteur.nom`",
"IFNULL(du.courriel, do.courriel_utilisateur) AS `auteur.courriel`"));
 
$requete = "SELECT $obsChamps, $imgChamps, $annuaireChamps ".
"FROM del_observation AS do ".
" LEFT JOIN del_image AS di ON (do.id_observation = di.ce_observation) ".
" LEFT JOIN del_utilisateur AS du ON (do.ce_utilisateur = du.id_utilisateur) ".
"WHERE do.id_observation = {$this->idObs} ".
'-- '.__FILE__.':'.__LINE__;
//Debug::printr($requete);
return $this->bdd->recuperer($requete);
}
 
private function formaterObservation($infos) {
$infos = array_filter($infos);
 
$image = array_intersect_key($infos, array_flip(array('id_image', 'date', 'hauteur' , 'largeur', 'nom_original')));
$urlImgTpl = $this->conteneur->getParametre('cel_img_url_tpl');
$imageFormat = 'XL';
$image['binaire.href'] = sprintf($urlImgTpl, $image['id_image'], $imageFormat);
unset($infos['id_image'], $infos['date'], $infos['hauteur'], $infos['largeur'], $infos['nom_original']);
 
$this->observation = $infos;
$this->observation['images'][$image['id_image']] = $image;
}
 
private function getCommentaires() {
$selectVotes = array('id_vote', 'ce_proposition', 'ce_utilisateur', 'valeur', 'date');
$selectCommentaires = 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');
 
$voteChamps = $this->sql->getAliasDesChamps($this->mappings['votes'], $selectVotes, 'cv');
$commentaireChamps = $this->sql->getAliasDesChamps($this->mappings['commentaires'], $selectCommentaires, 'dc');
 
// LEFT JOIN optionnel, mais explicatif : récupèration des infos de vote que pour les commentaires comportant un nom_sel "valide"
$requete = "SELECT $commentaireChamps, $voteChamps ".
"FROM del_commentaire AS dc ".
" LEFT JOIN del_commentaire_vote AS cv ".
" ON (cv.ce_proposition = dc.id_commentaire AND dc.nom_sel != '' AND dc.nom_sel IS NOT NULL) ".
"WHERE ce_observation = {$this->idObs} ".
'-- '.__FILE__.':'.__LINE__;
 
$commentaires = $this->bdd->recupererTous($requete);
return $commentaires;
 
}
 
private function ajouterCommentaires($commentaires) {
if (!$commentaires) return;
 
$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($this->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($this->mappings['votes']));
$ret[$commentId]['votes'][$voteId] = $vote;
}
$this->observation['commentaires'] = $ret;
}
 
private function nettoyerAuteur() {
if (!isset($this->observation['auteur.id']) || !is_numeric($this->observation['auteur.id'])) {
$this->observation['auteur.id'] = '0';
}
if (!isset($this->observation['auteur.nom'])) {
$this->observation['auteur.nom'] = '[inconnu]';
}
}
 
/**
* Modifie une observation directement dans le CEL en faisant un appel à un web service du CEL.
* Utilisé uniquement par les admins.
* Permet de dépublier une observation.
*
* @param array $ressources tableau des informations contenues dans l'url après le nom du service
* @param array $parametres contenu du post
* @return mixed Chaine "OK" (en majuscule) en cas de succès, booléen "false" en cas d'échec
*/
public function modifier($ressources, $parametres) {
$controlAcces = $this->conteneur->getControleAcces();
$controlAcces->etreUtilisateurAvecDroitAdmin();
 
$retour = false;
if (isset($parametres['transmission'])) {
$idObs = $ressources[0];
$clientRest = $this->conteneur->getRestClient();
$urlTpl = $this->conteneur->getParametre('urlServiceCelObs');
$url = $urlTpl.$idObs;
$retourCel = $clientRest->modifier($url, $parametres);
$retour = preg_match('/^OK$/i', $retourCel) ? 'OK' : false;
if ($retour === false) {
$message = "Erreur du web service CEL : ".$retourCel;
$code = RestServeur::HTTP_CODE_MAUVAISE_REQUETE;
throw new Exception($message, $code);
}
} else {
$message = "Ce web service doit contenir un paramètre 'transmission'.";
$code = RestServeur::HTTP_CODE_MAUVAISE_REQUETE;
throw new Exception($message, $code);
}
return $retour;
}
}
/tags/v1.5-carbone/services/modules/0.1/observations/VoteObservation.php
New file
0,0 → 1,244
<?php
// declare(encoding='UTF-8');
/**
* Web service permetant d'ajouter ou de modifier les votes associés aux propositions d'une observation.
*
* @category DEL
* @package Services
* @subpackage Observations
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
 
class VoteObservation {
private $conteneur;
private $bdd;
private $navigation;
private $mapping;
private $ressources;
private $parametres;
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->bdd = $this->conteneur->getBdd();
$this->navigation = $conteneur->getNavigation();
 
$this->mapping = $this->conteneur->getParametreTableau('votes.mapping');
}
 
public function consulter($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
 
$votes = $this->chargerVotes();
$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->navigation->getEntete(), 'resultats' => $votes);
return $resultat;
}
 
private function chargerVotes() {
$idCommentaireP = $this->bdd->proteger($this->ressources[1]);
$requete = 'SELECT * '.
'FROM del_commentaire_vote '.
"WHERE ce_proposition = $idCommentaireP ";
' -- '.__FILE__.':'.__LINE__;
$resultats = $this->bdd->recupererTous($requete);
$votes = array();
foreach ($resultats as $vote) {
$votes[$vote['id_vote']] = $this->formaterVotes($vote);
$utilisateur = $this->chercherUtilisateur($vote['ce_utilisateur']);
if (count($utilisateur) > 0) {
$votes[$vote['id_vote']] = array_merge($votes[$vote['id_vote']], $utilisateur);
}
}
return $votes;
}
 
private function formaterVotes($vote) {
$retour = array();
foreach ($vote as $param => $valeur) {
$retour[$this->mapping[$param]] = $valeur;
}
return $retour;
}
 
private function chercherUtilisateur($id) {
// par défaut, pas d'info
$utilisateur = array();
// Si l'id utilisateur est un hash de session, on ne cherche rien
if (is_numeric($id)) {
$idUtilisateurP = $this->bdd->proteger($id);
$requete = "SELECT id_utilisateur AS 'auteur.id', nom AS 'auteur.nom', prenom AS 'auteur.prenom', ".
"courriel AS 'auteur.courriel' ".
'FROM del_utilisateur '.
"WHERE id_utilisateur = $idUtilisateurP ".
' -- '.__FILE__.':'.__LINE__;
$utilisateur = $this->bdd->recuperer($requete);
}
return $utilisateur;
}
 
public function ajouter($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
$this->verifierParametresAjoutModif();
$idVote = $this->ajouterVote();
if ($idVote) {
$resultat = new ResultatService();
$resultat->corps = array('id_vote' => $idVote);
return $resultat;
}
return false;
}
 
private function ajouterVote() {
$idProposition = $this->creerPropositionDeterminationInitiale();
 
$idObsP = $this->bdd->proteger($this->ressources[0]);
$idPropositionP = $this->bdd->proteger($idProposition);
$idUtilisateurP = $this->bdd->proteger($this->parametres['utilisateur']);
$valeurP = $this->bdd->proteger($this->parametres['valeur']);
$requete = 'INSERT INTO del_commentaire_vote (ce_proposition , ce_utilisateur , valeur , date) '.
"VALUES ($idPropositionP, $idUtilisateurP, $valeurP, NOW()) ".
' -- '.__FILE__.' : '.__LINE__;
 
$resultat = $this->bdd->executer($requete);
if ($resultat === false) {
$msg = "Un problème est survenu lors de l'ajout d'un vote.";
throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
} else if ($resultat === 0) {
$msg = "Aucun vote ne correspond au critères fournis : ".
"idObs -> $idObsP, idProposition -> $idPropositionP et id_utilisateur -> $idUtilisateurP.";
throw new Exception($msg, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
}
// ATTENTION : idVote doit être récupéré avant toute nouvelle requete !
$idVote = $this->bdd->recupererIdDernierAjout();
return $idVote;
}
 
/** 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)
*/
private function creerPropositionDeterminationInitiale() {
$idProposition = $this->ressources[1];
if ($idProposition === 0) {
$propositionExiste = $this->verifierExistencePropositionInitiale();
if ($propositionExiste === false) {
$idProposition = $this->creerPropositionInitiale();
} else {
$idProposition = $this->getIdPropositionInitiale();
}
}
return $idProposition;
}
 
private function verifierExistencePropositionInitiale() {
$idObservationP = $this->bdd->proteger($this->ressources[0]);
$requete = 'SELECT COUNT(*) >= 1 AS existe '.
'FROM del_commentaire '.
"WHERE ce_observation = $idObservationP ".
'AND proposition_initiale = 1 '.
' -- '.__FILE__.' : '.__LINE__;
$resultat = $this->bdd->recuperer($requete);
return $resultat['existe'] == 1;
}
 
private function creerPropositionInitiale() {
$idObservationP = $this->bdd->proteger($this->ressources[0]);
$requete = '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 = $idObservationP ".
' -- '.__FILE__.' : '.__LINE__;
 
$this->bdd->executer($requete);
$id = $this->bdd->recupererIdDernierAjout();
return $id;
}
 
private function getIdPropositionInitiale() {
$idObservationP = $this->bdd->proteger($this->ressources[0]);
$requete = 'SELECT id_commentaire '.
'FROM del_commentaire '.
"WHERE ce_observation = $idObservationP ".
'AND proposition_initiale = 1 '.
' -- '.__FILE__.' : '.__LINE__;
$resultat = $this->bdd->recuperer($requete);
return $resultat['id_commentaire'];
}
 
public function modifier($ressources, $parametres) {
$this->ressources = $ressources;
$this->parametres = $parametres;
$this->verifierParametresAjoutModif();
$resultat = $this->modifierVote();
if ($resultat > 0) {
return 'ok';
}
}
 
private function modifierVote() {
$idProposition = $this->creerPropositionDeterminationInitiale();
if ($idProposition == null) {
$msg = "Aucun identifiant de proposition n'est lié à cette observation.";
throw new Exception($msg, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
}
 
$idObsP = $this->bdd->proteger($this->ressources[0]);
$idPropositionP = $this->bdd->proteger($idProposition);
$idUtilisateurP = $this->bdd->proteger($this->parametres['utilisateur']);
$valeurP = $this->bdd->proteger($this->parametres['valeur']);
$requete = 'UPDATE del_commentaire_vote '.
"SET valeur = $valeurP, date = NOW() ".
"WHERE ce_proposition = $idPropositionP AND ce_utilisateur = $idUtilisateurP ".
' -- '.__FILE__.' : '.__LINE__;
 
$resultat = $this->bdd->executer($requete);
if ($resultat === false) {
$msg = "Un erreur est survenu lors de la tentative de modification du vote.";
throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
} else if ($resultat === 0) {
$msg = "Aucun vote ne correspond au critères fournis : ".
"idObs -> $idObsP, idProposition -> $idPropositionP et id_utilisateur -> $idUtilisateurP.";
throw new Exception($msg, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
}
return $resultat;
}
 
private function verifierParametresAjoutModif() {
$erreurs = array();
 
if (!isset($this->parametres['utilisateur'])) {
$erreurs[] = 'Paramètre "utilisateur" manquant.';
}
 
if (!isset($this->parametres['valeur'])) {
$erreurs[] = 'Paramètre "valeur" manquant.';
} else {
if (!is_numeric($this->parametres['valeur'])) {
$erreurs[] = 'Le paramètre "valeur" doit être numérique.';
} elseif($this->parametres['valeur'] != 0 && $this->parametres['valeur'] != 1) {
$erreurs[] = 'Le paramètre "valeur" ne peut prendre que la valeur 0 ou 1.';
}
}
 
if (!empty($erreurs)) {
$msg = "Erreur lors de la configuration : \n".implode("\n", $erreurs);
throw new Exception($msg, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
}
}
}
/tags/v1.5-carbone/services/modules/0.1/Protocoles.php
New file
0,0 → 1,127
<?php
// declare(encoding='UTF-8');
/**
* Classe principale de chargement des sous-services de Protocoles.
*
* Urls possibles :
* http://localhost/service:del:0.1/protocoles => tous les protocoles
*
* @category DEL
* @package Services
* @subpackage Protocoles
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
class Protocoles extends RestService {
 
private $parametres = array();
private $ressources = array();
private $methode = null;
private $serviceNom = 'protocoles';
private $sousServiceNom = null;
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';
$this->initialiserRessourcesEtParametres($ressources, $parametres);
return $this->executerService();
}
 
private function initialiserRessourcesEtParametres($ressources, $parametres = array()) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function executerService() {
$reponseHttp = new ReponseHttp();
try {
$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 traiterRessources() {
$this->analyserRessources();
$retour = $this->initialiserService();
return $retour;
}
 
private function analyserRessources() {
if ($this->methode == 'consulter') {
if (count($this->ressources) == 0) {
$this->sousServiceNom = 'liste-protocoles';
}
}
if ($this->sousServiceNom == null) {
$this->lancerMessageErreurRessource();
}
}
 
private function lancerMessageErreurRessource() {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
$message = "La ressource demandée '$ressource' ".
"n'est pas disponible pour le service ".$this->serviceNom." !\n".
"Les URLs disponibles sont : \n".
" - en GET : protocoles (paramètres : aucun) \n";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
 
private function initialiserService() {
$classe = $this->obtenirNomClasseService($this->sousServiceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->serviceNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
 
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
require_once $chemin;
$service = new $classe($this->conteneur);
if ($this->methode == 'consulter') {
$retour = $service->consulter();
} else {
$message = "Le sous-service '{$this->sousServiceNom}' du service '{$this->serviceNom}' ".
"ne possède pas de méthode '{$this->methode}' !";
$code = RestServeur::HTTP_NON_IMPLEMENTE;
throw new Exception($message, $code);
}
}
}
 
if (is_null($service)) {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
$message = "Le classe '$classe' correspondant à la ressource '$ressource' ".
"est introuvable par le service '{$this->serviceNom}' !";
$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.5-carbone/services/modules/0.1/MotsCles.php
New file
0,0 → 1,148
<?php
// declare(encoding='UTF-8');
/**
* Classe principale de chargement des sous-service "mots-clés" de DEL.
*
* URLs possibles :
* GET
* http://localhost/del/services/0.1/mots-cles?image=#id&auteur.id=#id => les différents mots-clés des images en fonction des paramètres.
* PUT
* http://localhost/del/services/0.1/mots-cles?image=#id&auteur.id=#id&mot_cle=motCle1,motCle2,... => Ajoute différents mots-clés pour une image d'un utilisateur
* DELETE
* http://localhost/del/services/0.1/mots-cles?image=#id&auteur.id=#id => les différents mots-clés des images en fonction des paramètres.
*
* @category DEL
* @package Services
* @subpackage MotsCles
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
class MotsCles extends RestService {
 
private $parametres = array();
private $ressources = array();
private $methode = null;
private $serviceNom = 'mots_cles';
private $sousServiceNom = null;
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';
$this->initialiserRessourcesEtParametres($ressources, $parametres);
return $this->executerService();
}
 
public function ajouter($ressources, $requeteDonnees) {
$this->methode = 'ajouter';
$this->initialiserRessourcesEtParametres($ressources, $requeteDonnees);
return $this->executerService();
}
 
public function supprimer($ressources) {
$this->methode = 'supprimer';
$this->initialiserRessourcesEtParametres($ressources);
return $this->executerService();
}
 
private function initialiserRessourcesEtParametres($ressources, $parametres = array()) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function executerService() {
$resultat = '';
$reponseHttp = new ReponseHttp();
try {
$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 traiterRessources() {
$this->analyserRessources();
$retour = $this->initialiserService();
return $retour;
}
 
private function analyserRessources() {
if ($this->methode == 'consulter') {
if (!isset($this->ressources) || empty($this->ressources)) {
$this->sousServiceNom = 'liste-mots-cles';
}
} else if ($this->methode == 'ajouter') {
$this->sousServiceNom = 'ajouter-mot-cle';
} else if ($this->methode == 'supprimer') {
if (isset($this->ressources[0]) && count($this->ressources) == 1 && is_numeric($this->ressources[0])) {
$this->sousServiceNom = 'supprimer-mot-cle';
}
}
 
if ($this->sousServiceNom == null) {
$this->lancerMessageErreurRessource();
}
}
 
private function lancerMessageErreurRessource() {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
$message = "La ressource demandée '$ressource' ".
"n'est pas disponible pour le service «".$this->serviceNom."» !\n".
"Les URLs disponibles sont : \n".
" - en GET : mots-cles?image=#idImg&auteur.id=#idUtilisateur \n".
" - en PUT : mots-cles?image=#idImg&auteur.id=#idUtilisateur&mots_cles=motCle1,motCle2,...".
" - en DELETE : mots-cles/#idMotCle";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
 
private function initialiserService() {
$classe = $this->obtenirNomClasseService($this->sousServiceNom);
$chemin = $this->cheminCourant.$this->serviceNom.DS.$classe.'.php';
$retour = '';
$service = null;
if (file_exists($chemin)) {
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);
}
}
 
if (is_null($service)) {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
$message = "Le classe '$classe' correspondant à la ressource '$ressource' ".
"n'existe pas dans le service '{$this->serviceNom}' !";
$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.5-carbone/services/modules/0.1/Utilisateurs.php
New file
0,0 → 1,148
<?php
// declare(encoding='UTF-8');
/**
* Classe principale de chargement des sous-services liés aux utilisateurs.
*
* @category DEL
* @package Services
* @subpackage Utilisateurs
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
class Utilisateurs extends RestService {
 
private $parametres = array();
private $ressources = array();
private $methode = null;
private $serviceNom = 'utilisateurs';
private $sousServiceNom = null;
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;
$this->conteneur = new Conteneur();
}
 
public function consulter($ressources, $parametres) {
$this->methode = 'consulter';
$this->initialiserRessourcesEtParametres($ressources, $parametres);
return $this->executerService();
}
 
public function modifier($ressources, $requeteDonnees) {
$this->methode = 'modifier';
$this->initialiserRessourcesEtParametres($ressources, $requeteDonnees);
return $this->executerService();
}
 
private function initialiserRessourcesEtParametres($ressources, $parametres = array()) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function executerService() {
$reponseHttp = new ReponseHttp();
try {
$resultat = $this->traiterRessources();
$reponseHttp->setResultatService($resultat);
} catch (Exception $e) {
$reponseHttp->ajouterErreur($e);
}
$reponseHttp->emettreLesEntetes();
$corps = $reponseHttp->getCorps();
return $corps;
}
 
private function traiterRessources() {
$this->analyserRessources();
$retour = $this->initialiserService();
return $retour;
}
 
private function analyserRessources() {
if ($this->methode == 'consulter') {
//S'il n'y a pas de ressources => envoyer sur identification anonyme
if (!isset($this->ressources) || empty($this->ressources)) {
$this->sousServiceNom = 'identification';
} else {
if (count($this->ressources) == 1 && ($this->ressources[0] == 'deconnecter')) {
$this->sousServiceNom = 'deconnecter';
} else if(count($this->ressources) == 2 && $this->ressources[1] == 'preferences') {
$this->sousServiceNom = 'preferences';
} else if (count($this->ressources) == 2) {
$this->sousServiceNom = 'connecter';
} else {
$this->sousServiceNom = 'identification';
}
}
} else if ($this->methode == 'modifier') {
if (count($this->ressources) == 2 && $this->ressources[1] == 'preferences') {
$this->sousServiceNom = 'preferences';
}
}
 
if ($this->sousServiceNom == null) {
$this->lancerMessageErreurRessource();
}
}
 
private function lancerMessageErreurRessource() {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
$message = "La ressource demandée '$ressource' ".
"n'est pas disponible pour le service ".$this->serviceNom." !\n".
"Les URLs disponibles sont : \n".
" * en GET : \n".
" - utilisateurs : identification anonyme à partir des cookies (par défaut quelque soit l'url)\n".
" - utilisateurs/#login/#mot-de-passe : connecte l'utilisateur\n".
" - utilisateurs/deconnecter : déconnecte l'utilisateur actuellement connecté par cookie\n".
" - utilisateurs/#id/preferences : fourni les préférences de l'utilisateur #id\n".
" * en POST : \n".
" - utilisateurs/#id/preferences : permet de modifier \n";
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
 
private function initialiserService() {
$classe = $this->obtenirNomClasseService($this->sousServiceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->serviceNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
require_once $chemin;
$service = new $classe($this->conteneur);
if ($this->methode == 'consulter') {
$retour = $service->consulter($this->ressources, $this->parametres);
} elseif ($this->methode == 'modifier') {
$retour = $service->modifier($this->ressources, $this->parametres);
}
}
}
 
if (is_null($service)) {
$ressource = $this->serviceNom.'/'.implode('/', $this->ressources);
$message = "Le classe '$classe' correspondant à la ressource '$ressource' ".
"n'existe pas dans le service '{$this->serviceNom}' !";
$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.5-carbone/services/modules/0.1/syndication/Tags.php
New file
0,0 → 1,210
<?php
// declare(encoding='UTF-8');
/**
* Service fournissant des informations concernant les tags sur les images de DEL en fonction d'un protocole
* au format RSS1, RSS2 ou ATOM.
*
* @category DEL
* @package Services
* @subpackage Syndication
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
class Tags {
 
private $categorie = 'Tag';
private $conteneur;
private $bdd;
private $navigation;
private $syndication;
private $mapping = array();
 
public function __construct(Conteneur $conteneur) {
$this->conteneur = $conteneur;
$this->bdd = $this->conteneur->getBdd();
$this->navigation = $this->conteneur->getNavigation();
$this->syndication = $this->conteneur->getSyndicationOutils();
$this->mapping = $this->conteneur->getParametreTableau('syndication.mapping');
}
 
public function consulter() {
if ($this->syndication->fluxAdminDemande()) {
$this->syndication->demanderAutorisationAdmin();
}
 
$donnees_brutes = $this->getDerniersVotesImage();
$commentaires_formates = $this->formaterPourRss($donnees_brutes) ;
return $commentaires_formates;
}
 
/**
* Formater les données pour mettre en page le RSS
* */
private function formaterPourRss($elements) {
$derniere_info_en_date = reset($elements);
$donnees = $this->syndication->construireDonneesCommunesAuFlux('tag', $derniere_info_en_date['date']);
foreach ($elements as $element) {
$donnees['items'][] = $this->construireDonneesCommunesAuxItems($element);
}
return $donnees;
}
 
/**
* 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'] = htmlentities($this->categorie);
$item['description'] = $this->creerDescription($info, $item);
$item['description_encodee'] = htmlspecialchars($this->creerDescription($info, $item));
$item['modifier_par'] = $this->formaterNomTagueur($info);
return $item;
}
 
private function creerGuidItem($element) {
$guid = sprintf($this->conteneur->getParametre('syndication.tag_guid_tpl'), $element['id_tag']);
return $guid;
}
 
private function creerLienItem($element) {
// TODO : ajouter un lien vers la plateforme validation de picto lorsqu'elle sera dispo
$lien = sprintf($this->conteneur->getParametre('img_fiche_tpl'), $element['id_image']);
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->syndication->getUrlImage($donnees['id_image']);
$miniatureUrl = $this->syndication->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 creerAuteurImg($info) {
$auteur = $this->formaterNomAuteurImg($info).
($this->syndication->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->syndication->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() {
$clauseWhere = $this->chargerClauseWhere();
$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 '.
($clauseWhere != '' ? "AND $clauseWhere " : '').
'ORDER BY date DESC '.
'LIMIT '.$this->navigation->getDepart().','.$this->navigation->getLimite().' '.
' -- '.__FILE__.' : '.__LINE__;
$elements = $this->bdd->recupererTous($requete);
return $elements;
}
 
private function chargerClauseWhere() {
$where = array();
$filtres = $this->navigation->getFiltre();
if (!empty($filtres)) {
$filtrePossibles = $this->conteneur->getParametreTableau('syndication.tag_filtres');
foreach ($filtres as $cleFiltre => $valeur) {
if (in_array($cleFiltre, $filtrePossibles)) {
$champ = $this->mapping[$cleFiltre];
$valeurP = $this->bdd->proteger($valeur);
$where[] = " $champ = $valeurP ";
}
}
}
 
return (!empty($where)) ? implode('AND', $where) : '';
}
}
/tags/v1.5-carbone/services/modules/0.1/syndication/Commentaires.php
New file
0,0 → 1,237
<?php
// declare(encoding='UTF-8');
/**
* Service fournissant des informations concernant les commentaire de DEL au format RSS1, RSS2 ou ATOM.
*
* @category DEL
* @package Services
* @subpackage Syndication
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
class Commentaires {
 
private $categorie = 'Commentaires';
private $conteneur;
private $contexte;
private $bdd;
private $navigation;
private $mapping = array();
private $syndication;
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->contexte = $this->conteneur->getContexte();
$this->bdd = $this->conteneur->getBdd();
$this->navigation = $this->conteneur->getNavigation();
$this->syndication = $this->conteneur->getSyndicationOutils();
$this->mapping = $this->conteneur->getParametreTableau('syndication.mapping');
}
 
public function consulter() {
if ($this->syndication->fluxAdminDemande()) {
$this->syndication->demanderAutorisationAdmin();
}
 
$donnees_brutes = $this->getDerniersCommentaires();
$commentaires_formates = $this->formaterPourRss($donnees_brutes) ;
return $commentaires_formates;
}
 
private function formaterPourRss($elements) {
$derniere_info_en_date = reset($elements);
$donnees = $this->syndication->construireDonneesCommunesAuFlux('commentaire', $derniere_info_en_date['date']);
foreach ($elements as $element) {
$donnees['items'][] = $this->construireDonneesCommunesAuxItems($element);
}
return $donnees;
}
 
private function construireDonneesCommunesAuxItems($info) {
$item = array();
$date_modification_timestamp = $this->syndication->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'] = htmlentities($this->categorie);
$item['description'] = $this->creerDescription($info, $item);
$item['description_encodee'] = htmlspecialchars($this->creerDescription($info, $item));
$item['modifier_par'] = $this->creerAuteur($info);
return $item;
}
 
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('syndication.commentaire_guid_tpl'), $element['id_commentaire']);
return $guid;
}
 
private function creerLienItem($element) {
$lien = sprintf($this->conteneur->getParametre('obs_fiche_tpl'), $element['dob_id_observation']);
return $lien;
}
 
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->syndication->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->syndication->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() {
$clauseWhere = $this->chargerClauseWhere();
$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 '.
($clauseWhere != '' ? "AND $clauseWhere " : '').
'ORDER BY dc.date DESC '.
'LIMIT '.$this->navigation->getDepart().','.$this->navigation->getLimite().' '.
' -- '.__FILE__.' : '.__LINE__;
 
$elements = $this->bdd->recupererTous($requete);
return $elements;
}
 
/**
* Charger la clause WHERE en fonction des paramètres de masque
* */
private function chargerClauseWhere() {
$where = array();
$filtres = $this->navigation->getFiltre();
if (!empty($filtres)) {
$filtrePossibles = $this->conteneur->getParametreTableau('syndication.commentaire_filtres');
foreach ($filtres as $cleFiltre => $valeur) {
if (in_array($cleFiltre, $filtrePossibles)) {
if (isset($this->mapping[$cleFiltre])) {
$champ = $this->mapping[$cleFiltre];
}
switch ($cleFiltre) {
case 'espece':
$valeurP = $this->bdd->proteger($valeur.'%');
$where[] = " dob.$champ LIKE $valeurP OR dc.$champ LIKE $valeurP ";
break;
case 'auteur':
$where[] = $this->creerFiltreAuteur($valeur);
break;
default:
$valeurP = $this->bdd->proteger($valeur);
$where[] = " $champ = $valeurP ";
}
}
}
}
return (!empty($where)) ? implode('AND', $where) : '';
}
 
private function creerFiltreAuteur($auteurId) {
$whereAuteur = '';
if (is_numeric($auteurId)) {
$whereAuteur = " dc.ce_utilisateur = $auteurId ";
} else {
$auteurIdMotif = $this->bdd->proteger($auteurId.'%');
 
if (strpos($auteurId, '@') !== false) {
$whereAuteur = " dc.utilisateur_courriel LIKE $auteurIdMotif ";
} else {
$tableauNomPrenom = explode(' ', $auteurId, 2);
if (count($tableauNomPrenom) != 2) {
$whereAuteur = "(dc.utilisateur_nom LIKE $auteurIdMotif OR dc.utilisateur_prenom LIKE $auteurIdMotif) ";
} else {
// on teste potentiellement un nom prenom ou bien un prénom nom
$nomMotif = $this->bdd->proteger($tableauNomPrenom[0].'%');
$prenomMotif = $this->bdd->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) ".
') ';
}
}
}
return $whereAuteur;
}
}
/tags/v1.5-carbone/services/modules/0.1/syndication/squelettes/atom.tpl.xml
New file
0,0 → 1,33
<?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.5-carbone/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.5-carbone/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.5-carbone/services/modules/0.1/syndication/squelettes/rss2.tpl.xml
New file
0,0 → 1,25
<?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.5-carbone/services/modules/0.1/syndication/VotesParProtocole.php
New file
0,0 → 1,201
<?php
// declare(encoding='UTF-8');
/**
* Service fournissant des informations concernant les votes sur les images de DEL en fonction d'un protocole
* au format RSS1, RSS2 ou ATOM.
*
* @category DEL
* @package Services
* @subpackage Syndication
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
class VotesParProtocole {
 
private $categorie = 'Vote protocole';
private $conteneur;
private $bdd;
private $navigation;
private $syndication;
private $mapping = array();
 
public function __construct(Conteneur $conteneur) {
$this->conteneur = $conteneur;
$this->bdd = $this->conteneur->getBdd();
$this->navigation = $this->conteneur->getNavigation();
$this->syndication = $this->conteneur->getSyndicationOutils();
$this->mapping = $this->conteneur->getParametreTableau('syndication.mapping');
}
 
public function consulter() {
if ($this->syndication->fluxAdminDemande()) {
$this->syndication->demanderAutorisationAdmin();
}
 
$donnees_brutes = $this->getDerniersVotesImage();
$commentaires_formates = $this->formaterPourRss($donnees_brutes) ;
return $commentaires_formates;
}
 
/**
* Formater les données pour mettre en page le RSS
* */
private function formaterPourRss($elements) {
$derniere_info_en_date = reset($elements);
$donnees = $this->syndication->construireDonneesCommunesAuFlux('vote', $derniere_info_en_date['date_vote']);
foreach ($elements as $element) {
$donnees['items'][] = $this->construireDonneesCommunesAuxItems($element);
}
return $donnees;
}
 
/**
* 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'] = htmlentities($this->categorie);
$item['description'] = $this->creerDescription($info, $item);
$item['description_encodee'] = htmlspecialchars($this->creerDescription($info, $item));
$item['modifier_par'] = $this->creerVotant($info);
return $item;
}
 
private function creerGuidItem($element) {
$guid = sprintf($this->conteneur->getParametre('syndication.vote_guid_tpl'), $element['id_vote']);
return $guid;
}
 
private function creerLienItem($element) {
$lien = sprintf($this->conteneur->getParametre('img_fiche_tpl'), $element['ce_image']);
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->syndication->getUrlImage($donnees['ce_image']);
$miniatureUrl = $this->syndication->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 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() {
$clauseWhere = $this->chargerClauseWhere();
$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 '.
($clauseWhere != '' ? "WHERE $clauseWhere " : '').
'ORDER BY divo.date DESC '.
'LIMIT '.$this->navigation->getDepart().','.$this->navigation->getLimite().
' -- '.__FILE__.' : '.__LINE__;
 
$elements = $this->bdd->recupererTous($requete);
return $elements;
}
 
private function chargerClauseWhere() {
$where = array();
$filtres = $this->navigation->getFiltre();
if (!empty($filtres)) {
$filtrePossibles = $this->conteneur->getParametreTableau('syndication.vote_filtres');
foreach ($filtres as $cleFiltre => $valeur) {
if (in_array($cleFiltre, $filtrePossibles)) {
$champ = $this->mapping[$cleFiltre];
$valeurP = $this->bdd->proteger($valeur);
$where[] = " $champ = $valeurP ";
}
}
}
 
return (!empty($where)) ? implode('AND', $where) : '';
}
}
/tags/v1.5-carbone/services/modules/0.1/plantnet/Changements.php
New file
0,0 → 1,311
<?php
/**
* Le web service plantnet récupère toutes les infos de la vue del_plantnet.
* Ordonées par date de modification.
* Les images sont regroupées en observations.
* Les tags, les votes et les propositions de determinations sont intégrés à l'observation.
*
* @category DEL
* @package Services
* @subpackage Plantnet
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Samuel DUFOUR-KOWALSKI <samuel.dufour@cirad.fr>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
 
class Changements {
 
private $conteneur;
private $navigation;
private $bdd;
 
private $parametres = array();
private $ressources = array();
private $date_defaut = '1900-01-01';
private $idsObsImg = array();
private $infosObsImg = array();
 
 
public function __construct(Conteneur $conteneur = null) {
/* restore_exception_handler(); */
/* restore_error_handler(); */
/* ini_set("display_errors", "1"); */
 
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->navigation = $conteneur->getNavigation();
$this->bdd = $this->conteneur->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['date'])) {
$this->parametres['date'] = $this->date_defaut;
}
 
// Lancement du service
$this->idsObsImg = $this->getIdsObsImg();
$infos = array();
$total = 0;
if ($this->idsObsImg) {
$total = $this->getTotal();
 
$this->infosObsImg = $this->recupererInfos();
$infos = $this->formaterInfos();
$infos = $this->chargerPropositionPlusProbable($infos);
$infos = $this->orderArray($infos);
}
$this->navigation->setTotal($total);
 
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
$resultat->corps = array('entete' => $this->navigation->getEntete(), 'resultats' => $infos);
return $resultat;
}
 
/*-------------------------------------------------------------------------------
CHARGEMENT DES IMAGES
--------------------------------------------------------------------------------*/
 
private function getIdsObsImg() {
$date_debut = "'{$this->parametres['date']}'";
$limite = @min(intval($this->parametres['navigation.limite']), 1000);
$limite = $limite ? $limite : 10; // 0 => 10
$depart = intval(@$this->parametres['navigation.depart']);
 
$requete =
'SELECT SQL_CALC_FOUND_ROWS p.id_observation, p.id_image, '.
'GROUP_CONCAT(iv.valeur) AS votes, '.
'GROUP_CONCAT(DISTINCT tag) AS tags, '.
'GREATEST('.
' IFNULL(p.date_creation, \''.$this->date_defaut.'\'), '.
' IFNULL(p.date_modification, \''.$this->date_defaut.'\'), '.
' IFNULL(MAX(it.date), \''.$this->date_defaut.'\'), '.
' IFNULL(MAX(it.date_modification), \''.$this->date_defaut.'\'), '.
' IFNULL(MAX(iv.date), \''.$this->date_defaut.'\'), '.
' IFNULL(MAX(c.date), \''.$this->date_defaut.'\'), '.
' IFNULL(MAX(cv.date), \''.$this->date_defaut.'\')) AS modif_date '.
 
'FROM del_plantnet AS p '.
' LEFT JOIN del_image_vote AS iv '.
' ON (id_image = iv.ce_image AND iv.ce_protocole = 3) '.
' LEFT JOIN del_image_tag AS it '.
' ON (id_image = it.ce_image AND it.actif = 1) '.
' LEFT JOIN del_commentaire AS c '.
' ON (id_observation = c.ce_observation) '.
' LEFT JOIN del_commentaire_vote AS cv '.
' ON (c.id_commentaire = cv.ce_proposition) '.
'GROUP BY id_image, id_observation '.
'HAVING MAX(p.date_creation) >= '.$date_debut.' '.
' OR MAX(p.date_modification) >= '.$date_debut.' '.
' OR MAX(it.date) >= '.$date_debut.' '.
' OR MAX(it.date_modification) >= '.$date_debut.' '.
' OR MAX(iv.date) >= '.$date_debut.' '.
' OR MAX(c.date) >= '.$date_debut.' '.
' OR MAX(cv.date) >= '.$date_debut.' '.
'ORDER BY modif_date DESC '.
'LIMIT '.$depart.', '.$limite.
' -- '.__FILE__.':'.__LINE__;
//echo $requete; exit;
// GROUP BY (très couteux) car multiples observations associées à une image
// charlie est ici :-)
// eg: 16150,16185,16245,16246,118995,129989
return $this->bdd->recupererTous($requete);
}
 
private function getTotal() {
$compte = $this->bdd->recuperer('SELECT FOUND_ROWS() AS nbre');
$total = (int) $compte['nbre'];
return $total;
}
 
// recupere les donnée associées (fait en 2 requetes pour optimiser)
private function recupererInfos() {
// recuperer les ids
$idsImg = array();
foreach ($this->idsObsImg as $ids) {
$id = $ids['id_image'];
$idsImg[] = $id;
}
$idsImgConcat = implode(',', $idsImg);
 
$requete = 'SELECT '.
'id_observation, id_image, '.
'nom_sel, '.
'nom_referentiel, nom_ret, nom_ret_nn, nt, famille, '.
'zone_geo, latitude, longitude, '.
'date_observation, date_creation, date_transmission, '.
'mots_cles_texte, '.
'ce_utilisateur, prenom_utilisateur, nom_utilisateur, courriel_utilisateur, '.
'i_mots_cles_texte AS mots_cles_texte_image, nom_original AS nom_image '.
'FROM del_plantnet AS p '.
"WHERE id_image IN ($idsImgConcat) ".
' -- '.__FILE__.':'.__LINE__;
// recuperer les donnees
$resultats = $this->bdd->recupererTous($requete);
 
// regroupe les données par id_image
$img_data = array();
foreach ($resultats as $infos) {
$idImg = $infos['id_image'];
$img_data[$idImg] = $infos;
}
return $img_data;
}
 
/**
* Retourner un tableau d'images formaté en fonction des liaisons trouvées
* @param $liaisons les liaisons de la table del_obs_images
*/
private function formaterInfos() {
// regroupe les observations
$obs = array();
foreach ($this->idsObsImg as $ids) {
$idobs = $ids['id_observation'];
$idimg = $ids['id_image'];
 
$imgdata = $this->infosObsImg[$idimg];
 
if (!isset($obs[$idobs])) {
$obs[$idobs] = array();
}
 
$obs[$idobs]['id_observation'] = $idobs;
$obs[$idobs]['auteur_id'] = $imgdata['ce_utilisateur'];
$obs[$idobs]['auteur_prenom'] = $imgdata['prenom_utilisateur'];
$obs[$idobs]['auteur_nom'] = $imgdata['nom_utilisateur'];
$obs[$idobs]['auteur_courriel'] = $imgdata['courriel_utilisateur'];
 
$obs[$idobs]['mots_cles_obs_cel'] = $this->formaterMotsClesCel($imgdata['mots_cles_texte']);
 
$obs[$idobs]['date_observation'] = $imgdata['date_observation'];
$obs[$idobs]['date_publication'] = $imgdata['date_transmission'];
$obs[$idobs]['date_creation'] = $imgdata['date_creation'];
$obs[$idobs]['date_changement'] = $ids['modif_date'];
 
$obs[$idobs]['nom_sel'] = $imgdata['nom_sel'];
$obs[$idobs]['nom_referentiel'] = $imgdata['nom_referentiel'];
$obs[$idobs]['nom_ret'] = $imgdata['nom_ret'];
$obs[$idobs]['nn'] = $imgdata['nom_ret_nn'];
$obs[$idobs]['nt'] = $imgdata['nt'];
$obs[$idobs]['famille'] = $imgdata['famille'];
 
$obs[$idobs]['zone_geo'] = $imgdata['zone_geo'];
$obs[$idobs]['latitude'] = floatval($imgdata['latitude']);
$obs[$idobs]['longitude'] = floatval($imgdata['longitude']);
 
if (!isset($obs[$idobs]['images'])) {
$obs[$idobs]['images'] = array();
}
 
$img_obj = array(
'id_image' => $idimg,
'nom_image' => $imgdata['nom_image'],
'url' => sprintf('http://api.tela-botanica.org/img:%09dO.jpg', $idimg),
'votes' => array_map('intval', explode(',', $ids['votes'])),
'tags' => explode(',', $ids['tags']),
'mots_cles_img_cel' => $this->formaterMotsClesCel($imgdata['mots_cles_texte_image'])
);
// push
$obs[$idobs]['images'][] = $img_obj;
}
return $obs;
}
 
/**
* Charger les votes pour chaque image
*/
private function chargerPropositionPlusProbable(&$obs) {
$obsIds = array_keys($obs);
$idsObsConcat = implode(',', $obsIds);
 
$requete = 'SELECT ce_observation, id_commentaire, valeur, nom_sel, nom_sel_nn, nom_ret, nom_ret_nn, cv.ce_utilisateur '.
'FROM del_commentaire_vote AS cv, del_commentaire AS c '.
"WHERE ce_observation IN ($idsObsConcat) ".
'AND nom_sel IS NOT NULL '.
'AND c.id_commentaire = cv.ce_proposition '.
' -- '.__FILE__.':'.__LINE__;
$resultats = $this->bdd->recupererTous($requete);
 
// calcul des votes
// un vote identifié a un facteur de 3
// additionne tous les vote par ce_proposition
$votes = array(); // map ce_proposition -> score
foreach ($resultats as $vote) {
if (!isset($votes[$vote['id_commentaire']])) {
$votes[$vote['id_commentaire']] = 0;
}
$valeur = ($vote['valeur'] == 1) ? 1 : -1;
$votes[$vote['id_commentaire']] += is_numeric($vote['ce_utilisateur']) ? 3 * $valeur : $valeur;
}
 
foreach ($resultats as $vote) {
$idobs = $vote['ce_observation'];
 
if (!isset($obs[$idobs]['determinations'])) {
$obs[$idobs]['determinations'] = array();
}
 
$obs[$idobs]['determinations'][$vote['id_commentaire']] =
array('nom_sel' => $vote['nom_sel'],
'nom_ret' => $vote['nom_ret'],
'score' => $votes[$vote['id_commentaire']],
'nn' => $vote['nom_sel_nn']);
}
return $obs;
}
 
private function orderArray(&$obs) {
$ret = array();
foreach ($obs as $o) {
$ret[] = $o;
}
 
function cmp($a, $b) {
return ($a['date_changement'] < $b['date_changement']) ? 1 : -1;
}
 
usort($ret, 'cmp');
return $ret;
}
 
 
/*-------------------------------------------------------------------------------
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) {
$mots_cles_cel_affiches = "fleur,fleurs,feuille,feuilles,ecorce,fruit,fruits,port,plantnet,plantscan_new";
 
$result = array_intersect(
explode(',', $mots_cles_cel_affiches), // $tabMotsClesAffiches
explode(',', $chaineMotCleCel)); // $tabMotsClesCel
 
if (count($result) === 0) {
return array();
}
$ret = explode(',', implode(',', $result));
return $ret;
}
 
}
/tags/v1.5-carbone/services/modules/0.1/determinations/ValiderDetermination.php
New file
0,0 → 1,153
<?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 DEL
* @package Services
* @subpackage Determinations
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
 
class ValiderDetermination {
 
private $conteneur;
private $bdd;
private $idObs = null;
private $idProposition = null;
private $idAuteurObs = null;
private $idValidateurObs = null;
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->bdd = $this->conteneur->getBdd();
}
 
public function modifier($ressources, $parametres) {
$this->verifierParametres($ressources, $parametres);
$this->idProposition = $ressources[1];
$this->idValidateurObs = $this->validateurEstPresent($parametres) ? $parametres['validateur.id'] : $parametres['auteur.id'] ;
$retourCel = $this->modifierObservationParDetermination();
 
if (preg_match('/^(OK|Not Modified)$/i', $retourCel) == false) {
$msg = "Erreur: le web service du CEL a retourné : $e";
$code = RestServeur::HTTP_CODE_ERREUR;
throw new Exception($msg, $code);
}
return 'OK';
}
 
private function validateurEstPresent($parametres) {
return isset($parametres['validateur.id']) && is_numeric($parametres['validateur.id']) && $parametres['validateur.id'] != 0;
}
 
private function verifierParametres($ressources, $parametres) {
$erreurs = array();
if (!is_numeric($ressources[1])) {
$erreurs[] = "La ressource 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[] = "Le paramètre 'auteur.id' est manquant.";
}
// Le paramètre validateur.id (id de la personne validant la détemrinatiuon)
// est là pour éviter que le $_POST ne soit vide
if (isset($parametres['validateur.id']) && !is_numeric($parametres['validateur.id'])) {
$erreurs[] = "Le paramètre 'validateur.id' doit être un entier.";
}
 
if ($erreurs) {
$msg = "Erreur dans les paramètres d'appel au web service :\n\n" . implode("\n", $erreurs);
throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
}
}
 
/**
* 1) récupère l'observation, autrement échec
* 2) récupère et l'id auteur de l'obs et vérifie qu'il correspond à l'id de l'utilisateur actuel
* 3) prépare les nouvelles valeurs à transférer au service CEL
* 4) effectue la mise à jour
* 5) si tout s'est passé comme convenu, marque la proposition comme "retenue"
*/
private function modifierObservationParDetermination() {
$propositionInfos = $this->getInfosProposition();
$this->idObs = $propositionInfos['ce_observation'];
$this->idAuteurObs = $this->getIdAuteurObs();
$this->verifierDroitUtilisateur();
 
$parametres = array(
'id_observation' => $this->idObs,
'nom_sel_nn' => $propositionInfos['nom_sel_nn'],
'nom_referentiel' => $propositionInfos['nom_referentiel']
);
 
$urlBase = $this->conteneur->getParametre('urlServiceCelObs');
$url = $urlBase.$this->idObs;
$retour = $this->conteneur->getRestClient()->modifier($url, $parametres);
 
// TODO: check sur HTTP code == 200, plutôt que sur texte
if ($retour == 'ok' || $retour == 'OK') {
$this->mettreAJourPropositionRetenue();
}
return $retour;
}
 
private function getInfosProposition() {
$idPropositionP = $this->bdd->proteger($this->idProposition);
$requete = "SELECT id_commentaire, ce_observation, nom_sel_nn, nom_referentiel ".
'FROM del_commentaire '.
"WHERE id_commentaire = $idPropositionP ".
' -- '.__FILE__.' : '.__LINE__;
$resultat = $this->bdd->recuperer($requete);
if (! $resultat) {
throw new Exception("Cette proposition est invalide.", RestServeur::HTTP_CODE_ERREUR);
}
return $resultat;
}
 
private function getIdAuteurObs() {
$obsIdP = $this->bdd->proteger($this->idObs);
$requete = 'SELECT ce_utilisateur '.
'FROM del_observation '.
"WHERE id_observation = $obsIdP ".
' -- '.__FILE__.' : '.__LINE__;
$auteurInfo = $this->bdd->recuperer($requete);
return $auteurInfo['ce_utilisateur'];
}
 
private function verifierDroitUtilisateur() {
$controleAcces = $this->conteneur->getControleAcces();
$utilisateurInfos = $controleAcces->getInfosUtilisateurConnecte();
$utilisateurId = $utilisateurInfos['id_utilisateur'];
 
// si l'utilisateur connecté n'est ni auteur de l'observation, ni au moins administrateur de niveau 1
if (($this->idAuteurObs != $utilisateurId) && $utilisateurInfos['admin'] < 1) {
$msg = "Seul l'utilisateur ayant saisi l'observation, un administrateur ou un validateur peut la valider : veuillez vous identifier.\n";
throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
}
}
 
/**
* Remet à 0 le status "proposition_retenue" pour toutes les propositions faites sur cette
* observation à l'exception de celle désormais validée (qui voit son ce_validateur et sa date validation mise à jour)
*/
private function mettreAJourPropositionRetenue() {
$requete = 'UPDATE del_commentaire '.
"SET proposition_retenue = IF(id_commentaire = {$this->idProposition}, 1, 0), ".
"ce_validateur = IF(id_commentaire = {$this->idProposition}, {$this->idValidateurObs} , ce_validateur), ".
"date_validation = IF(id_commentaire = {$this->idProposition}, NOW() , date_validation) ".
"WHERE ce_observation = {$this->idObs} ".
' -- '.__FILE__.' : '.__LINE__;
 
return $this->bdd->requeter($requete);
}
}
/tags/v1.5-carbone/services/modules/0.1/determinations/ListeImagesDeterminationsProbables.php
New file
0,0 → 1,342
<?php
// declare(encoding='UTF-8');
/**
* Web service récupèrant toutes les données de la table del_obs_images
* pour retourner une liste d'images associées à la détermination la plus probable.
*
* Possibilité de ne renvoyer que les images les mieux notées pour un protocole donné.
*
* @category DEL
* @package Services
* @subpackage Determinations
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
 
class ListeImagesDeterminationsProbables {
 
private $indexImagesIds = array();
private $conteneur;
private $navigation;
private $bdd;
 
private $erreurs = array();
private $parametres = array();
private $protocoles = array();
 
private $idsImagesOrdonnees = array();
private $resultats = array();
private $propositions = array();
private $votes = array();
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->navigation = $conteneur->getNavigation();
$this->bdd = $this->conteneur->getBdd();
$this->chargerProtocoles();
}
 
private function chargerProtocoles() {
$requete = 'SELECT id_protocole FROM del_image_protocole -- '.__FILE__.' : '.__LINE__;
$resultats = $this->bdd->recupererTous($requete);
if ($resultats) {
foreach ($resultats as $infos) {
$this->protocoles[] = $infos['id_protocole'];
}
sort($this->protocoles);
}
}
 
public function consulter($parametres) {
$this->parametres = $parametres;
$this->verifierParametres();
 
// Lancement du service
$this->idsImagesOrdonnees = $this->getIdsImages();
$infos = $this->chargerInfos();
$this->modifierEnteteTotal();
if ($infos) {
$this->traiterResultats($infos);
$this->completerResutlats();
}
 
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
$resultat->corps = array('entete' => $this->navigation->getEntete(), 'resultats' => $this->resultats);
return $resultat;
}
 
private function verifierParametres() {
$this->verifierParamProtocole();
$this->verifierParamVote();
 
if (!empty($this->erreurs)) {
$msg = "Erreur de configuration :\n".implode("\n\n", $this->erreurs);
throw new Exception($msg, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
}
}
 
private function verifierParamProtocole() {
if (isset($this->parametres['masque.protocole'])) {
$protocoleExistant = in_array($this->parametres['masque.protocole'], $this->protocoles);
 
if (!is_numeric($this->parametres['masque.protocole']) || $protocoleExistant === false) {
$protocolesListe = implode(', ', $this->protocoles);
$msg = "La valeur pour le protocole doit être un entier compris dans les numéros de protocole ".
"existants : $protocolesListe";
$this->erreurs[] = $msg;
}
}
}
 
private function verifierParamVote() {
if (isset($this->parametres['masque.valeur_min_vote'])) {
$minVote = $this->parametres['masque.valeur_min_vote'];
if (!is_numeric($minVote) || ($minVote < 0 && $minVote > 5)) {
$this->erreurs[] = "La valeur minimum de valeur des votes doit être un entier compris entre 0 et 5.";
}
}
}
 
private function getIdsImages() {
$whereClause = $this->getClauseWhere();
$depart = $this->navigation->getDepart();
$limite = $this->navigation->getLimite();
 
$requete = 'SELECT SQL_CALC_FOUND_ROWS di.id_image '.
'FROM del_image AS di '.
' LEFT JOIN del_image_stat AS ds ON (di.id_image = ds.ce_image) '.
"$whereClause ".
'ORDER BY moyenne DESC '.
"LIMIT $depart, $limite ".
' -- '.__FILE__.' : '.__LINE__;
//Debug::printr($requete);
$resultats = $this->bdd->recupererTous($requete);
$idImgs = array();
if ($resultats !== false ) {
foreach ($resultats as $resultat) {
$idImgs[] = $resultat['id_image'];
}
}
return $idImgs;
}
 
private function getClauseWhere() {
$where = array();
if (isset($this->parametres['masque.protocole'])) {
$protocoleIdP = $this->bdd->proteger($this->parametres['masque.protocole']);
$where[] = "ds.ce_protocole = $protocoleIdP ";
}
if (isset($this->parametres['masque.valeur_vote_min'])) {
$voteP = $this->bdd->proteger($this->parametres['masque.valeur_vote_min']);
$where[] = "moyenne >= $voteP";
}
return (count($where) > 0) ? 'WHERE '.implode(' AND ', $where).' ' : '';
}
 
private function chargerInfos() {
$idImgsConcat = implode(',', $this->idsImagesOrdonnees);
 
$requete = 'SELECT SQL_CALC_FOUND_ROWS '.
'di.id_image, di.mots_cles_texte AS mots_cles_texte_image, '.
'do.id_observation, nom_referentiel, nom_ret, '.
'nom_ret_nn, nt, famille, ce_zone_geo, zone_geo, date_observation, '.
'do.ce_utilisateur, do.nom_utilisateur, do.prenom_utilisateur, '.
'du.prenom, du.nom '.
'FROM del_image AS di '.
' INNER JOIN del_observation AS do ON (di.ce_observation = do.id_observation) '.
' LEFT JOIN del_utilisateur AS du ON (di.ce_utilisateur = du.id_utilisateur) '.
' LEFT JOIN del_image_stat AS ds ON (di.id_image = ds.ce_image) '.
"WHERE di.id_image IN ($idImgsConcat) ".
'ORDER BY moyenne DESC '.
' -- '.__FILE__.' : '.__LINE__;
return $this->bdd->recupererTous($requete);
}
 
private function modifierEnteteTotal() {
$requete = 'SELECT FOUND_ROWS() AS nbre -- '.__FILE__.' : '.__LINE__;
$compte = $this->bdd->recuperer($requete);
$total = ($compte !== false) ? (int) $compte['nbre'] : 0;
$this->navigation->setTotal($total);
}
 
/**
* Retourner un tableau d'images formaté en fonction des liaisons trouvées
* @param $infos les infos sur les images et observations
* */
private function traiterResultats($infos) {
//Debug::printr($infos);
foreach ($infos as $info) {
$idImage = $info['id_image'];
$index = $this->formaterIndexResultat($info);
 
$this->obsIds[] = $info['id_observation'];
$this->indexImagesIds[$idImage] = $index;
$this->resultats[$index] = array(
'id_image' => $idImage,
'id_observation' => $info['id_observation'],
'auteur.intitule' => $this->formaterIntituleAuteur($info),
'binaire.href' => $this->formaterBinaireHref($info),
'determination.famille' => $info['famille'],
'determination.referentiel' => $info['nom_referentiel'],
'determination.ns' => $info['nom_ret'],
'determination.nn' => $info['nom_ret_nn'],
'determination.nt' => $info['nt'],
'date_observation' => $info['date_observation'],
'localite' => $this->formaterLieu($info),
'mots_cles_image_cel' => $this->formaterMotsClesCel($info),
'mots_cles_image_del' => ''
);
}
}
 
private function formaterIndexResultat($infos) {
return $infos['id_image'].'-'.$infos['id_observation'];
}
 
private function formaterIntituleAuteur($infos) {
if ($infos['ce_utilisateur'] == 0) {
$infos['prenom'] = $infos['prenom_utilisateur'];
$infos['nom'] = $infos['nom_utilisateur'];
}
$intitule = $infos['prenom'].' '.$infos['nom'];
return $intitule;
}
 
private function formaterBinaireHref($infos) {
return sprintf($this->conteneur->getParametre('determinations.url_image_tpl'), $infos['id_image']);
}
 
private function formaterLieu($infos) {
$lieuFormate = '';
if ($infos['ce_zone_geo']) {
$lieu = $infos['zone_geo'];
$id_zone_geo = $infos['ce_zone_geo'];
if (strpos($infos['ce_zone_geo'], 'INSEE-C:') === 0) {
$id_zone_geo = str_replace('INSEE-C:', '', $infos['ce_zone_geo']);
$id_zone_geo = strlen($id_zone_geo) >= 5 ? substr($id_zone_geo, 0, 2) : $id_zone_geo;
}
$lieuFormate = "$lieu ($id_zone_geo)";
}
return $lieuFormate;
}
 
/**
* 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 $infos le tableau contenant les infos sur une image.
* @return string la chaine filtrée
*/
private function formaterMotsClesCel($infos) {
$motsClesAffiches = $this->conteneur->getParametreTableau('determinations.mots_cles_cel_affiches');
$motsClesCel = explode(',', $infos['mots_cles_texte_image']);
$motsCles = array_intersect($motsClesAffiches, $motsClesCel);
return implode(',', $motsCles);
}
 
private function completerResutlats() {
$this->chargerVotes();
$this->chargerPropositions();
 
$this->completerMotsCles();
 
foreach ($this->resultats as $index => $infos) {
if ($this->doitRemplacerObservationParProposition($index)) {
$id_obs = $infos['id_observation'];
$this->resultats[$index]['determination.famille'] = $this->propositions[$id_obs]['famille'];
$this->resultats[$index]['determination.ns'] = $this->propositions[$id_obs]['nom_sel'];
$this->resultats[$index]['determination.nn'] = $this->propositions[$id_obs]['nom_sel_nn'];
$this->resultats[$index]['determination.nt'] = $this->propositions[$id_obs]['nt'];
}
$this->completerUrlFicheEflore($index);
}
}
 
private function chargerVotes() {
$idsObs = implode(',', $this->obsIds);
$requete = 'SELECT ce_proposition, valeur, ce_utilisateur '.
'FROM del_commentaire_vote '.
'WHERE ce_proposition IN '.
'( SELECT id_commentaire '.
' FROM del_commentaire '.
" WHERE ce_observation IN ($idsObs) AND nom_sel IS NOT NULL ) ".
'ORDER BY ce_proposition '.
' -- '.__FILE__.' : '.__LINE__;
$resultats = $this->bdd->recupererTous($requete);
if ($resultats !== false) {
foreach ($resultats as $vote) {
if (!isset($this->votes[$vote['ce_proposition']])) {
$this->votes[$vote['ce_proposition']] = 0;
}
$valeur = ($vote['valeur'] == 1) ? 1 : -1;
$this->votes[$vote['ce_proposition']] += is_numeric($vote['ce_utilisateur']) ? 3 * $valeur : $valeur;
}
}
}
 
private function chargerPropositions() {
$idsObs = implode(',', $this->obsIds);
$requete = 'SELECT * '.
'FROM del_commentaire '.
"WHERE ce_observation IN ($idsObs) ".
'AND nom_sel IS NOT NULL '.
' -- '.__FILE__.' : '.__LINE__;
$resultats = $this->bdd->recupererTous($requete);
 
foreach($resultats as $proposition) {
$id_proposition = $proposition['id_commentaire'];
$id_obs = $proposition['ce_observation'];
$proposition['valeur'] = (isset($this->votes[$id_proposition])) ? $this->votes[$id_proposition] : -1;
 
if (!isset($this->propositions[$id_obs])) {
$this->propositions[$id_obs] = $proposition;
} else {
$score_actuel = $proposition['valeur'];
$score_precedent = $this->propositions[$id_obs]['valeur'];
if ($score_actuel >= $score_precedent) {
$this->propositions[$id_obs] = $proposition;
}
}
}
}
 
private function completerMotsCles() {
$idsImages = implode(',', array_keys($this->indexImagesIds));
$requete = 'SELECT tag, ce_image '.
'FROM del_image_tag '.
"WHERE ce_image IN ($idsImages) ".
'AND actif = 1 '.
' -- '.__FILE__.' : '.__LINE__;
$resultats = $this->bdd->recupererTous($requete);
 
foreach ($resultats as $info) {
$index = $this->indexImagesIds[$info['ce_image']];
$tag = ($this->resultats[$index]['mots_cles_image_del'] != '') ? ','.$info['tag'] : $info['tag'];
$this->resultats[$index]['mots_cles_image_del'] .= $tag ;
}
}
 
private function doitRemplacerObservationParProposition($index) {
$idObs = $this->resultats[$index]['id_observation'];
return ((isset($this->propositions[$idObs])
&& $this->propositions[$idObs] != null
&& $this->propositions[$idObs]['nom_sel_nn'] != 0)
&& ($this->propositions[$idObs]['valeur'] > 0 || $this->resultats[$index]['determination.nn'] == 0)
);
}
 
private function completerUrlFicheEflore($index) {
if (isset($this->resultats[$index]['determination.nn'])) {
$urlTpl = $this->conteneur->getParametre('determinations.url_fiche_eflore_tpl');
$nn = $this->resultats[$index]['determination.nn'];
 
$this->resultats[$index]['url_fiche_eflore'] = sprintf($urlTpl, $nn);
}
}
}
/tags/v1.5-carbone/services/modules/0.1/commentaires/ListeCommentaires.php
New file
0,0 → 1,108
<?php
// declare(encoding='UTF-8');
/**
* Retourne la liste commentaires correspondant aux filtres passés dans l'url :
* http://localhost/del/services/0.1/commentaires => liste tous les commentaires
* Filtres : voir le fichier de config : commentaires.masques_possibles
*
* @category DEL
* @package Services
* @subpackage Commentaires
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
 
class ListeCommentaires {
 
private $conteneur;
private $navigation;
private $bdd;
 
private $mapping = array();
private $mappingInverse = array();
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = ($conteneur == null) ? new Conteneur() : $conteneur;
$this->navigation = $this->conteneur->getNavigation();
$this->bdd = $this->conteneur->getBdd();
 
$this->mapping = $this->conteneur->getParametreTableau('commentaires.mapping');
$this->mappingInverse = array_flip($this->mapping);
}
 
/**
* 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) {
// Lancement du service
$commentaires = $this->chargerCommentaires();
$total = $this->compterCommentairesTotal();
 
$commentaires = $this->formaterCommentaires($commentaires);
$this->navigation->setTotal($total);
 
$resultat = new ResultatService();
$resultat->corps = array('entete' => $this->navigation->getEntete(), 'resultats' => $commentaires);
return $resultat;
}
 
/**
* Chargement depuis la bdd de tous les commentaires
* */
private function chargerCommentaires() {
$requete = 'SELECT DISTINCT SQL_CALC_FOUND_ROWS * '.
'FROM del_commentaire '.
'WHERE '.$this->creerClauseWhere().' '.
'LIMIT '.$this->navigation->getDepart().','.$this->navigation->getLimite().' '.
' -- '.__FILE__.' : '.__LINE__;
$resultat = $this->bdd->recupererTous($requete);
return is_array($resultat) ? $resultat : array();
}
 
private function creerClauseWhere() {
$where = array();
$filtres = $this->navigation->getFiltre();
if (!empty($filtres)) {
foreach ($filtres as $cle => $valeur) {
$where[] = $this->mappingInverse[$cle].' = '.$this->bdd->proteger($valeur);
}
}
$clauseWhere = (!empty($where)) ? ' '.implode(' AND ', $where).' ' : ' 1 ';
return $clauseWhere;
}
 
/**
* Compter le nombre total de commentaires dans la base vis à vis des filtres de l'url.
* Utilisation du mécanisme SQL_CALC_FOUND_ROW de Mysql pour éviter une deuxième requete avec un COUNT.
*/
private function compterCommentairesTotal() {
$requete = 'SELECT FOUND_ROWS() AS nbre ';
$resultats = $this->bdd->recuperer($requete);
return (int) $resultats['nbre'];
}
 
/**
* Formater les commentaires
* @param $commentaires les commentaires à mettre à jour
* @return $commentaires les commentaires mis à jour
* */
private function formaterCommentaires($commentaires) {
$retour = array();
foreach ($commentaires as $idCommentaire => $infos) {
$idCommentaire = $infos['id_commentaire'];
foreach ($this->mapping as $nomChampBdd => $nomAttributSortie) {
$retour[$idCommentaire][$nomAttributSortie] = $infos[$nomChampBdd];
}
}
return $retour;
}
}
/tags/v1.5-carbone/services/modules/0.1/commentaires/CommentaireDetails.php
New file
0,0 → 1,68
<?php
// declare(encoding='UTF-8');
/**
* Retourne le contenu d'un commentaire pour un identifiant donné.
* http://localhost/service:del:0.1/commentaires/#id => retourne le contenu d'un commentaire d'id #id
*
* @category DEL
* @package Services
* @subpackage Commentaires
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
 
class CommentaireDetails {
 
private $conteneur;
private $bdd;
private $idCommentaire;
 
private $mapping = array();
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->bdd = $this->conteneur->getBdd();
 
$this->mapping = $this->conteneur->getParametreTableau('commentaires.mapping');
}
 
public function consulter($ressources) {
$this->idCommentaire = $ressources[0];
 
// Lancement du service
$commentaire = $this->chargerCommentaire();
$commentaire = $this->formaterCommentaires($commentaire);
 
// Mettre en forme le résultat et l'envoyer pour affichage*/
$resultat = new ResultatService();
$resultat->corps = $commentaire;
 
return $resultat;
}
 
private function chargerCommentaire() {
$requete = 'SELECT * '.
'FROM del_commentaire '.
'WHERE id_commentaire = '.$this->idCommentaire.' '.
' -- '.__FILE__.' : '.__LINE__;
$resultat = $this->bdd->recuperer($requete);
if ($resultat === false) {
$message = "Aucune information ne correspond au commentaire # «{$this->idCommentaire}».";
throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
}
return is_array($resultat) ? $resultat : array();
}
 
private function formaterCommentaires($infos) {
$retour = array();
foreach ($this->mapping as $nomChampBdd => $nomAttributSortie) {
$retour[$nomAttributSortie] = $infos[$nomChampBdd];
}
return $retour;
}
}
/tags/v1.5-carbone/services/modules/0.1/commentaires/SupprimerCommentaire.php
New file
0,0 → 1,118
<?php
// declare(encoding='UTF-8');
/**
* Permet de supprimer un commentaire.
*
* @category DEL
* @package Services
* @subpackage Commentaires
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
 
class SupprimerCommentaire {
 
private $conteneur;
private $navigation;
private $bdd;
private $utilisateur;
 
private $commentaireId;
private $utilisateurId;
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->navigation = $conteneur->getNavigation();
$this->bdd = $this->conteneur->getBdd();
$this->utilisateur = $this->conteneur->getUtilisateur();
}
 
public function supprimer($ressources) {
$this->commentaireId = $ressources[0];
 
$utilisateur = $this->utilisateur->getUtilisateurIdentifie();
$this->verifierIdentificationUtilisateur($utilisateur);
$this->utilisateurId = $utilisateur['id_utilisateur'];
 
// 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->etreCommentaireSansEnfant() && $this->etreUtilisateurAutorise()) {
$this->supprimerCommentaire();
$this->supprimerVotesAssocies();
}
 
$resultat = new ResultatService();
return $resultat;
}
 
private function verifierIdentificationUtilisateur($utilisateur) {
if ($utilisateur == null) {
$msg = "Ce service nécessite d'être identifié.";
throw new Exception($msg, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
}
}
 
private function etreCommentaireSansEnfant() {
$idCommentaireP = $this->bdd->proteger($this->commentaireId);
$requete = 'SELECT * '.
'FROM del_commentaire '.
"WHERE (ce_proposition = $idCommentaireP ".
"OR ce_commentaire_parent = $idCommentaireP) ".
' -- '.__FILE__.' : '.__LINE__;
$resultats = $this->bdd->recupererTous($requete);
if (!empty($resultats)) {
$msg = "Impossible de supprimer le commentaire car il a des réponses.";
throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
}
return true;
}
 
private function etreUtilisateurAutorise() {
if (! $this->etreProprietaire() && ! $this->utilisateur->etreAdmin()) {
$msg = "Impossible de supprimer le commentaire car l'utilisateur n'a pas les droits requis.";
throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
}
return true;
}
 
private function etreProprietaire() {
$requete = 'SELECT * '.
'FROM del_commentaire '.
"WHERE id_commentaire = {$this->commentaireId} ".
"AND ce_utilisateur = {$this->utilisateurId} ".
' -- '.__FILE__.' : '.__LINE__;
$resultats = $this->bdd->recupererTous($requete);
return !empty($resultats);
}
 
private function supprimerCommentaire() {
$commentaireIdP = $this->bdd->proteger($this->commentaireId);
$utilisateurIdP = $this->bdd->proteger($this->utilisateurId);
$requete = 'DELETE FROM del_commentaire '.
"WHERE id_commentaire = $commentaireIdP ".
"AND ce_utilisateur = $utilisateurIdP ".
' -- '.__FILE__.' : '.__LINE__;
$retour = $this->bdd->requeter($requete);
if (!$retour) {
$msg = 'Erreur lors de la suppression.';
throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
}
}
 
private function supprimerVotesAssocies() {
$commentaireId = $this->bdd->proteger($this->commentaireId);
$requete = 'DELETE FROM del_commentaire_vote '.
"WHERE ce_proposition = $commentaireId ".
' -- '.__FILE__.' : '.__LINE__;
$retour = $this->bdd->requeter($requete);
if (!$retour) {
$msg = 'Erreur lors de la suppression des votes associés.';
throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
}
}
}
/tags/v1.5-carbone/services/modules/0.1/commentaires/AjouterCommentaire.php
New file
0,0 → 1,207
<?php
// declare(encoding='UTF-8');
/**
* Permet d'ajouter un commentaire.
*
* @category DEL
* @package Services
* @subpackage Commentaires
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
 
class AjouterCommentaire {
 
private $conteneur;
private $navigation;
private $bdd;
private $parametres = array();
 
private $mapping = array();
private $erreurs = array();
 
public function __construct(Conteneur $conteneur) {
$this->conteneur = $conteneur;
$this->navigation = $this->conteneur->getNavigation();
$this->bdd = $this->conteneur->getBdd();
 
$this->mapping = $this->conteneur->getParametreTableau('commentaires.mapping');
}
 
public function ajouter($parametres) {
$this->parametres = $parametres;
$this->verifierParametres();
 
$this->completerParametresUtilisateur();
$this->gererPropositionInitiale();
$idCommentaireAjoute = $this->insererCommentaire();
 
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
$resultat->corps = array('id_commentaire' => $idCommentaireAjoute);
 
return $resultat;
}
 
private function verifierParametres() {
if (!isset($this->parametres['observation'])) {
$this->erreurs[] = "Impossible d'ajouter un commentaire sans identifiant d'observation (paramètre 'observation').";
}
 
if (!isset($this->parametres['auteur.id'])) {
$this->verifierParamsAuteurAnonyme();
}
 
$this->verifierParamsNonVide();
 
if (isset($this->parametres['nom_sel_nn']) && !isset($this->parametres['nom_referentiel'])) {
$this->erreurs[] = "Si le paramètre «nom_sel_nn» est présent, le paramètre «nom_referentiel» doit l'être aussi.";
}
 
if (!empty($this->erreurs)) {
$msg = "Erreur de configuration :\n".implode("\n\n", $this->erreurs);
throw new Exception($msg, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
}
}
 
private function verifierParamsAuteurAnonyme() {
$paramsAuteur = array('auteur.nom', 'auteur.prenom', 'auteur.courriel');
$paramsAuteurManquant = array();
foreach ($paramsAuteur as $param) {
if (!isset($this->parametres[$param])) {
$paramsAuteurManquant[] = $param;
}
}
 
if (!empty($paramsAuteurManquant)) {
$msgAuteurTpl = "Si le parametre 'auteur.id' n'est pas utilisé, il est nécessaire d'indiquer les ".
"nom (paramètre 'auteur.nom'), prénom (paramètre 'auteur.prenom') et courriel ".
"(paramètre 'auteur.courriel') de l'auteur.\nLes paramètres suivant sont abscents : %s\n";
$this->erreurs[] = sprintf($msgAuteurTpl, implode(', ', $paramsAuteurManquant));
}
}
 
private function verifierParamsNonVide() {
$paramsNonVide = array('nom_sel', 'nom_referentiel', 'nom_sel_nn');
foreach ($paramsNonVide as $param) {
if (isset($this->parametres[$param]) && trim($this->parametres[$param]) == '' ) {
$this->erreurs[] = "S'il est présent le paramètre «$param» ne peut pas être vide.";
}
}
}
 
private function completerParametresUtilisateur() {
$utilisateur = (isset($this->parametres['auteur.id'])) ? $this->obtenirUtilisateurAvecId() : $this->obtenirUtilisateurSansId();
if ($utilisateur !== false) {
foreach ($utilisateur as $param => $valeur) {
$this->parametres[$param] = $valeur;
}
}
}
 
private function obtenirUtilisateurAvecId() {
$auteurIdP = $this->bdd->proteger($this->parametres['auteur.id']);
$requete = "SELECT id_utilisateur AS 'auteur.id', nom AS 'auteur.nom', prenom AS 'auteur.prenom', courriel AS 'auteur.courriel' ".
'FROM del_utilisateur '.
"WHERE id_utilisateur = $auteurIdP ".
' -- '.__FILE__.' : '.__LINE__;
$utilisateur = $this->bdd->recuperer($requete);
return $utilisateur;
}
 
private function obtenirUtilisateurSansId() {
$nomP = $this->bdd->proteger($this->parametres['auteur.nom']);
$prenomP = $this->bdd->proteger($this->parametres['auteur.prenom']);
$courrielP = $this->bdd->proteger($this->parametres['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 = $courrielP AND nom = $nomP AND prenom = $prenomP ".
' -- '.__FILE__.' : '.__LINE__;
$utilisateur = $this->bdd->recuperer($requete);
return $utilisateur;
}
 
private function gererPropositionInitiale() {
if ($this->verifierExistencePropositionInitiale() === false) {
$this->creerPropositionInitiale();
// TODO : en cas d'échec de la création de la proposition ajouter un log...
}
}
 
private function verifierExistencePropositionInitiale() {
$idObsP = $this->bdd->proteger($this->parametres['observation']);
$requete = 'SELECT COUNT(*) >= 1 AS existe '.
'FROM del_commentaire '.
"WHERE ce_observation = $idObsP ".
' AND proposition_initiale = 1 '.
' -- '.__FILE__.' : '.__LINE__;
$resultat = $this->bdd->recuperer($requete);
return $resultat['existe'] == 1;
}
 
private function creerPropositionInitiale() {
$idObsP = $this->bdd->proteger($this->parametres['observation']);
$requete = '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, '.
"IF(nom_sel_nn = 0, NULL, nom_sel_nn), IF(nom_ret = '', NULL, nom_ret), IF(nom_ret_nn = 0, NULL, nom_ret_nn), ".
"IF(nt = 0, NULL, nt), IF(famille = '', NULL, famille), IF(nom_sel_nn = 0, NULL, 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 = $idObsP ".
' -- '.__FILE__.' : '.__LINE__;
$resultat = $this->bdd->executer($requete);
return $resultat;
}
 
private function insererCommentaire() {
$champs = $this->creerEnteteChamps();
$values = $this->creerClauseValues();
$requete = "INSERT INTO del_commentaire (date, $champs) VALUES (NOW(), $values) ".
' -- '.__FILE__.' : '.__LINE__;
 
$retour = $this->bdd->executer($requete);
if ($retour == null) {
$msgTpl = "Erreur inopinée lors de l'insertion du commentaire lié à l'observation «%s».";
$msg = sprintf($msgTpl, $this->parametres['observation']);
throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
}
 
$idCommentaire = $this->bdd->recupererIdDernierAjout();
return $idCommentaire;
}
 
private function creerEnteteChamps() {
return $this->creerSuiteChampsOuValeurs('champs');
}
 
private function creerClauseValues() {
return $this->creerSuiteChampsOuValeurs('valeurs');
}
 
private function creerSuiteChampsOuValeurs($mode) {
$suite = array();
foreach ($this->mapping as $nomChampBdd => $nomAttributSortie) {
if (isset($this->parametres[$nomAttributSortie]) && $this->parametres[$nomAttributSortie] != null) {
if ($mode == 'valeurs') {
$suite[] = $this->bdd->proteger($this->parametres[$nomAttributSortie]);
} else if ($mode == 'champs') {
$suite[] = $nomChampBdd;
} else {
$msg = "Erreur interne : mauvais paramètre passé à la méthode 'creerSuiteChampsOuValeurs'";
throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
}
}
}
return implode(', ', $suite);
}
}
/tags/v1.5-carbone/services/modules/0.1/communes/ListeCommunes.php
New file
0,0 → 1,50
<?php
// declare(encoding='UTF-8');
/**
* Web service fournissant une liste de noms de communes correspondants au terme recherché.
*
* @category DEL
* @package Services
* @subpackage Communes
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
class ListeCommunes {
 
private $conteneur;
private $navigation;
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->navigation = $conteneur->getNavigation();
}
 
public function consulter() {
$communes = $this->chargerCommunes();
$total = $this->compterCommunes($communes);
$this->navigation->setTotal($total);
$this->navigation->setSansLimite();
 
$resultat = new ResultatService();
$resultat->corps = array('entete' => $this->navigation->getEntete(), 'resultats' => $communes);
return $resultat;
}
 
private function chargerCommunes() {
$urlCelTpl = $this->conteneur->getParametre('urlServiceCelCommune');
$url = $urlCelTpl.$this->navigation->getFiltre('masque.nom');
$restClient = $this->conteneur->getRestClient();
$resultatJson = $restClient->consulter($url);
$resultat = json_decode($resultatJson);
return $resultat;
}
 
private function compterCommunes($communes) {
return count($communes);
}
}
/tags/v1.5-carbone/services/modules/0.1/mots_cles/ListeMotsCles.php
New file
0,0 → 1,106
<?php
// declare(encoding='UTF-8');
/**
* Récupère des listes de mots clés associés aux images
*
* @category DEL
* @package Services
* @subpackage MotsCles
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
 
class ListeMotsCles {
 
private $conteneur;
private $navigation;
private $bdd;
 
private $mapping = array();
private $mappingInverse = array();
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->navigation = $conteneur->getNavigation();
$this->bdd = $this->conteneur->getBdd();
 
$this->mapping = $this->conteneur->getParametreTableau('mots-cles.mapping');
$this->mappingInverse = array_flip($this->mapping);
}
 
/**
* 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) {
// Lancement du service
$motsCles = $this->chargerMotsCles();
$total = $this->compterMotsClesTotal();
 
$motsClesSortie = $this->formaterMotsCles($motsCles);
$this->navigation->setTotal($total);
 
$resultat = new ResultatService();
$resultat->corps = array('entete' => $this->navigation->getEntete(), 'resultats' => $motsClesSortie);
return $resultat;
}
 
private function chargerMotsCles() {
$requete = 'SELECT DISTINCT SQL_CALC_FOUND_ROWS * '.
'FROM del_image_tag '.
'WHERE actif = 1 '.$this->creerClauseWhere().
'LIMIT '.$this->navigation->getDepart().','.$this->navigation->getLimite().' '.
' -- '.__FILE__.' : '.__LINE__;
$resultat = $this->bdd->recupererTous($requete);
return is_array($resultat) ? $resultat : array();
}
 
private function creerClauseWhere() {
$where = array();
$filtres = $this->navigation->getFiltre();
if (!empty($filtres)) {
foreach ($filtres as $cle => $valeur) {
$where[] = $this->mappingInverse[$cle].' = '.$this->bdd->proteger($valeur);
}
}
$clauseWhere = (!empty($where)) ? ' AND '.implode(' AND ', $where).' ' : '';
return $clauseWhere;
}
 
/**
* Compter le nombre total de commentaires dans la base vis à vis des filtres de l'url.
* Utilisation du mécanisme SQL_CALC_FOUND_ROW de Mysql pour éviter une deuxième requete avec un COUNT.
*/
private function compterMotsClesTotal() {
$requete = 'SELECT FOUND_ROWS() AS nbre ';
$resultats = $this->bdd->recuperer($requete);
return (int) $resultats['nbre'];
}
 
/**
* Formater les mots clés pour la sortie.
*
* @param $mots_cles les mots clés à formater
* @return $mots_cles les mots clés mis à jour au format de la sortie du web service
*/
private function formaterMotsCles($mots_cles) {
$retour = array();
foreach ($mots_cles as $mot_cle) {
// Boucle sur le mapping pour respecter l'ordre des champs de sortie
foreach ($this->mapping as $nomChampBdd => $nomAttributSortie) {
if (isset($mot_cle[$nomChampBdd])) {
$retour[$mot_cle['id_tag']][$nomAttributSortie] = $mot_cle[$nomChampBdd];
}
}
}
return $retour;
}
}
/tags/v1.5-carbone/services/modules/0.1/mots_cles/SupprimerMotCle.php
New file
0,0 → 1,76
<?php
// declare(encoding='UTF-8');
/**
* Supprime un mot clé par son identifiant
*
* @category DEL
* @package Services
* @subpackage MotsCles
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
 
class SupprimerMotCle {
 
private $conteneur;
private $bdd;
private $ressources = array();
private $motCleId;
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->bdd = $this->conteneur->getBdd();
}
 
/**
* Supprime un mot-clé si les données fournis en paramètres sont valides.
*
* @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2)
*/
public function supprimer($ressources) {
$this->ressources = $ressources;
$this->verifierRessources();
 
$this->motCleId = $this->ressources[0];
$this->supprimerMotCle();
TelaBotanica\Del\Commun\MotsClesImage::updateStats($this->bdd, $this->motCleId);
 
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
return $resultat;
}
 
private function verifierRessources() {
$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)) {
$msg = "Erreur de configuration :\n".implode("\n", $erreurs);
throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
}
}
 
private function supprimerMotCle() {
$idMotCleP = $this->bdd->proteger($this->motCleId);
$requete = 'UPDATE del_image_tag '.
'SET actif = 0, date_modification = NOW() '.
"WHERE id_tag = $idMotCleP ".
' -- '.__FILE__.' : '.__LINE__;
$retour = $this->bdd->executer($requete);
if ($retour == null) {
$msg = "Erreur lors de la suppression du mot-clé d'id $idMotCleP";
throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
}
return $retour;
}
}
/tags/v1.5-carbone/services/modules/0.1/mots_cles/AjouterMotCle.php
New file
0,0 → 1,120
<?php
// declare(encoding='UTF-8');
/**
* Ajoute un ou plusieurs mots-clés en les associant à un identifiant d'image
*
* @category DEL
* @package Services
* @subpackage MotsCles
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
 
class AjouterMotCle {
 
private $conteneur;
private $bdd;
private $parametres = array();
private $idDernierAjout = null;
private $nbreMotsClesAjoutes = null;
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->bdd = $this->conteneur->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->parametres = $parametres;
 
// Gestion des configuration du script
$this->verifierParametres();
$this->insererMotCle();
TelaBotanica\Del\Commun\MotsClesImage::updateStats($this->bdd, $this->parametres['image']);
 
// Mettre en forme le résultat et l'envoyer pour affichage
$resultat = new ResultatService();
$resultat->corps = array('nbre' => $this->nbreMotsClesAjoutes, 'id' => $this->idDernierAjout);
 
return $resultat;
}
 
public function verifierParametres() {
$erreurs = array();
 
if (!isset($this->parametres['image'])) {
$erreurs[] = " - impossible d'ajouter un mot clé sans l'indication de l'identifiant de l'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 l'identifiant de l'auteur associé";
}
 
if (!empty($erreurs)) {
$msg = "Erreur de configuration :\n".implode("\n", $erreurs);
throw new Exception($msg, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
}
}
 
/**
* Insère un mot clé dans la table
* */
private function insererMotCle() {
$clauseValues = $this->creerClauseValues();
$requete = 'INSERT INTO del_image_tag '.
'(ce_image, ce_utilisateur, tag, tag_normalise, date, actif, date_modification) '.
"VALUES $clauseValues ".
' -- '.__FILE__.' : '.__LINE__;
$nbreInsertion = $this->bdd->executer($requete);
$idDernierAjout = $this->bdd->recupererIdDernierAjout();
if ($nbreInsertion == null) {
$msgTpl = "Erreur lors de l'insertion d'un des tags «%s» pour l'image «%s» de l'auteur «%s»";
$msg = sprintf($msgTpl, $this->parametres['mot_cle'], $this->parametres['image'], $this->parametres['auteur.id']);
throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
}
$this->nbreMotsClesAjoutes = $nbreInsertion;
$this->listerIdAjoutes($idDernierAjout, $nbreInsertion);
}
 
private function listerIdAjoutes($dernierId, $nbreInsertion) {
$this->idDernierAjout[] = $dernierId;
for ($i = 1 ; $i <= ($nbreInsertion - 1); $i++ ) {
$this->idDernierAjout[] = ++$dernierId;
}
}
 
private function creerClauseValues() {
$id_image = intval($this->parametres['image']);
$idImageP = $this->bdd->proteger($id_image);
$id_auteur = $this->parametres['auteur.id'];
$idAuteurP = $this->bdd->proteger($id_auteur);
$mots_cles = explode(',', $this->parametres['mot_cle']);
 
$values = array();
foreach ($mots_cles as $mot_cle) {
$motCleP = $this->bdd->proteger(trim($mot_cle));
$mot_cle_normalise = TelaBotanica\Del\Commun\MotsClesImage::normaliserMotCle($mot_cle);
$motCleNormaliseP = $this->bdd->proteger($mot_cle_normalise);
 
$values[] = "($idImageP, $idAuteurP, $motCleP, $motCleNormaliseP, NOW(), 1, NOW())";
}
$clauseValues = implode(',', $values);
return $clauseValues;
}
}
/tags/v1.5-carbone/services/modules/0.1/Statistiques.php
New file
0,0 → 1,135
<?php
// declare(encoding='UTF-8');
/**
* Accès aux sous-services de statistiques pour Identiplante / Pictoflora
*
* @see Documentation : <http://www.tela-botanica.org/wikini/DevInformatiques/wakka.php?wiki=AppliDelStats>
*
* @category DEL
* @package Services
* @subpackage Statistiques
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
class Statistiques extends RestService {
 
private $parametres = array();
private $ressources = array();
private $methode = null;
private $serviceNom = 'statistiques';
private $sousServiceNom = null;
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';
$this->initialiserRessourcesEtParametres($ressources, $parametres);
return $this->executerService();
}
 
private function initialiserRessourcesEtParametres($ressources, $parametres = array()) {
$this->ressources = $ressources;
$this->parametres = $parametres;
}
 
private function executerService() {
$reponseHttp = new ReponseHttp();
try {
$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 traiterRessources() {
$this->analyserRessources();
$retour = $this->initialiserService();
return $retour;
}
 
private function analyserRessources() {
if ($this->methode == 'consulter') {
$this->sousServiceNom = 'statistiques-par-annee';
}
if ($this->sousServiceNom == null) {
$this->lancerMessageErreurRessource();
}
}
 
private function lancerMessageErreurRessource() {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
$message = "La ressource demandée '$ressource' ".
"n'est pas disponible pour le service {$this->serviceNom} !\n".
self::getDoc();
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
throw new Exception($message, $code);
}
 
public static function getDoc() {
return "Les URLs disponibles pour ce service sont :\n".
" * en GET :\n".
" - statistiques/tout\n".
" - statistiques/moyenneObsSansNomParMois\n".
" - statistiques/moyenneObsIdentifieesParMois\n".
" - statistiques/pourcentageObsIdentifieesEnFinDAnnee\n".
" - statistiques/pourcentageObsIdentifieesEnFinDAnneePlusPlus\n".
" - statistiques/moyenneActionsParJour\n".
" - statistiques/personnesEnvoyantUnePropositionParMois\n";
}
 
private function initialiserService() {
$classe = $this->obtenirNomClasseService($this->sousServiceNom);
$chemins = array();
$chemins[] = $this->cheminCourant.$this->serviceNom.DS.$classe.'.php';
$chemins[] = $this->cheminCourant.'commun'.DS.$classe.'.php';
$retour = '';
$service = null;
 
foreach ($chemins as $chemin) {
if (file_exists($chemin)) {
require_once $chemin;
$service = new $classe($this->conteneur);
if ($this->methode == 'consulter') {
$retour = $service->consulter();
} else {
$message = "Le sous-service '{$this->sousServiceNom}' du service '{$this->serviceNom}' ".
"ne possède pas de méthode '{$this->methode}' !";
$code = RestServeur::HTTP_NON_IMPLEMENTE;
throw new Exception($message, $code);
}
}
}
 
if (is_null($service)) {
$ressource = $this->sousServiceNom.'/'.implode('/', $this->ressources);
$message = "Le classe '$classe' correspondant à la ressource '$ressource' ".
"est introuvable par le service '{$this->serviceNom}' !";
$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.5-carbone/services/modules/0.1/protocoles/ListeProtocoles.php
New file
0,0 → 1,66
<?php
// declare(encoding='UTF-8');
/**
* Récupère tous les protocoles avec id, nom et descriptif
*
* @category DEL
* @package Services
* @subpackage Protocoles
* @version 0.1
* @author Mathias CHOUET <mathias@tela-botanica.org>
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Aurelien 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>
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
*/
 
class ListeProtocoles {
 
private $conteneur;
private $navigation;
private $bdd;
 
private $mapping = array();
 
public function __construct(Conteneur $conteneur = null) {
$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
$this->navigation = $conteneur->getNavigation();
$this->bdd = $this->conteneur->getBdd();
}
 
public function consulter() {
// Gestion des configuration du script
$this->mapping = $this->conteneur->getParametreTableau('protocoles.mapping');
 
$protocoles = $this->chargerProtocoles();
$protocoles = $this->formaterProtocoles($protocoles);
$this->navigation->setTotal(count($protocoles));
 
$resultat = new ResultatService();
$resultat->corps = array(
'entete' => $this->navigation->getEntete(),
'resultats' => $protocoles);
return $resultat;
}
 
private function chargerProtocoles() {
$requete = 'SELECT * FROM del_image_protocole -- '.__FILE__.' : '.__LINE__;
return $this->bdd->recupererTous($requete);
}
 
private function formaterProtocoles($protocoles) {
$protocolesRetour = array();
foreach ($protocoles as $protocole) {
$protocoleFormate = array();
$idProtocole = $protocole['id_protocole'];
foreach($protocole as $champProtocole => $valeur) {
if (isset($this->mapping[$champProtocole])) {
$protocoleFormate[$this->mapping[$champProtocole]] = $valeur;
}
}
$protocolesRetour[$idProtocole] = $protocoleFormate;
}
return $protocolesRetour;
}
}