Subversion Repositories eFlore/Applications.moissonnage

Rev

Rev 43 | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?php

/**
 * 
 * Classe en charge de recuperer les donnees d'observation ou liees a leur localisation
 * Le jeu de donnees a interroger est celui utilise par l'application Carnet En Ligne
 * (http://www.tela-botanica.org/page:cel)
 * 
 * On passera en parametre lors de la creation d'une instance un objet contenant la liste des criteres
 * qui vont restreindre le nombre de resultats a renvoyer
 * 
 * Les deux operations suivantes peuvent etre utilisees dans les services :
 *   - recupererStations : va rechercher dans la base de donnees tous les points d'observations
 *     correspondant aux criteres de recherche demandes. La precision des lieux d'observation est
 *     soit un point precis, soit ramenee au niveau de la commune dans laquelle l'observation a ete faite
 *     En fonction du niveau de zoom et du nombre de resultats trouves, la presentation se fera
 *     soit par les points localisant les stations pour des niveaux de zoom eleves ou pour un nombre
 *     de stations inferieur a un seuil, ou par des mailles de 64*64 pixels dans le cas contraire
 *
 *   - recupererObservations : va rechercher dans la base de donnees les donnees sur des observations
 *     a partir des coordonnees longitude et latitude d'une station (+ des parametres additionnels)
 * 
 * Les donnees seront renvoyees au format JSON
 * 
 * @package framework-0.4
 * @author Alexandre GALIBERT <alexandre.galibert@tela-botanica.org>
 * @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
 * @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
 * @version $Id$
 * @copyright 2013 Tela Botanica (accueil@tela-botanica.org)
 *
 */


final class FloradataFormateur extends Formateur {
        
        final protected function construireRequeteStations() {
                $condition = "(longitude IS NULL OR latitude IS NULL OR (longitude=0 AND latitude=0) ".
                "OR longitude>180 OR latitude>90 OR mots_cles_texte LIKE '%sensible%')";
                $requete = 
                        "SELECT COUNT(id_observation) AS observations, ce_zone_geo, zone_geo, station, ".
                        "IF({$condition}, wgs84_latitude, latitude) AS latitude, IF({$condition}, wgs84_longitude, longitude) ".
                        "AS longitude, IF({$condition}, 'COMMUNE', 'STATION') AS type_site, 'floradata' AS source ".
                        "FROM cel_obs  LEFT JOIN cel_zones_geo cz ON ce_zone_geo=id_zone_geo ".
                        "WHERE transmission=1 ".
                        $this->construireWhereDepartement().' '.
                        $this->construireWhereAuteur().' '.
                        $this->construireWhereDate().' '.
                        $this->construireWhereReferentiel().' '.
                        $this->construireWhereTaxon().' '.
                        $this->construireWhereCoordonneesBbox().' '.
                        "GROUP BY IF({$condition},wgs84_longitude,longitude), IF({$condition},wgs84_latitude,latitude)";
                return $requete;
        }
        
        final protected function construireRequeteObservations() {
                $requete =
                        "SELECT id_observation AS id_obs, nom_sel_nn AS nn, nom_referentiel, lieudit, milieu, ".
                        "(DATE(IF(date_observation != '0000-00-00 00:00:00', date_observation, date_transmission))) AS date, ".
                        "CONCAT(prenom_utilisateur, ' ', nom_utilisateur) AS observateur, ce_utilisateur AS observateurId, ".
                        "IF(nom_sel IS NULL, 'A identifier',nom_sel) AS nomSci, 'floradata' AS projet ".
                        "FROM cel_obs WHERE transmission=1 ".
                        $this->construireWhereAuteur().' '.
                        $this->construireWhereReferentiel().' '.
                        $this->construireWhereDate().' '.
                        $this->construireWhereTaxon().' '.
                        $this->construireWhereCoordonneesPoint().' '.
                        "ORDER BY IF(nom_sel IS NULL, 'A identifier',nom_sel), date, observateur";
                return $requete;
        }
        
        final protected function construireRequeteWfs() {
                $condition = "(longitude IS NULL OR latitude IS NULL OR (longitude=0 AND latitude=0) ".
                        "OR longitude>180 OR latitude>90 OR mots_cles_texte LIKE '%sensible%')";
                $requete =
                "SELECT nom_sel AS taxon, ce_zone_geo, zone_geo, station, 'floradata' AS source, ".
                "IF({$condition}, wgs84_latitude, latitude) AS latitude, IF({$condition}, wgs84_longitude, longitude) ".
                "AS longitude, IF({$condition}, 'commune', 'station') AS type_site, ".
                "CONCAT(prenom_utilisateur, ' ', nom_utilisateur) AS auteur ".
                "FROM cel_obs  LEFT JOIN cel_zones_geo cz ON ce_zone_geo=id_zone_geo ".
                "WHERE transmission=1 ".
                $this->construireWhereCoordonneesBbox().' '.
                $this->construireWhereNomScientifique().' '.
                "ORDER BY IF({$condition},wgs84_longitude,longitude), IF({$condition},wgs84_latitude,latitude)";
                return $requete;
        }
        
