* @copyright Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org) * @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL * @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL * @version $Id: Bdd.php 403 2012-02-22 14:35:20Z gduche $ * @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=ApiIdentiplante01Observations */ class ListeObservationsWidget { private $conteneur; private $navigation; private $masque; private $gestionBdd; private $bdd; private $parametres = array(); private $ressources = array(); private $tri = 'date_transmission'; private $directionTri = 'desc'; public function __construct(Conteneur $conteneur = null) { $this->conteneur = $conteneur == null ? new Conteneur() : $conteneur; $this->conteneur->chargerConfiguration('config_observations.ini'); $this->conteneur->chargerConfiguration('config_departements_bruts.ini'); $this->navigation = $conteneur->getNavigation(); $this->masque = $conteneur->getMasque(); $this->gestionBdd = $conteneur->getGestionBdd(); $this->bdd = $this->gestionBdd->getBdd(); } /** * Méthode principale de la classe. * Lance la récupération des images dans la base et les place dans un objet ResultatService * pour l'afficher. * @param array $ressources les ressources situées après l'url de base (ex : http://url/ressource1/ressource2) * @param array $parametres les paramètres situés après le ? dans l'url * */ public function consulter($ressources, $parametres) { $this->initialiserRessourcesEtParametres($ressources, $parametres); // Gestion des configuration du script $this->configurer(); $this->verifierConfiguration(); $this->verifierParametresTri(); $this->initialiserTri(); // Lancement du service $observations = $this->chargerObservations(); $total = $this->compterObservations(); $this->navigation->setTotal($total); $observations = $this->formaterObservations($observations); // Mettre en forme le résultat et l'envoyer pour affichage $resultat = new ResultatService(); $resultat->corps = array('entete' => $this->conteneur->getEntete(), 'resultats' => $observations); return $resultat; } private function initialiserRessourcesEtParametres($ressources, $parametres) { $this->ressources = $ressources; $this->parametres = $parametres; } private function verifierParametresTri() { $erreurs = array(); $tris_possibles = $this->conteneur->getParametre('tris_possibles'); $tris_possibles_tableau = explode(',', $tris_possibles); if(isset($this->parametres['tri']) && !in_array($this->parametres['tri'], $tris_possibles_tableau)) { $erreurs[] = '- le type de tri demandé est incorrect, les valeurs possibles sont '.$tris_possibles.' ;'; } $directions_tri = array('asc', 'desc'); if(isset($this->parametres['ordre']) && !in_array($this->parametres['ordre'], $directions_tri)) { $erreurs[] = '- la direction du tri demandé est incorrecte, les valeurs supportées sont asc ou desc ;'; } if (!empty($erreurs)) { $e = 'Erreur lors de l\'analyse des parametres du tri : '."\n"; $e .= implode("\n", $erreurs); throw new Exception($e, RestServeur::HTTP_CODE_ERREUR); } } private function initialiserTri() { $this->tri = isset($this->parametres['tri']) ? $this->parametres['tri'] : $this->tri; $this->directionTri = isset($this->parametres['ordre']) ? $this->parametres['ordre'] : $this->directionTri; } /*------------------------------------------------------------------------------- CONFIGURATION DU SERVICE --------------------------------------------------------------------------------*/ /** * Configuration du service en fonction du fichier de config config_del.ini * */ private function configurer() { $this->mappingFiltre = $this->conteneur->getParametre('mapping_masque'); $this->mappingObservation = $this->conteneur->getParametre('mapping_observation'); $this->mappingVotes = $this->conteneur->getParametre('mapping_votes'); $this->mappingCommentaire = $this->conteneur->getParametre('mapping_commentaire'); } /** * Vérifier que le service est bien configuré * */ private function verifierConfiguration() { $erreurs = array(); $tableauObservations = $this->conteneur->getParametre('observations'); if (empty($tableauObservations)) { $erreurs[] = '- le fichier de configuration ne contient pas le tableau [images] ou celui-ci est vide ;'; } else { if ($this->conteneur->getParametre('url_service') == null) { $erreurs[] = '- paramètre "url_service" manquant ;'; } if ($this->conteneur->getParametre('url_images') == null) { $erreurs[] = '- paramètre "url_images" manquant ;'; } } if (empty($this->mappingObservation)) { $erreurs[] = '- le fichier de configuration ne contient pas le tableau [mapping_observation] ou celui-ci est vide ;'; } else { $champsMappingObs = array('id_observation', 'date_observation', 'date_transmission', 'famille', 'nom_sel', 'nom_sel_nn', 'nt', 'ce_zone_geo', 'zone_geo', 'lieudit', 'station', 'courriel', 'ce_utilisateur', 'nom', 'prenom'); foreach ($champsMappingObs as $champ) { if (!isset($this->mappingObservation[$champ])) { $erreurs[] = '- le mapping du champ "'.$champ.'" pour l\'observation est manquant ;'; } } } if (!empty($erreurs)) { $e = 'Erreur lors de la configuration : '."\n"; $e .= implode("\n", $erreurs); throw new Exception($e, RestServeur::HTTP_CODE_ERREUR); } } /** * Charger la clause WHERE en fonction des paramètres de masque * */ private function chargerClauseWhere() { $where = array(); $tableauMasque = $this->masque->getMasque(); if (!empty($tableauMasque)) { foreach($tableauMasque as $idMasque => $valeurMasque) { $idMasque = str_replace('masque.', '', $idMasque); switch ($idMasque) { // nom du masque => nom BDD case 'auteur' : $whereAuteur = ' '.$this->creerFiltreAuteur($this->masque->getMasque('auteur')); if($whereAuteur != '') { $where[] = $whereAuteur; } break; case 'date' : $whereDate = ' '.$this->creerFiltreDate($valeurMasque); if($whereDate != '') { $where[] = $whereDate; } break; case 'departement' : $where[] = ' '.$this->creerFiltreIdZoneGeo($valeurMasque); break; case 'genre' : $where[] = ' '.$this->mappingFiltre['ns'].' LIKE '.$this->proteger('%'.$valeurMasque.'% %'); break; case 'tag' : $where[] = ' '.$this->creerFiltreMotsCles($valeurMasque); break; case 'ns' : $where[] = ' nom_sel LIKE '.$this->proteger($valeurMasque.'%'); break; case 'commune' : $where[] = ' '.$this->mappingFiltre[$idMasque].' LIKE '.$this->proteger(str_replace(array('-',' '), '_', $valeurMasque).'%'); break; case 'masque' : $where[] = ' '.$this->creerFiltreMasqueGeneral($valeurMasque); break; default: $where[] = ' '.$this->mappingFiltre[$idMasque].' = '.$this->proteger($valeurMasque); break; } } } if (!empty($where)) { return ' WHERE '.implode('AND', $where); } else { return; } } private function creerFiltreMasqueGeneral($valeurMasque) { //TODO: affecter d'aborder les variables, puis les tester pour les // ajouter à la chaine $whereAuteur = $this->creerFiltreAuteur($valeurMasque); $whereIdZoneGeo = $this->creerFiltreIdZoneGeo($valeurMasque); $masqueGeneral = '( '. (($whereAuteur != '') ? $whereAuteur.' OR ' : '' ). (($whereIdZoneGeo != '') ? $whereIdZoneGeo.' OR ' : '' ). 'zone_geo LIKE '.$this->proteger($this->remplacerParJokerCaractere($valeurMasque).'%').' OR '. $this->creerFiltreMotsCles($valeurMasque).' OR '. 'nom_sel LIKE '.$this->proteger($valeurMasque.'%').' OR '. 'famille LIKE '.$this->proteger($valeurMasque.'%').' OR '. 'milieu LIKE '.$this->proteger($valeurMasque).' OR '. $this->mappingFiltre['ns'].' LIKE '.$this->proteger('%'.$valeurMasque.'% %').' OR '. $this->creerFiltreDate($valeurMasque). ') '; return $masqueGeneral; } private function creerFiltreAuteur($valeurMasque) { $masque = ''; $auteurId = $valeurMasque; if (is_numeric($auteurId)) { $masque = ' ce_utilisateur = '.$auteurId; } else { if (strpos($auteurId, '@') === false) { $tableauNomPrenom = explode(' ',$auteurId, 2); if(count($tableauNomPrenom) == 2) { // on teste potentiellement un nom prenom ou bien un prénom nom $masque = '('. '(nom LIKE '.$this->proteger($tableauNomPrenom[0].'%').' AND '. 'prenom LIKE '.$this->proteger($tableauNomPrenom[1].'%').') OR '. '(nom LIKE '.$this->proteger($tableauNomPrenom[1].'%').' AND '. 'prenom LIKE '.$this->proteger($tableauNomPrenom[0].'%').') OR '. '(dob.nom_utilisateur LIKE '.$this->proteger($tableauNomPrenom[0].'%').' AND '. 'dob.prenom_utilisateur LIKE '.$this->proteger($tableauNomPrenom[1].'%').') OR '. '(dob.nom_utilisateur LIKE '.$this->proteger($tableauNomPrenom[1].'%').' AND '. 'dob.prenom_utilisateur LIKE '.$this->proteger($tableauNomPrenom[0].'%').') '. ')'; } else { $masque = '( (nom LIKE '.$this->proteger($auteurId.'%').' OR '. 'prenom LIKE '.$this->proteger($auteurId.'%').' OR '. 'dob.nom_utilisateur LIKE '.$this->proteger($auteurId.'%').' OR '. 'dob.prenom_utilisateur LIKE '.$this->proteger($auteurId.'%').')'. ')'; } } else { $masque = " courriel LIKE ".$this->proteger($valeurMasque.'%'). " OR dob.courriel_utilisateur LIKE ".$this->proteger($valeurMasque.'%')." "; } } return $masque; } private function remplacerParJokerCaractere($valeurMasque) { return str_replace(array('-',' '), '_', $valeurMasque); } //TODO: déplacer les fonctions ci dessus et dessous dans une classe // utilitaire function supprimerAccents($str, $charset='utf-8') { $str = htmlentities($str, ENT_NOQUOTES, $charset); $str = preg_replace('#&([A-za-z])(?:acute|cedil|circ|grave|orn|ring|slash|th|tilde|uml);#', '\1', $str); $str = preg_replace('#&([A-za-z]{2})(?:lig);#', '\1', $str); // pour les ligatures e.g. 'œ' $str = preg_replace('#&[^;]+;#', '', $str); // supprime les autres caractères return $str; } private function obtenirIdDepartement($nomDpt) { $nomDpt = $this->supprimerAccents($nomDpt); $nomDpt = strtolower(str_replace(' ','-',$nomDpt)); $idDpt = $this->conteneur->getParametre($nomDpt); if($idDpt == null || $idDpt == ' ') { $idDpt = ' '; } return $idDpt; } private function creerFiltreIdZoneGeo($valeurMasque) { $masque = ''; $dept = $valeurMasque; if (is_numeric($dept)) { $dept = sprintf('%02s', $dept); $dept = sprintf("%-'_5s", $dept); $masque = " ce_zone_geo LIKE ".$this->proteger('INSEE-C:'.$dept); } else { $deptId = $this->conteneur->getParametre($dept); if ($deptId != null) { $masque = " ce_zone_geo LIKE ".$this->proteger('INSEE-C:'.$deptId.'%'); } else { $id = $this->obtenirIdDepartement($valeurMasque); $masque = " ce_zone_geo LIKE ".$this->proteger('INSEE-C:'.$id.'%'); } } return $masque; } private function creerFiltreDate($valeurMasque) { //TODO: définir dans le fichier de config un tableau contenant plusieurs format de date // autorisés pour la recherche, qui seraient ajoutés au OR $masque = '('; $masque .= (is_numeric($valeurMasque)) ? ' YEAR(date_observation) = '.$this->proteger($valeurMasque).' OR ' : ''; $masque .= " DATE_FORMAT(date_observation, '%d/%m/%Y') = ".$this->proteger($valeurMasque).' '. ')'; return $masque; } private function creerFiltreMotsCles($valeurMasque) { $mots_cles = explode(' ', $valeurMasque); $requeteMotsClesImg = ''; $requeteMotsClesObs = ''; //TODO voir s'il existe un moyen plus simple que le foreach + rtrim // comme avec implode (attention au fait que l'on concatène des % au début et à la fin) foreach($mots_cles as $mot_cle) { $requeteMotsCles = $this->proteger('%'.$mot_cle.'%'); $requeteMotsClesObs .= 'dob.mots_cles_texte LIKE '.$requeteMotsCles.' AND '; } $requeteMotsClesImg = rtrim($requeteMotsClesImg, ' AND '); $requeteMotsClesObs = rtrim($requeteMotsClesObs, ' AND '); $masque = '('. '('.$requeteMotsClesImg.') OR '. '('.$requeteMotsClesObs.') '. ') '; return $masque; } /*------------------------------------------------------------------------------- CHARGEMENT DES OBSERVATIONS --------------------------------------------------------------------------------*/ /** * Chargement depuis la bdd de toutes les liaisons entre images et observations * */ private function chargerObservations() { $requete = 'SELECT DISTINCT dob.id_observation '. 'FROM '.$this->gestionBdd->formaterTable('del_observation', 'dob'). 'INNER JOIN '.$this->gestionBdd->formaterTable('del_obs_image', 'doi'). 'ON doi.id_observation = dob.id_observation '. $this->chargerClauseWhere(). ' ORDER BY '.$this->tri.' '.$this->directionTri.' '. $this->gestionBdd->getLimitSql(); return $this->bdd->recupererTous($requete); } /** * Compter le nombre total d'images dans la base pour affichage dans entete. * */ private function compterObservations() { $requete = 'SELECT FOUND_ROWS() AS nbre '; $resultats = $this->bdd->recuperer($requete); return (int) $resultats['nbre']; } /** * Retourner un tableau d'images formaté en fonction des liaisons trouvées * @param $liaisons les liaisons de la table del_obs_images * */ private function formaterObservations($liaisons) { $observations = array(); foreach ($liaisons as $liaison) { $observations[] = $liaison['id_observation']; } return $observations; } /*------------------------------------------------------------------------------- FORMATER ET METTRE EN FORME --------------------------------------------------------------------------------*/ private function proteger($valeur) { if (is_array($valeur)) { return $this->bdd->protegerTableau($valeur); } else { return $this->bdd->proteger($valeur); } } } ?>