        private function construireWhereTaxon() {
                $sql = '';
                if (isset($this->criteresRecherche->taxon)) {
                        $taxons = $this->criteresRecherche->taxon;
                        $criteres = array();
                        foreach ($taxons as $taxon) {
                                if ($taxon['rang'] == Config::get('rang.famille')) {
                                        $criteres[] = "famille=".$this->getBdd()->proteger($taxon['nom']);
                                } elseif ($taxon['rang'] == Config::get('rang.genre')) {
                                        $criteres[] = "nom_sel LIKE ".$this->getBdd()->proteger($taxon['nom']." %");
                                } else {
                                        $sousTaxons = $this->concatenerSynonymesEtSousEspeces($taxon);
                                        $criteres[] = "nt IN (".implode(',', $sousTaxons).")";
                                }
                        }
                        $sql = "AND (".implode(' OR ',array_unique($criteres)).")";
                }
                return $sql;
        }

        private function concatenerSynonymesEtSousEspeces($taxon) {
                $referentiel = new Referentiel($this->criteresRecherche->referentiel, $taxon);
                $sousTaxons = $referentiel->recupererSynonymesEtSousEspeces();
                $criteres = array();
                foreach ($sousTaxons as $sousTaxon) {
                        $criteres[] = $sousTaxon['nt'];
                }
                return array_unique($criteres);
        }
        
        private function construireWhereReferentiel() {
                $sql = '';
                if (isset($this->criteresRecherche->referentiel) && !isset($this->criteresRecherche->taxon)) {
                        $referentiel = current(explode('_', $this->criteresRecherche->referentiel));
                        $sql = "AND nom_referentiel LIKE ".$this->getBdd()->proteger($referentiel."%");
                }
                return $sql;
        }
        
        private function construireWhereDepartement() {
                $sql = '';
                if (isset($this->criteresRecherche->departement)) {
                        $valeurs_a_proteger = $this->criteresRecherche->departement;
                        foreach ($valeurs_a_proteger as $valeur) {
                                $valeurs_protegees[] = "ce_zone_geo LIKE " . $this->getBdd()->proteger('INSEE-C:' . $valeur . '%');
                        }
                        $valeurs = implode(' OR ', $valeurs_protegees);
                        $sql = "AND ($valeurs)";
                }
                return $sql;
        }
        
        private function construireWhereAuteur() {
                $sql = '';
                if (isset($this->criteresRecherche->auteur)) {
                        $utilisateur = $this->getBdd()->proteger($this->criteresRecherche->auteur);
                        $sql = "AND courriel_utilisateur = $utilisateur";
                }
                return $sql;
        }
        
        private function construireWhereDate() {
                $sql = '';
                if (isset($this->criteresRecherche->nbJours)) {
                        $nbJours = $this->criteresRecherche->nbJours;
                        $sql = "AND (Datediff(Curdate(), date_transmission)<={$nbJours})";
                } else {
                        $sql = $this->construireWhereDateDebutEtFin();
                }
                return $sql;
        }
        
        private function construireWhereDateDebutEtFin() {
                $sql = '';
                $dateDebut = isset($this->criteresRecherche->dateDebut) ? $this->criteresRecherche->dateDebut : null;
                $dateFin   = isset($this->criteresRecherche->dateFin) ? $this->criteresRecherche->dateFin : null;
                if (!is_null($dateDebut) || !is_null($dateFin)) {
                        $dateFin = !is_null($dateFin) ? $dateFin : date('Y-m-d');
                        $condition = '';
                        if ($dateDebut == $dateFin) {
                                $condition = "DATE(date_observation)=".$this->getBdd()->proteger($dateDebut);
                        } elseif (is_null($dateFin)) {
                                $condition = "DATE(date_observation)>=".$this->getBdd()->proteger($dateDebut);
                        } elseif (is_null($dateDebut)) {
                                $condition = "DATE(date_observation)<=".$this->getBdd()->proteger($dateFin);
                        } else {
                                $condition = "DATE(date_observation) BETWEEN ".$this->getBdd()->proteger($dateDebut)." ".
                                                "AND ".$this->getBdd()->proteger($dateFin);
                        }
                        $sql = "AND ($condition)";
                }
                return $sql;
        }
        
        private function construireWhereCoordonneesBbox() {
                $sql = '';
                if (isset($this->criteresRecherche->bbox)) {
                        $sql = "AND (".
                                "(".$this->genererCritereWhereBbox('').") OR (".
                                        "(longitude IS NULL OR latitude IS NULL OR (longitude=0 AND latitude=0) ".
                                        "OR longitude>180 OR latitude>90 OR mots_cles_texte LIKE '%sensible%') AND ".
                                        $this->genererCritereWhereBbox('wgs84_').
                                ")".
                        ")";
                }
                return $sql;
        }
        
        private function genererCritereWhereBbox($suffixe) {
                $bboxRecherche = $this->criteresRecherche->bbox;
                $conditions = array();
                $sql = '';
                foreach ($bboxRecherche as $bbox) {
                        $conditions[] = "({$suffixe}latitude BETWEEN ".$bbox['sud']." AND ".$bbox['nord']." ".
                                "AND {$suffixe}longitude BETWEEN ".$bbox['ouest']." AND ".$bbox['est'].")";
                }
                if (count($conditions) > 0) {
                        $sql = '('.implode(' OR ', $conditions).')';
                }
                return $sql;
        }
        
        private function construireWhereNomScientifique() {
                $sql = '';
                if (isset($this->criteresRecherche->filtre)) {
                        $filtre = $this->criteresRecherche->filtre;
                        $valeur = "'{$filtre['valeur']}".($filtre['operateur'] == 'LIKE' ? "%" : "")."'";
                        switch ($filtre['champ']) {
                                case "taxon" : $sql = "AND nom_sel {$filtre['operateur']} {$valeur}"; break;
                        }
                }
                return $sql;
        }
        
        private function construireWhereCoordonneesPoint() {
                $sql = '';
                $conditions = array();
                foreach ($this->criteresRecherche->stations as $station) {
                        if ($station[0] == $this->nomSource) {
                                $longitude = str_replace(",", ".", strval($station[3]));
                                $latitude  = str_replace(",", ".", strval($station[2]));
                                if ($station[1] == 'station') {
                                        $conditions[] = "(longitude=".$longitude." AND latitude=".$latitude." ".
                                                "AND (mots_cles_texte IS NULL OR mots_cles_texte NOT LIKE '%sensible%'))";
                                } else {
                                        $commune = $this->obtenirCoordonneesCommune($longitude, $latitude);
                                        $conditions[] =
                                        "(".
                                                "((longitude IS NULL OR latitude IS NULL) OR (longitude=0 AND latitude=0) ".
                                                "OR longitude>180 OR latitude>90 OR mots_cles_texte LIKE '%sensible%') ".
                                                "AND ce_zone_geo=".$this->getBdd()->proteger($commune['id_zone_geo']).
                                        ")";
                                }
                        }
                }
                if (count($conditions) > 0) {
                        $sql = "AND (".implode(" OR ", $conditions).")";
                }
                return $sql;    
        }
        
        private function obtenirCoordonneesCommune($longitude, $latitude) {
                $requete = "SELECT id_zone_geo, nom FROM cel_zones_geo WHERE wgs84_longitude=$longitude ".
                        "AND wgs84_latitude=$latitude";
                $commune = $this->getBdd()->recuperer($requete);
                if ($commune === false) {
                        $commune = null;
                }
                return $commune;
        }
        
        final protected function obtenirNomsStationsSurPoint() {
                // verifier si les coordonnees du point de requetage correspondent a une commune 
                $coordonnees = $this->recupererCoordonneesPremiereStation();
                $station = $this->obtenirCoordonneesCommune($coordonnees[0], $coordonnees[1]);
                if (is_null($station)) {
                        $requete = 'SELECT DISTINCT lieudit AS nom FROM cel_obs WHERE longitude='.
                                $coordonnees[0].' AND latitude='.$coordonnees[1];
                        $station = $this->getBdd()->recuperer($requete);
                }
                $nomStation = '';
                if ($station !== false) {
                        $nomStation = trim($station['nom']);
                }
                return $nomStation;
        }
        
        private function recupererCoordonneesPremiereStation() {
                $coordonnees = null;
                foreach ($this->criteresRecherche->stations as $station) {
                        if ($station[0] == $this->nomSource) {
                                $longitude = str_replace(",", ".", strval($station[3]));
                                $latitude  = str_replace(",", ".", strval($station[2]));
                                $coordonnees = array($longitude, $latitude);
                        }
                }
                return $coordonnees;
        }
        
}

?>