/trunk/services/bibliotheque/VerificateurParametres.php |
---|
New file |
0,0 → 1,474 |
<?php |
/** |
* Classe commune a tous les services de ce projet qui va analyser et rechercher des erreurs |
* sur les valeurs passees en parametres lors d'un appel a ces web services. |
* |
* Les parametres suivants sont traites : |
* - zoom : le niveau de zoom sur la carte (API cartographique client) |
* On va verifier que c'est un nombre entier compris entre une valeur minimale et une valeur maximale |
* |
* - bbox : rectangle dont les bords delimitent en coordonnees l'espace de recherche de donnees spatiales |
* L'ordre des valeurs est le suivant : ouest, sud, est, nord |
* On va verifier que c'est une serie de quatre nombre decimaux delimites par des virgules |
* et compris dans l'espace representant le monde a partir du systeme de projection WGS84 (EPSG:4326) |
* |
* - stations : liste de points d'observations. C'est une serie de stations qui est passee en parametres |
* de cette maniere, separees entre elles par un seperateur vertical |. Chaque station est decrite |
* par sa source de donnees, le type de site et ses coordonnees longitude et latitude. |
* |
* - referentiel : referentiel taxonomique a utiliser. On peut passer aussi bien en parametres |
* son nom court que son nom complet (incluant le numero de version) |
* On va verifier la disponibilite du referentiel pour ce service |
* |
* - num_taxon : numero taxonomique d'une espece |
* - nn : numero nomenclatural d'une espece |
* On va rechercher sa presence dans les referentiels disponibles |
* (les informations principales sur ce taxon seront renvoyees) |
* |
* - dept : une liste de numeros de departements separees entre eux par des virgules |
* On va verifier que chaque numero est un nombre entier et represente un code de departement valide |
* |
* - auteur : l'auteur de l'observation |
* |
* - date_debut et date_fin : intervalle de dates d'observation. On verifie que ce sont des dates valides |
* et que date_debut <= date_fin. Le programme peut accepter la presence d'un seul de ces deux |
* parametres : soit une date de debut, soit une date de fin |
* |
* - nb_jours : valeur entiere qui indique de recuperer les observations effectuees ou transmises |
* sur les derniers jours avant la date d'execution du script |
* |
* La fonction principale de verification des parametres va parcourir tous les parametres, et verifier |
* pour chacun d'eux la validite de leurs valeurs. Dans le cas ou une valeur anormale est detectee |
* ou qu'elle se trouve en dehors de l'intervalle des resultats acceptes, une liste de messages d'erreur |
* sera generee et mise a jour. |
* |
* Le resultat final de la verfication peut entrainer deux cas d'utilisation possibles. Si des messages |
* d'erreurs ont ete generes durant la verification, ils sont regroupes en un seul message pour lever |
* une exception qui sera interpretee par la classe appelante. Dans le cas ou la verification n'a rien |
* rencontre d'anormal, une fonction renverra la liste des parametres valides utilisables |
* pour des recherches de donnees pour la suite du traitement pour le service. |
* |
* @package framework-0.3 |
* @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) |
* |
*/ |
class VerificateurParametres { |
private $parametres = array(); |
private $validation = null; |
private $erreurs = array(); |
private $dateTraitee = false; |
private $bboxMonde = null; |
public function __construct($parametres) { |
foreach ($parametres as $nomParametre => $valeur) { |
$this->parametres[$nomParametre] = $valeur; |
} |
$this->bboxMonde = array( |
'ouest' => floatval(Config::get('carte.limite_ouest')), |
'est' => floatval(Config::get('carte.limite_est')), |
'sud' => floatval(Config::get('carte.limite_sud')), |
'nord' => floatval(Config::get('carte.limite_nord')) |
); |
$this->validation = new StdClass(); |
} |
public function verifierParametres() { |
foreach ($this->parametres as $nomParametre => $valeur) { |
switch ($nomParametre) { |
case 'zoom' : $this->traiterParametreZoom($valeur); |
break; |
case 'bbox' : $this->traiterParametreBbox($valeur); |
break; |
case 'stations' : $this->traiterParametreStations($this->parametres['stations']); |
break; |
case 'dept' : $this->traiterParametreDepartement($valeur); |
break; |
case 'auteur' : $this->traiterParametreAuteur($valeur); |
break; |
case 'referentiel' : $this->traiterParametreReferentiel($valeur); |
break; |
case 'num_taxon' : $this->traiterParametreTaxon($valeur); |
break; |
case 'nn' : $this->traiterParametreNomenclatural($valeur); |
break; |
case 'type_site' : $this->traiterParametreTypeSite($valeur); |
break; |
case 'nb_jours' : $this->traiterParametreNbJours($valeur); |
break; |
case 'date_debut' : |
case 'date_fin' : { |
$dateDebut = isset($this->parametres['date_debut']) ? $this->parametres['date_debut'] : null; |
$dateFin = isset($this->parametres['date_fin']) ? $this->parametres['date_fin'] : null; |
if (!$this->dateTraitee) { |
$this->traiterParametresDate($dateDebut, $dateFin); |
$this->dateTraitee = true; |
} |
break; |
} |
case 'format' : $this->validation->format = strtolower($valeur); break; |
// autres parametres ==> les ignorer |
default : break; |
} |
} |
$this->verifierPresenceParametreSpatial(); |
} |
private function ajouterErreur($messageErreur) { |
$this->erreurs[] = $messageErreur; |
} |
public function renvoyerResultatVerification() { |
return $this->validation; |
} |
public function contienterreurs() { |
return count($this->erreurs); |
} |
public function leverException() { |
$messagesErreur = "Les erreurs suivantes ont été rencontrées : \n". |
implode("\n", $this->erreurs); |
throw new Exception($messagesErreur, RestServeur::HTTP_CODE_MAUVAISE_REQUETE); |
} |
// ------------------------------------------------------------------------- // |
// Fonctions de verification de parametres et detection de valeurs anormales // |
// ------------------------------------------------------------------------- // |
private function traiterParametreZoom($zoom) { |
$zoom = intval($zoom); |
$mondeZoom = array( |
'min' => intval(Config::get('carte.zoom_minimal')), |
'max' => intval(Config::get('carte.zoom_maximal')) |
); |
if ($zoom < $mondeZoom['min'] || $zoom > $mondeZoom['max']) { |
$message = 'Niveau de zoom non reconnu par le service. Il doit être compris entre '. |
$mondeZoom['min'].' et '.$mondeZoom['max']; |
$this->ajouterErreur($message); |
} else { |
$this->validation->zoom = $zoom; |
} |
} |
private function traiterParametreBbox($chaineBbox) { |
$listeBbox = explode('|', trim($chaineBbox)); |
$critereBbox = array(); |
foreach ($listeBbox as $bbox) { |
$bboxVerifiee = $this->verifierCoordonneesBbox($bbox); |
if (!is_null($bboxVerifiee)) { |
$critereBbox[] = $bboxVerifiee; |
} |
} |
$this->validation->bbox = $critereBbox; |
} |
private function verifierCoordonneesBbox($bbox) { |
$bboxVerifiee = null; |
// verifier que la chaine de caracteres $bbox est une serie de chaque nombre decimaux |
// separes entre eux par une virgule |
if (preg_match('/^(-?\d{1,3}(.\d+)?,){3}(-?\d{1,3}(.\d+)?)$/', $bbox) == 0) { |
$message = "Format de saisie des coordonnees de la bounding box non valide. Le service ". |
"n'accepte seulement qu'une serie de 4 nombre décimaux séparés par des virgules."; |
$this->ajouterErreur($message); |
} else { |
$coordonnees = explode(',', $bbox); |
// index du tableau des coordonnees : ouest/sud/est/nord |
$nomsIndexBbox = array("ouest", "sud", "est", "nord"); |
$bbox = array(); |
for ($i = 0; $i < count($coordonnees); $i ++) { |
$bbox[$nomsIndexBbox[$i]] = $coordonnees[$i]; |
} |
// verifier que les coordonnees de chaque bord de la bbox sont valides |
if ($this->estUneBboxValide($bbox)) { |
$bboxVerifiee = $bbox; |
} else { |
$message = "Certaines coordonnées de la bounding box sont situés en dehors des limites ". |
"de notre monde"; |
$this->ajouterErreur($message); |
} |
} |
return $bboxVerifiee; |
} |
private function estUneBboxValide($bbox) { |
$monde = $this->bboxMonde; |
return (floatval($bbox['ouest']) >= $monde['ouest'] && floatval($bbox['ouest']) <= $monde['est'] |
&& floatval($bbox['est']) >= $monde['ouest'] && floatval($bbox['est']) <= $monde['est'] |
&& floatval($bbox['nord']) >= $monde['sud'] && floatval($bbox['nord']) <= $monde['nord'] |
&& floatval($bbox['sud']) >= $monde['sud'] && floatval($bbox['sud']) <= $monde['nord']); |
} |
private function traiterParametreStations($listeStations) { |
$stations = explode('|', trim($listeStations)); |
$critereStations = array(); |
foreach ($stations as $station) { |
preg_match("/([a-z]+):([a-z]+):(-?\d{1,3}.\d+),(-?\d{1,3}.\d+)/", $station, $matches); |
if (count($matches) < 5) { |
$message = "Les données transmises sur la station à interroger sont incomplètes. ". |
"Le format suivant doit être respecté : source:type_site:longitude:latitude"; |
$this->ajouterErreur($message); |
} else { |
$matches = array_splice($matches, 1, count($matches)); |
$this->verifierCoordonneesStation($matches); |
$this->verifierSourceStation($matches[0]); |
$this->verifierTypeStation($matches[1]); |
$critereStations[] = $matches; |
} |
} |
$this->validation->stations = $critereStations; |
} |
private function verifierCoordonneesStation(& $station) { |
$longitude = floatval($station[2]); |
$latitude = floatval($station[3]); |
if ($this->sontDesCoordonneesValides($longitude, $latitude)) { |
$station[2] = $latitude; |
$station[3] = $longitude; |
} else { |
$message = "Les coordonnees du point passées en parametres sont en dehors des limites de notre monde"; |
$this->ajouterErreur($message); |
} |
} |
private function sontDesCoordonneesValides($longitude, $latitude) { |
$monde = $this->bboxMonde; |
return (floatval($longitude) >= $monde['ouest'] && floatval($longitude) <= $monde['est'] |
&& floatval($latitude) >= $monde['sud'] && floatval($latitude) <= $monde['nord']); |
} |
private function verifierTypeStation($typeStation) { |
$typeStationsValides = array('station', 'commune'); |
if (!in_array($typeStation, $typeStationsValides)) { |
$message = "'$typeStation' n'est pas un type de station reconnu. Sont acceptés seulement 'station' et 'commune'."; |
$this->ajouterErreur($message); |
} |
} |
private function verifierSourceStation($source) { |
$sourcesARequeter = explode(',', trim($this->parametres['source'])); |
if (!in_array($source, $sourcesARequeter)) { |
$message = "La source '$source' n'est pas listée dans le paramètre source de l'URL (sont disponibles ". |
implode(',', $sourcesARequeter).")."; |
$this->ajouterErreur($message); |
} |
} |
private function traiterParametreDepartement($numeroDepartement) { |
if ($numeroDepartement != '*') { |
$departements = explode(',', trim($numeroDepartement)); |
foreach ($departements as $departement) { |
if($this->estUnCodeDepartementValide($departement)) { |
$this->validation->departement[] = $departement; |
} else { |
$message = "Code de département non valide"; |
$this->ajouterErreur($message); |
} |
} |
} |
} |
private function estUnCodeDepartementValide($departement) { |
// expression reguliere pour verifier que c'est un nombre entier a 2 ou 3 chiffres |
$estUnDepartementValide = true; |
if ($departement == '2A' || $departement == '2B') { |
$estUnDepartementValide = true; |
} elseif (preg_match('/^\d{2,3}$/', $departement) != 1) { |
$estUnDepartementValide = false; |
} else { |
if ((intval($departement) < 1 || intval($departement) > 95) |
&& (intval($departement) < 971 || intval($departement) > 978)) { |
$estUnDepartementValide = false; |
} |
} |
return $estUnDepartementValide; |
} |
private function traiterParametreAuteur($auteur) { |
if ($auteur != '*') { |
$this->validation->auteur = trim($auteur); |
} |
} |
private function traiterParametreTypeSite($typeSite) { |
$this->validation->typeSite = strtolower(trim($typeSite)); |
} |
private function traiterParametreReferentiel($referentiel) { |
if (!isset($this->validation->referentiel) && $referentiel != '*') { |
$referentielAUtiliser = $this->affecterNomCompletReferentiel($referentiel); |
if (is_null($referentielAUtiliser)) { |
$message = "Le référentiel demandé n'est pas reconnu par le service."; |
$this->ajouterErreur($message); |
} else { |
$this->validation->referentiel = $referentielAUtiliser; |
} |
} |
} |
private function affecterNomCompletReferentiel($referentiel) { |
$referentielAUtiliser = null; |
$listeReferentiels = Referentiel::recupererListeReferentielsDisponibles(); |
foreach ($listeReferentiels as $nomReferentiel) { |
$nomCourtReferentiel = current(explode('_', $nomReferentiel)); |
if ($referentiel == $nomCourtReferentiel || $referentiel == $nomReferentiel) { |
$referentielAUtiliser = $nomReferentiel; |
break; |
} |
} |
return $referentielAUtiliser; |
} |
private function traiterParametreTaxon($numeroTaxon) { |
if ($numeroTaxon != '*') { |
$listeTaxons = explode(',', $numeroTaxon); |
foreach ($listeTaxons as $nt) { |
$taxon = null; |
if (isset($this->validation->referentiel)) { |
$taxon = $this->renvoyerTaxonDansReferentiel($nt, 'nt', $this->validation->referentiel); |
} else { |
$taxon = $this->rechercherTaxonDansReferentiels($nt, 'nt'); |
} |
if (is_null($taxon)) { |
$message = "Le numéro de taxon n'a pas permis de retrouver le taxon associé."; |
$this->ajouterErreur($message); |
} else { |
$this->ajouterTaxonAListe($taxon); |
$this->validation->referentiel = $taxon['referentiel']; |
} |
} |
} |
} |
private function traiterParametreNomenclatural($numeroNomenclatural) { |
if ($numeroNomenclatural != '*') { |
$listeTaxons = explode(',', $numeroNomenclatural); |
foreach ($listeTaxons as $nn) { |
$taxon = null; |
if (isset($this->validation->referentiel)) { |
$taxon = $this->renvoyerTaxonDansReferentiel($nn, 'nn', $this->validation->referentiel); |
} else { |
$taxon = $this->rechercherTaxonDansReferentiels($nn, 'nn'); |
} |
if (is_null($taxon)) { |
$message = "Le numéro nomenclatural n'a pas permis de retrouver le taxon associé."; |
$this->ajouterErreur($message); |
} else { |
$this->ajouterTaxonAListe($taxon); |
$this->validation->referentiel = $taxon['referentiel']; |
} |
} |
} |
} |
private function rechercherTaxonDansReferentiels($numeroTaxon, $typeNumero) { |
$taxon = null; |
$listeReferentiels = Referentiel::recupererListeReferentielsDisponibles(); |
foreach ($listeReferentiels as $nomReferentiel) { |
$taxon = $this->renvoyerTaxonDansReferentiel($numeroTaxon, $typeNumero, $nomReferentiel); |
if (!is_null($taxon)) { |
break; |
} |
} |
return $taxon; |
} |
private function renvoyerTaxonDansReferentiel($numeroTaxon, $typeNumero, $nomReferentiel) { |
$referentiel = new Referentiel($nomReferentiel); |
$referentiel->chargerTaxon($typeNumero, $numeroTaxon); |
$taxon = $referentiel->renvoyerTaxon(); |
return $taxon; |
} |
private function ajouterTaxonAListe($taxon) { |
if (!isset($this->validation->taxon)) { |
$this->validation->taxon = array($taxon); |
} elseif (!in_array($taxon, $this->validation->taxon)) { |
$this->validation->taxon[] = $taxon; |
} |
} |
private function traiterParametresDate($dateDebut, $dateFin) { |
$statutValidite = $this->verifierValiditeDate($dateDebut, 'début') |
+ $this->verifierValiditeDate($dateFin, 'fin'); |
if ($statutValidite == 2) { |
if (!is_null($dateDebut) && !is_null($dateFin) && $dateDebut > $dateFin) { |
$message = "Intervalle de dates incorrect : date de fin avant la date de début"; |
$this->ajouterErreur($message); |
} else { |
$this->validation->dateDebut = $dateDebut; |
$this->validation->dateFin = $dateFin; |
} |
} |
} |
private function verifierValiditeDate(& $date, $position) { |
$statutValidite = is_null($date) ? 1 : 0; |
$moisParDefaut = $position == 'début' ? 1 : 12; |
$jourParDefaut = $position == 'début' ? 1 : 31; |
if (!is_null($date)) { |
$split = explode("-", $date); |
$annee = intval($split[0]); |
$mois = isset($split[1]) ? intval($split[1]) : $moisParDefaut; |
$jour = isset($split[2]) ? intval($split[2]) : $jourParDefaut; |
if (!$this->estDateValide($jour, $mois, $annee)) { |
$message = "Date de {$position} saisie non valide"; |
$this->ajouterErreur($message); |
} else { |
$date = $annee."-".(($mois<10)?"0".$mois:$mois)."-".(($jour<10)?"0".$jour:$jour); |
$dateDuJour = date('Y-m-d'); |
if ($date > $dateDuJour) { |
$message = "La date de {$position} saisie postérieure à la date du jour : {$dateDuJour}"; |
$this->ajouterErreur($message); |
} else { |
$statutValidite = 1; |
} |
} |
} |
return $statutValidite; |
} |
private function estDateValide($jour, $mois, $annee) { |
$estBissextile = (($annee % 4 == 0 && $annee % 100 != 0) || ($annee % 400 == 0)); |
$dureeFevrier = $estBissextile ? 29 : 28; |
$dureeMois = array(1 => 31, 2 => $dureeFevrier, 3 => 31, 4 => 30, 5 => 31, 6 => 30, 7 => 31, |
8 => 31, 9 => 30, 10 => 31, 11 => 30, 12 => 31); |
return ($annee >= 1900 && $mois >= 1 && $mois <= 12 && $jour >= 1 && $jour <= $dureeMois[$mois]); |
} |
private function verifierPresenceParametreSpatial() { |
$presenceParametreSpatial = false; |
if (isset($this->parametres['bbox']) |
|| (isset($this->parametres['stations']))) { |
$presenceParametreSpatial = true; |
} |
if ($presenceParametreSpatial == false) { |
$message = "Aucune coordonnée n'a été saisie"; |
$this->ajouterErreur($message); |
} |
} |
private function traiterParametreNbJours($nbJours) { |
// verifier que c'est un nombre entier positif (avec expression reguliere) |
if (preg_match('/^\d+$/', $nbJours) != 1) { |
$message = "La valeur passée pour le nombre de jours doit être un entier positif."; |
$this->ajouterErreur($message); |
} elseif ($nbJours > 0) { |
$this->validation->nbJours = intval($nbJours); |
} |
} |
} |
?> |
/trunk/services/bibliotheque/FormateurJson.php |
---|
New file |
0,0 → 1,166 |
<?php |
class FormateurJson { |
public function __construct() {} |
public function formaterStations($stations) { |
$objetJSON = new StdClass(); |
$objetJSON->type = "FeatureCollection"; |
$objetJSON->stats = new StdClass(); |
$objetJSON->stats->source = array(); |
$objetJSON->stats->formeDonnees = ''; |
if (count($stations) > 0) { |
$objetJSON->stats->formeDonnees = ($stations[0]['type_site'] == 'MAILLE') ? 'maille' : 'point'; |
} |
$objetJSON->stats->stations = 0; |
$objetJSON->stats->observations = 0; |
$objetJSON->features = array(); |
foreach ($stations as $station) { |
$stationJSON = null; |
if ($station['type_site'] == 'MAILLE') { |
$stationJSON = $this->formaterMaille($station); |
$objetJSON->stats->stations += array_sum($station['stations']); |
$objetJSON->stats->observations += array_sum($station['observations']); |
} else { |
$stationJSON = $this->formaterPoint($station); |
$objetJSON->stats->stations ++; |
$objetJSON->stats->observations += $station['observations']; |
} |
$objetJSON->features[] = $stationJSON; |
$this->ajouterSourcesAuxStats($station, $objetJSON->stats); |
} |
return $objetJSON; |
} |
private function ajouterSourcesAuxStats($station, & $stats) { |
if ($station['type_site'] == 'MAILLE') { |
foreach ($station['stations'] as $source => $nombreStations) { |
if (!in_array($source, $stats->source)) { |
$stats->source[] = $source; |
} |
} |
} else { |
if (!in_array($station['source'], $stats->source)) { |
$stats->source[] = $station['source']; |
} |
} |
} |
private function formaterPoint(& $station) { |
$json = new StdClass(); |
$json->type = "Feature"; |
$json->geometry = new StdClass(); |
$json->properties = new StdClass(); |
$json->geometry->type = "Point"; |
$json->properties->source = $station['source']; |
$json->properties->typeSite = $station['type_site']; |
$json->geometry->coordinates = array($station['latitude'], $station['longitude']); |
$codeInsee = isset($station['code_insee']) ? $station['code_insee'] : substr($station['ce_zone_geo'],-5); |
$codeDepartement = $this->extraireCodeDepartement($codeInsee); |
$nom = ''; |
if ($station['source'] != 'floradata') { |
$json->properties->nom = trim($station['nom'])." ({$codeDepartement})"; |
} else { |
$station['station'] = (is_null($station['station']) || strlen(trim($station['station'])) == 0) |
? $station['zone_geo'] : $station['station']; |
$nom = $station['type_site'] == 'COMMUNE' ? $station['zone_geo'] : $station['station']; |
$json->properties->nom = trim($nom)." ({$codeDepartement})"; |
} |
return $json; |
} |
private function construireNomStation(& $station) { |
} |
private function extraireCodeDepartement($codeInsee) { |
$codeDepartement = substr($codeInsee, 0 ,2); |
if (intval($codeDepartement) > 95) { |
$codeDepartement = substr($codeInsee, 0 ,3); |
} |
return $codeDepartement; |
} |
private function formaterMaille($maille) { |
$json = new StdClass(); |
$json->type = "Feature"; |
$json->geometry = new StdClass(); |
$json->geometry->type = "Polygon"; |
$json->geometry->coordinates = array( |
array(floatval($maille['sud']), floatval($maille['ouest'])), |
array(floatval($maille['sud']), floatval($maille['est'])), |
array(floatval($maille['nord']), floatval($maille['est'])), |
array(floatval($maille['nord']), floatval($maille['ouest'])), |
array(floatval($maille['sud']), floatval($maille['ouest'])) |
); |
$json->properties = new StdClass(); |
$json->properties->source = array(); |
foreach ($maille['stations'] as $source => $nombreStations) { |
$json->properties->source[] = $source; |
} |
$json->properties->typeSite = 'MAILLE'; |
$json->properties->stations = $maille['stations']; |
$json->properties->observations = $maille['observations']; |
return $json; |
} |
public function formaterObservations($observations) { |
//print_r($observations); exit; |
$objetJSON = new StdClass(); |
$objetJSON->site = trim($observations[0]['nom_station']); |
$objetJSON->total = count($observations); |
$objetJSON->observations = array(); |
foreach ($observations as $observation) { |
$this->concatenerLieuObservation($observation); |
$observationJson = new stdClass(); |
foreach ($observation as $colonne => $valeur) { |
if ($colonne == 'nom_referentiel') { |
$observationJson->urlEflore = $this->genererUrlFicheEflore($observation); |
} else { |
$observationJson->$colonne = is_string($valeur) ? trim($valeur) : $valeur; |
} |
} |
$this->formaterDateObservation($observationJson); |
$objetJSON->observations[] = $observationJson; |
} |
return $objetJSON; |
} |
private function formaterDateObservation(& $observation) { |
if (isset($observation->date) && strlen($observation->date) > 4) { |
$dateFormatee = preg_replace('/(\d{4})-(\d{2})-(\d{2})/', '$3/$2/$1', $observation->date); |
$observation->date = $dateFormatee; |
} |
} |
private function genererUrlFicheEflore(& $observation) { |
$url = null; |
if (strstr($observation['nom_referentiel'], 'bdtfx') !== false) { |
$url = 'http://www.tela-botanica.org/bdtfx-nn-'.$observation['nn']; |
} |
return $url; |
} |
private function concatenerLieuObservation(& $observation) { |
$lieux = array(); |
if (isset($observation['lieudit']) && !is_null($observation['lieudit'])) { |
$lieux[] = $observation['lieudit']; |
} |
if (isset($observation['milieu']) && !is_null($observation['milieu'])) { |
$lieux[] = $observation['milieu']; |
} |
unset($observation['lieudit']); |
unset($observation['milieu']); |
$observation['lieu'] = implode(', ', $lieux); |
} |
} |
?> |
/trunk/services/bibliotheque/Maille.php |
---|
New file |
0,0 → 1,95 |
<?php |
class Maille { |
private $latitudeSud; |
private $longitudeOuest; |
private $latitudeNord; |
private $longitudeEst; |
private $indexLatitude; |
private $indexLongitude; |
private $stations = array(); |
private $observations = array(); |
public function __construct($sud, $ouest, $nord, $est, $indexLat, $indexLng) { |
$this->latitudeSud = $sud; |
$this->longitudeOuest = $ouest; |
$this->latitudeNord = $nord; |
$this->longitudeEst = $est; |
$this->indexLatitude = $indexLat; |
$this->indexLongitude = $indexLng; |
} |
public function ajouterStation($station, $source) { |
if (!array_key_exists($source, $this->stations)) { |
$this->stations[$source] = 1; |
$this->observations[$source] = $station['observations']; |
} else { |
$this->stations[$source] += 1; |
$this->observations[$source] += intval($station['observations']); |
} |
} |
public function getLatitudeNord() { |
return $this->latitudeNord; |
} |
public function getLongitudeOuest() { |
return $this->longitudeOuest; |
} |
public function getLatitudeSud() { |
return $this->latitudeSud; |
} |
public function getLongitudeEst() { |
return $this->longitudeEst; |
} |
public function getIndexLatitude() { |
return $this->indexLatitude; |
} |
public function getIndexLongitude() { |
return $this->indexLongitude; |
} |
public function getStations() { |
return $this->stations; |
} |
public function getNombreStations() { |
return count($this->stations); |
} |
public function getObservations() { |
return $this->observations; |
} |
public function combinerMailles($maille, $sourceReference) { |
if (is_array($maille['stations'])) { |
foreach ($maille['stations'] as $source => $nombreStations) { |
if (!array_key_exists($source, $this->stations)) { |
$this->stations[$source] = $nombreStations; |
$this->observations[$source] = $maille['observations'][$source]; |
} else { |
$this->stations[$source] += $nombreStations; |
$this->observations[$source] += $maille['observations'][$source]; |
} |
} |
} else { |
if (!array_key_exists($sourceReference, $this->stations)) { |
$this->stations[$sourceReference] = $maille['stations']; |
$this->observations[$sourceReference] = $maille['observations']; |
} else { |
$this->stations[$sourceReference] += $maille['stations']; |
$this->observations[$sourceReference] += $maille['observations']; |
} |
} |
} |
} |
?> |
/trunk/services/bibliotheque/EnteteHttp.php |
---|
New file |
0,0 → 1,7 |
<?php |
class EnteteHttp { |
public $code = RestServeur::HTTP_CODE_OK; |
public $encodage = 'utf-8'; |
public $mime = 'application/json'; |
} |
?> |
/trunk/services/bibliotheque/FormateurWfs.php |
---|
New file |
0,0 → 1,124 |
<?php |
class FormateurWfs { |
const TYPE_MIME = 'text/xml'; |
private $bbox = null; |
public function formaterGetCapabilities() { |
$nomFichierWfs = dirname(__FILE__).DS."squelettes".DS."GetCapabilities.tpl.xml"; |
return SquelettePhp::analyser($nomFichierWfs); |
} |
public function formaterDescribeFeatureType($sources) { |
$nomFichierWfs = dirname(__FILE__).DS."squelettes".DS."DescribeFeatureType.tpl.xml"; |
if (is_null($sources)) { |
$sources = Config::get('sources_dispo'); |
} |
$listeSources = is_array($sources) == 1 ? $sources : explode(',', $sources); |
$item = array('listeSources' => $listeSources); |
return SquelettePhp::analyser($nomFichierWfs, $item); |
} |
public function formaterGetFeature(& $stations, $sources) { |
$nomFichierWfs = dirname(__FILE__).DS."squelettes".DS."GetFeature.tpl.xml"; |
$this->bbox = array('ouest' => null, 'est' => null, 'sud' => null, 'nord'=> null); |
$stationsRetour = $this->mettreEnPageStations($stations); |
$listeSources = implode(',', $sources); |
$item = array('enveloppe' => $this->bbox, 'stations' => $stationsRetour, 'listeSources' => $listeSources); |
return SquelettePhp::analyser($nomFichierWfs, $item); |
} |
private function mettreEnPageStations(& $stations) { |
$station = array('longitude' => null, 'latitude' => null); |
$stationsRetour = array(); |
foreach ($stations as $stationBdd) { |
if ($this->estNonNul($stationBdd['longitude']) && $this->estNonNul($stationBdd['latitude']) |
&& ($stationBdd['longitude'] != $station['longitude'] || $stationBdd['latitude'] != $station['latitude'])) { |
if (isset($station['source'])) { |
if ($station['source'] == 'floradata') { |
$this->mettreEnPageStationFloradata($station); |
} else { |
$this->mettreEnPageStationMoissonnage($station); |
} |
$stationsRetour[] = $station; |
} |
foreach ($stationBdd as $cle => $valeur) { |
if ($cle != 'taxon' && $cle != 'auteur') { |
$station[$cle] = $valeur; |
} |
} |
$station['taxons'] = array(trim($stationBdd['taxon'])); |
$station['auteurs'] = array(trim($stationBdd['auteur'])); |
$this->mettreAJourBbox($station); |
} else { |
$station['taxons'][] = trim($stationBdd['taxon']); |
$station['auteurs'][] = trim($stationBdd['auteur']); |
} |
} |
return $stationsRetour; |
} |
private function estNonNul($valeur) { |
return (!is_null($valeur) && strlen(trim($valeur)) > 0); |
} |
private function mettreAJourBbox($station) { |
if (is_null($this->bbox['sud']) || floatval($station['latitude']) < floatval($this->bbox['sud'])) { |
$this->bbox['sud'] = $station['latitude']; |
} elseif (is_null($this->bbox['nord']) || floatval($station['latitude']) > floatval($this->bbox['nord'])) { |
$this->bbox['nord'] = $station['latitude']; |
} |
if (is_null($this->bbox['ouest']) || floatval($station['longitude']) < floatval($this->bbox['ouest'])) { |
$this->bbox['ouest'] = $station['longitude']; |
} elseif (is_null($this->bbox['est']) || floatval($station['longitude']) > floatval($this->bbox['est'])) { |
$this->bbox['est'] = $station['longitude']; |
} |
} |
private function mettreEnPageStationFloradata(& $station) { |
$station['nom_station'] = trim($station['station']); |
if ($this->estNonNul($station['zone_geo'])) { |
$station['nom_station'] .= ", ".$station['zone_geo']; |
} |
$station['nom_station'] = str_replace("&", "&", trim($station['nom_station'])); |
$station['departement'] = ''; |
$station['code_insee'] = ''; |
if ($this->estNonNul($station['ce_zone_geo'])) { |
$station['code_insee'] = substr($station['ce_zone_geo'], 8); |
$station['departement'] = substr($station['code_insee'],0, 2); |
if (intval($station['departement']) > 95) { |
$station['departement'] = substr($station['code_insee'],0, 2); |
} |
} |
unset($station['station']); |
unset($station['zone_geo']); |
unset($station['ce_zone_geo']); |
$station['taxons'] = str_replace("&", "&", implode(', ', $station['taxons'])); |
$station['auteurs'] = str_replace("&", "&", implode(', ', array_unique($station['auteurs']))); |
} |
private function mettreEnPageStationMoissonnage(& $station) { |
$station['nom_station'] = str_replace("&", "&", trim($station['nom'])); |
$station['departement'] = ''; |
if ($this->estNonNul($station['code_insee'])) { |
$station['departement'] = substr($station['code_insee'],0, 2); |
if (intval($station['departement']) > 95) { |
$station['departement'] = substr($station['code_insee'],0, 2); |
} |
} |
unset($station['nom']); |
$station['taxons'] = str_replace("&", "&", implode(', ', $station['taxons'])); |
$station['auteurs'] = str_replace("&", "&", implode(', ', array_unique($station['auteurs']))); |
} |
public function formaterException(Exception $erreur) { |
$nomFichierWfs = dirname(__FILE__).DS."squelettes".DS."Exception.tpl.xml"; |
$item = array('message' => $erreur->getMessage()); |
return SquelettePhp::analyser($nomFichierWfs, $item); |
} |
} |
?> |
/trunk/services/bibliotheque/Referentiel.php |
---|
New file |
0,0 → 1,155 |
<?php |
/** |
* Classe qui va effectuer toutes les operations liees aux referentiels ou rechercher |
* des informations sur les taxons dans les tables des referentiels dans la base de donnees |
* |
* Operations a utiliser : |
* - recupererListeReferentielsDisponibles (statique) : recherche dans les fichiers de configuration |
* la liste des referentiels disponibles et les renvoie dans un tableau |
* |
* - chargerTaxon : recherche dans la table possedant le meme nom que le nom du referentiel en attribut |
* les informations generales sur un taxon (numero nomenclatural retenu, numero taxonomique, |
* nom scientifique, rang) a partir de son numero taxonomique |
* On stockera dans un attribut un tableau associatif contenant ces informations + le nom du referentiel, |
* ou la valeur nulle si aucun taxon n'a ete trouve |
* |
* - recupererSousTaxons : a partir du numero nomenclatural d'un taxon, la fonction va recuperer |
* tous les taxons de rang inferieur de maniere recursive jusqu'en ne plus en trouver de nouveaux |
* la recherche s'effectuera seulement au niveau des rangs famille, genre, espece et sous-espece |
* pour limiter le nombre d'informations qui sera a la fin renvoye |
* |
* - obtenirNumeroNomenclatural : recherche le numero nomenclatural d'un taxon a partir de son nom scientifique |
* |
* @package framework-0.3 |
* @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) |
* |
*/ |
class Referentiel { |
private $nomComplet; |
private $nomCourt; |
private $taxon; |
private $bdd = null; |
private $nomsChampsBdtfx = array('nn' => 'num_nom_retenu', 'nt' => 'num_taxonomique', 'ns' => 'nom_sci'); |
private $nomsChampsBdtxa = array('nn' => 'num_nom_retenu', 'nt' => 'num_tax', 'ns' => 'nom_sci'); |
private $champs; |
public function __construct($nomReferentiel, $taxon = null) { |
$this->nomComplet = $nomReferentiel; |
$this->nomCourt = current(explode('_', $nomReferentiel)); |
$proprieteChamps = 'nomsChamps' . ucfirst($this->nomCourt); |
foreach ($this->$proprieteChamps as $nomCourt => $nomChamp) { |
$this->champs[$nomCourt] = $nomChamp; |
} |
$this->taxon = $taxon; |
} |
public function renvoyerNomCompletReferentiel() { |
return $this->nomComplet; |
} |
public function renvoyerTaxon() { |
return $this->taxon; |
} |
public function chargerTaxon($typeNumero, $numTaxon) { |
$taxon = null; |
// verifier que le numero de taxon soit bien une chaine de caracteres composee uniquement |
// que de nombres entiers avant de construire la requete SQL a executer |
if (preg_match('/^\d+$/', $numTaxon) == 1) { |
$champWhere = $typeNumero == 'nt' ? $this->champs['nt']: 'num_nom'; |
$requete = |
"SELECT ".$this->champs['nn']." AS nn, ".$this->champs['nt']." AS nt, ". |
$this->champs['ns']." AS nom, rang FROM ".$this->nomComplet." WHERE ". |
$champWhere."={$numTaxon} AND num_nom=".$this->champs['nn']." ". |
"ORDER BY rang, If(num_nom=".$this->champs['nn'].", 0, 1) LIMIT 0, 1"; |
$taxon = $this->getBdd()->recuperer($requete); |
if ($taxon == false) { |
$taxon = null; |
} else { |
$taxon['referentiel'] = $this->nomComplet; |
} |
} |
$this->taxon = $taxon; |
} |
private function getBdd() { |
if (is_null($this->bdd)) { |
$this->bdd = new Bdd(); |
} |
$nomBdd = Config::get('bdd_nom'); |
$this->bdd->requeter("USE ".$nomBdd); |
return $this->bdd; |
} |
public function recupererSynonymesEtSousEspeces() { |
$sousTaxons = array(); |
if (!is_null($this->taxon) && $this->taxon['rang'] >= Config::get('rang.espece')) { |
$requete = |
"SELECT ".$this->champs['nn']." AS nn, ".$this->champs['nt']." AS nt, ". |
$this->champs['ns']." AS nom, rang FROM ".$this->nomComplet. " WHERE ". |
$this->champs['nt']."=".$this->taxon['nt']." OR hierarchie LIKE '%-".$this->champs['nn']."-%'"; |
$sousTaxons = $this->getBdd()->recupererTous($requete); |
} |
return $sousTaxons; |
} |
public function recupererGenres() { |
$sousTaxons = array(); |
if (!is_null($this->taxon) && $this->taxon['rang'] == Config::get('rang.famille')) { |
$requete = |
"SELECT ".$this->champs['nn']." AS nn, ".$this->champs['nt']." AS nt, ". |
$this->champs['ns']." AS nom, rang FROM ".$this->nomComplet. " WHERE ". |
"num_tax_sup=".$this->taxon['nn']." AND num_nom=".$this->champs['nn']; |
$sousTaxons = $this->getBdd()->recupererTous($requete); |
} |
return $sousTaxons; |
} |
public static function recupererListeReferentielsDisponibles() { |
$tableau = array(); |
$tableauPartiel = explode(',', Config::get('referentiels_dispo')); |
$tableauPartiel = array_map('trim', $tableauPartiel); |
foreach ($tableauPartiel as $champ) { |
if (strpos($champ, '=') === false) { |
$tableau[] = $champ; |
} else { |
list($cle, $val) = explode('=', $champ); |
$clePropre = trim($cle); |
$valeurPropre = trim($val); |
$tableau[$clePropre] = $valeurPropre; |
} |
} |
return $tableau; |
} |
public function obtenirNumeroNomenclatural($nomScientifique, $numeroNomenclatural = null) { |
$aProteger = $this->getBdd()->proteger(trim($nomScientifique) . '%'); |
$requete = "SELECT ".$this->champs['nn']." AS nn FROM ".$this->nomComplet." ". |
"WHERE ".$this->champs['ns']." LIKE ".$aProteger; |
if (!is_null($numeroNomenclatural) || strlen($numeroNomenclatural) > 0) { |
$requete .= " OR ".$this->champs['nn']."={$numeroNomenclatural}"; |
} |
$taxon = $this->getBdd()->recuperer($requete); |
if ($taxon == false) { |
$taxon = null; |
} else { |
$taxon['referentiel'] = $this->nomComplet; |
} |
return $taxon; |
} |
} |
?> |
/trunk/services/bibliotheque/ResultatService.php |
---|
New file |
0,0 → 1,9 |
<?php |
class ResultatService { |
public $mime = 'application/json'; |
public $encodage = 'utf-8'; |
public $corps = ''; |
} |
?> |
/trunk/services/bibliotheque/CacheMoissonnage.php |
---|
New file |
0,0 → 1,70 |
<?php |
class CacheMoissonnage { |
private $service; |
private $config; |
private $dureecache = 0; |
private $serviceNom; |
private $cache; |
private $cacheActif; |
public function __construct($service, $serviceNom, $cacheActif) { |
$this->cacheActif = $cacheActif; |
$this->service = $service; |
$this->chargerDureeCache(); |
$this->serviceNom = $serviceNom; |
$this->cache = new CacheSimple(array( |
"mise_en_cache" => true, |
"stockage_chemin" => Config::get("chemincache"), |
"duree_de_vie" => $this->dureecache |
)); |
} |
public function chargerDureeCache() { |
if ($this->cacheActif == "1") { |
$this->dureecache = $this->service->getDureeCache(); |
} |
} |
public function consulter($ressources, $parametres) { |
$id = $this->genererID($ressources, $parametres); |
$retour = unserialize($this->cache->charger($id)); |
if ($retour == false) { |
$retour = $this->mettreEnCache($ressources, $parametres); |
} |
return $retour; |
} |
public function mettreEnCache($ressources, $parametres) { |
$retour = $this->service->consulter($ressources, $parametres); |
$id = $this->genererID($ressources, $parametres); |
if ($this->dureecache > 0) { |
$this->cache->sauver(serialize($retour), $id); |
} |
return $retour; |
} |
public function genererID($ressources, $parametres) { |
$chaineRessources = ""; |
$chaineParametres = ""; |
if (count($ressources) > 0) { |
foreach ($ressources as $key => $val) { |
$chaineRessources .= "$key:$val;"; |
} |
} |
if (count($parametres) > 0) { |
foreach ($parametres as $key => $val) { |
$chaineParametres .= "$key:$val;"; |
} |
} |
$chaineMD5 = $this->serviceNom.'/'.md5($chaineRessources.$chaineParametres); |
return $chaineMD5; |
} |
} |
?> |
/trunk/services/bibliotheque/squelettes/GetCapabilities.tpl.xml |
---|
New file |
0,0 → 1,153 |
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'."\n"; ?> |
<wfs:WFS_Capabilities |
xmlns:gml="http://www.opengis.net/gml" |
xmlns:wfs="http://www.opengis.net/wfs" |
xmlns:ows="http://www.opengis.net/ows" |
xmlns:xlink="http://www.w3.org/1999/xlink" |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
xmlns:ogc="http://www.opengis.net/ogc" |
xmlns="http://www.opengis.net/wfs" |
version="1.1.0" |
xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd"> |
<ows:ServiceIdentification> |
<ows:Title>Observations Tela-Botanica</ows:Title> |
<ows:Abstract>Observations Tela-Botanica</ows:Abstract> |
<ows:Keywords> |
<ows:Keyword>Tela-Botanica</ows:Keyword> |
<ows:Keyword>Botanique</ows:Keyword> |
<ows:Keyword>Observation naturaliste</ows:Keyword> |
</ows:Keywords> |
<ows:ServiceType codeSpace="OGC">OGC WFS</ows:ServiceType> |
<ows:ServiceTypeVersion>1.1.0</ows:ServiceTypeVersion> |
<ows:Fees>none</ows:Fees> |
<ows:AccessConstraints>none</ows:AccessConstraints> |
</ows:ServiceIdentification> |
<ows:ServiceProvider> |
<ows:ProviderName>Association Tela-Botanica</ows:ProviderName> |
<ows:ProviderSite xlink:type="simple" xlink:href="http://tela-botanica.org" /> |
<ows:ServiceContact> |
<ows:IndividualName>Tela-Botanica</ows:IndividualName> |
<ows:ContactInfo> |
<ows:Phone> |
<ows:Voice>+33 467524122</ows:Voice> |
</ows:Phone> |
<ows:Address> |
<ows:DeliveryPoint>4, Rue de Belfort</ows:DeliveryPoint> |
<ows:City>Montpellier</ows:City> |
<ows:AdministrativeArea>Hérault (34)</ows:AdministrativeArea> |
<ows:PostalCode>34000</ows:PostalCode> |
<ows:Country>France</ows:Country> |
<ows:ElectronicMailAddress>accueil@tela-botanica.org</ows:ElectronicMailAddress> |
</ows:Address> |
<ows:Role>resourceProvider</ows:Role> |
</ows:ContactInfo> |
</ows:ServiceContact> |
</ows:ServiceProvider> |
<ows:OperationsMetadata> |
<ows:Operation name="GetCapabilities"> |
<ows:DCP> |
<ows:HTTP> |
<ows:Get xlink:type="simple" xlink:href="<?php echo Config::get('url_service_base'); ?>wfs" /> |
<ows:Post xlink:type="simple" xlink:href="<?php echo Config::get('url_service_base'); ?>wfs" /> |
</ows:HTTP> |
</ows:DCP> |
<ows:Parameter name="service"> |
<ows:Value>WFS</ows:Value> |
</ows:Parameter> |
<ows:Parameter name="AcceptVersions"> |
<ows:Value>1.1.0</ows:Value> |
</ows:Parameter> |
<ows:Parameter name="AcceptFormat"> |
<ows:Value>text/xml</ows:Value> |
</ows:Parameter> |
</ows:Operation> |
<ows:Operation name="DescribeFeatureType"> |
<ows:DCP> |
<ows:HTTP> |
<ows:Get xlink:type="simple" xlink:href="<?php echo Config::get('url_service_base'); ?>wfs" /> |
<ows:Post xlink:type="simple" xlink:href="<?php echo Config::get('url_service_base'); ?>wfs" /> |
</ows:HTTP> |
</ows:DCP> |
<ows:Parameter name="outputFormat"> |
<ows:Value>text/xml; subtype=gml/3.1.1</ows:Value> |
</ows:Parameter> |
</ows:Operation> |
<ows:Operation name="GetFeature"> |
<ows:DCP> |
<ows:HTTP> |
<ows:Get xlink:type="simple" xlink:href="<?php echo Config::get('url_service_base'); ?>wfs" /> |
<ows:Post xlink:type="simple" xlink:href="<?php echo Config::get('url_service_base'); ?>wfs" /> |
</ows:HTTP> |
</ows:DCP> |
<ows:Parameter name="resultType"> |
<ows:Value>results</ows:Value> |
</ows:Parameter> |
<ows:Parameter name="outputFormat"> |
<ows:Value>text/xml; subtype=gml/3.1.1</ows:Value> |
</ows:Parameter> |
</ows:Operation> |
</ows:OperationsMetadata> |
<FeatureTypeList> |
<Operations> |
<Operation>Query</Operation> |
</Operations> |
<FeatureType> |
<Name>floradata</Name> |
<Title>FloraData</Title> |
<Abstract>Base de données constituée d'observations publiques du Carnet en Ligne de Tela Botanica. URL : http://www.tela-botanica.org/appli:cel</Abstract> |
<DefaultSRS>EPSG:4326</DefaultSRS> |
<OutPutFormats> |
<Format>text/xml; subtype=gml/3.1.1</Format> |
</OutPutFormats> |
<ows:WGS84BoundingBox dimensions="2"> |
<ows:LowerCorner>-180 -90</ows:LowerCorner> |
<ows:UpperCorner>180 90</ows:UpperCorner> |
</ows:WGS84BoundingBox> |
</FeatureType> |
<FeatureType> |
<Name>sophy</Name> |
<Title>SOPHY, banque de données botaniques et écologiques</Title> |
<Abstract>Données issues de SOPHY, une banque de données botaniques et écologiques réalisée par P. DE RUFFRAY, H. BRISSE, G. GRANDJOUAN et E. GARBOLINO dans le cadre de l'Association d'Informatique Appliquée à la Botanique (A.I.A.B.). URL : http://sophy.u-3mrs.fr/</Abstract> |
<DefaultSRS>EPSG:4326</DefaultSRS> |
<OutPutFormats> |
<Format>text/xml; subtype=gml/3.1.1</Format> |
</OutPutFormats> |
<ows:WGS84BoundingBox dimensions="2"> |
<ows:LowerCorner>-180 -90</ows:LowerCorner> |
<ows:UpperCorner>180 90</ows:UpperCorner> |
</ows:WGS84BoundingBox> |
</FeatureType> |
<FeatureType> |
<Name>baznat</Name> |
<Title>BazNat - Flore</Title> |
<Abstract>Données issues des prospections flore de la base de données naturaliste du réseau BazNat. URL : http://www.baznat.net/</Abstract> |
<DefaultSRS>EPSG:4326</DefaultSRS> |
<OutPutFormats> |
<Format>text/xml; subtype=gml/3.1.1</Format> |
</OutPutFormats> |
<ows:WGS84BoundingBox dimensions="2"> |
<ows:LowerCorner>-180 -90</ows:LowerCorner> |
<ows:UpperCorner>180 90</ows:UpperCorner> |
</ows:WGS84BoundingBox> |
</FeatureType> |
</FeatureTypeList> |
<ogc:Filter_Capabilities> |
<ogc:Spatial_Capabilities> |
<ogc:SpatialOperators> |
<ogc:SpatialOperator name="BBOX"/> |
</ogc:SpatialOperators> |
</ogc:Spatial_Capabilities> |
<ogc:Scalar_Capabilities> |
<ogc:ComparisonOperators> |
<ogc:ComparisonOperator>EqualTo</ogc:ComparisonOperator> |
<ogc:ComparisonOperator>NotEqualTo</ogc:ComparisonOperator> |
<ogc:ComparisonOperator>Like</ogc:ComparisonOperator> |
</ogc:ComparisonOperators> |
</ogc:Scalar_Capabilities> |
</ogc:Filter_Capabilities> |
</wfs:WFS_Capabilities> |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/trunk/services/bibliotheque/squelettes/GetFeature.tpl.xml |
---|
New file |
0,0 → 1,31 |
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'."\n"; ?> |
<wfs:FeatureCollection |
xmlns:ms="http://mapserver.gis.umn.edu/mapserver" |
xmlns:gml="http://www.opengis.net/gml" |
xmlns:wfs="http://www.opengis.net/wfs" |
xmlns:ogc="http://www.opengis.net/ogc" |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
xsi:schemaLocation="http://mapserver.gis.umn.edu/mapserver <?php echo Config::get('url_service_base'); ?>wfs?service=wfs&version=1.1.0&request=DescribeFeatureType&typename=<?php echo $listeSources; ?> http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd"> |
<gml:boundedBy> |
<gml:Box srsName="EPSG:4326"> |
<gml:coordinates decimal="." cs="," ts=" "><?=$enveloppe['ouest']?>,<?=$enveloppe['sud']?>,<?=$enveloppe['est']?>,<?=$enveloppe['nord']?></gml:coordinates> |
</gml:Box> |
</gml:boundedBy> |
<?php foreach ($stations as $station) { ?> |
<gml:featureMember> |
<ms:<?=$station['source']?>> |
<ms:coordonnees> |
<gml:Point srsName="EPSG:4326"> |
<gml:coordinates decimal="." cs="," ts=" "><?=$station['longitude']?>,<?=$station['latitude']?></gml:coordinates> |
</gml:Point> |
</ms:coordonnees> |
<ms:nomStation><?=$station['nom_station']?></ms:nomStation> |
<ms:precision><?=$station['type_site']?></ms:precision> |
<ms:codeInsee><?=$station['code_insee']?></ms:codeInsee> |
<ms:departement><?=$station['departement']?></ms:departement> |
<ms:taxons><?=$station['taxons']?></ms:taxons> |
<ms:auteurs><?=$station['auteurs']?></ms:auteurs> |
</ms:<?=$station['source']?>> |
</gml:featureMember> |
<?php } ?> |
</wfs:FeatureCollection> |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/trunk/services/bibliotheque/squelettes/DescribeFeatureType.tpl.xml |
---|
New file |
0,0 → 1,29 |
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'."\n"; ?> |
<schema |
targetNamespace="http://mapserver.gis.umn.edu/mapserver" |
xmlns:ms="http://mapserver.gis.umn.edu/mapserver" |
xmlns:ogc="http://www.opengis.net/ogc" |
xmlns:xsd="http://www.w3.org/2001/XMLSchema" |
xmlns="http://www.w3.org/2001/XMLSchema" |
xmlns:gml="http://www.opengis.net/gml" |
elementFormDefault="qualified" version="0.1" > |
<import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/3.1.1/base/gml.xsd" /> |
<?php foreach ($listeSources as $source) { ?> |
<element name="<?=$source ?>" type="ms:<?=$source ?>Type" substitutionGroup="gml:_Feature" /> |
<complexType name="<?=$source ?>Type"> |
<complexContent> |
<extension base="gml:AbstractFeatureType"> |
<sequence> |
<element name="coordonnees" type="gml:Point" /> |
<element name="nomStation" type="string" /> |
<element name="precision" type="string" /> |
<element name="codeInsee" type="string" /> |
<element name="departement" type="string" /> |
<element name="taxons" type="string" /> |
<element name="auteurs" type="string" /> |
</sequence> |
</extension> |
</complexContent> |
</complexType> |
<?php } ?> |
</schema> |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/trunk/services/bibliotheque/squelettes/Exception.tpl.xml |
---|
New file |
0,0 → 1,7 |
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'."\n"; ?> |
<ows:ExceptionReport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ows="http://www.opengis.net/ows/1.1" version="1.1.0" xml:lang="en-US" xsi:schemaLocation="http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsExceptionReport.xsd"> |
xsi:schemaLocation="http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsExceptionReport.xsd"> |
<ows:Exception exceptionCode="typename" locator="InvalidParameterValue"> |
<ows:ExceptionText><?=$message?></ows:ExceptionText> |
</ows:Exception> |
</ows:ExceptionReport> |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/trunk/services/bibliotheque/JSON.php |
---|
New file |
0,0 → 1,806 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ |
/** |
* Converts to and from JSON format. |
* |
* JSON (JavaScript Object Notation) is a lightweight data-interchange |
* format. It is easy for humans to read and write. It is easy for machines |
* to parse and generate. It is based on a subset of the JavaScript |
* Programming Language, Standard ECMA-262 3rd Edition - December 1999. |
* This feature can also be found in Python. JSON is a text format that is |
* completely language independent but uses conventions that are familiar |
* to programmers of the C-family of languages, including C, C++, C#, Java, |
* JavaScript, Perl, TCL, and many others. These properties make JSON an |
* ideal data-interchange language. |
* |
* This package provides a simple encoder and decoder for JSON notation. It |
* is intended for use with client-side Javascript applications that make |
* use of HTTPRequest to perform server communication functions - data can |
* be encoded into JSON notation for use in a client-side javascript, or |
* decoded from incoming Javascript requests. JSON format is native to |
* Javascript, and can be directly eval()'ed with no further parsing |
* overhead |
* |
* All strings should be in ASCII or UTF-8 format! |
* |
* LICENSE: Redistribution and use in source and binary forms, with or |
* without modification, are permitted provided that the following |
* conditions are met: Redistributions of source code must retain the |
* above copyright notice, this list of conditions and the following |
* disclaimer. Redistributions in binary form must reproduce the above |
* copyright notice, this list of conditions and the following disclaimer |
* in the documentation and/or other materials provided with the |
* distribution. |
* |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED |
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN |
* NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
* DAMAGE. |
* |
* @category |
* @package Services_JSON |
* @author Michal Migurski <mike-json@teczno.com> |
* @author Matt Knapp <mdknapp[at]gmail[dot]com> |
* @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com> |
* @copyright 2005 Michal Migurski |
* @version CVS: $Id$ |
* @license http://www.opensource.org/licenses/bsd-license.php |
* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198 |
*/ |
/** |
* Marker constant for Services_JSON::decode(), used to flag stack state |
*/ |
define('SERVICES_JSON_SLICE', 1); |
/** |
* Marker constant for Services_JSON::decode(), used to flag stack state |
*/ |
define('SERVICES_JSON_IN_STR', 2); |
/** |
* Marker constant for Services_JSON::decode(), used to flag stack state |
*/ |
define('SERVICES_JSON_IN_ARR', 3); |
/** |
* Marker constant for Services_JSON::decode(), used to flag stack state |
*/ |
define('SERVICES_JSON_IN_OBJ', 4); |
/** |
* Marker constant for Services_JSON::decode(), used to flag stack state |
*/ |
define('SERVICES_JSON_IN_CMT', 5); |
/** |
* Behavior switch for Services_JSON::decode() |
*/ |
define('SERVICES_JSON_LOOSE_TYPE', 16); |
/** |
* Behavior switch for Services_JSON::decode() |
*/ |
define('SERVICES_JSON_SUPPRESS_ERRORS', 32); |
/** |
* Converts to and from JSON format. |
* |
* Brief example of use: |
* |
* <code> |
* // create a new instance of Services_JSON |
* $json = new Services_JSON(); |
* |
* // convert a complexe value to JSON notation, and send it to the browser |
* $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4))); |
* $output = $json->encode($value); |
* |
* print($output); |
* // prints: ["foo","bar",[1,2,"baz"],[3,[4]]] |
* |
* // accept incoming POST data, assumed to be in JSON notation |
* $input = file_get_contents('php://input', 1000000); |
* $value = $json->decode($input); |
* </code> |
*/ |
class Services_JSON |
{ |
/** |
* constructs a new JSON instance |
* |
* @param int $use object behavior flags; combine with boolean-OR |
* |
* possible values: |
* - SERVICES_JSON_LOOSE_TYPE: loose typing. |
* "{...}" syntax creates associative arrays |
* instead of objects in decode(). |
* - SERVICES_JSON_SUPPRESS_ERRORS: error suppression. |
* Values which can't be encoded (e.g. resources) |
* appear as NULL instead of throwing errors. |
* By default, a deeply-nested resource will |
* bubble up with an error, so all return values |
* from encode() should be checked with isError() |
*/ |
function Services_JSON($use = 0) |
{ |
$this->use = $use; |
} |
/** |
* convert a string from one UTF-16 char to one UTF-8 char |
* |
* Normally should be handled by mb_convert_encoding, but |
* provides a slower PHP-only method for installations |
* that lack the multibye string extension. |
* |
* @param string $utf16 UTF-16 character |
* @return string UTF-8 character |
* @access private |
*/ |
function utf162utf8($utf16) |
{ |
// oh please oh please oh please oh please oh please |
if(function_exists('mb_convert_encoding')) { |
return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16'); |
} |
$bytes = (ord($utf16{0}) << 8) | ord($utf16{1}); |
switch(true) { |
case ((0x7F & $bytes) == $bytes): |
// this case should never be reached, because we are in ASCII range |
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
return chr(0x7F & $bytes); |
case (0x07FF & $bytes) == $bytes: |
// return a 2-byte UTF-8 character |
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
return chr(0xC0 | (($bytes >> 6) & 0x1F)) |
. chr(0x80 | ($bytes & 0x3F)); |
case (0xFFFF & $bytes) == $bytes: |
// return a 3-byte UTF-8 character |
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
return chr(0xE0 | (($bytes >> 12) & 0x0F)) |
. chr(0x80 | (($bytes >> 6) & 0x3F)) |
. chr(0x80 | ($bytes & 0x3F)); |
} |
// ignoring UTF-32 for now, sorry |
return ''; |
} |
/** |
* convert a string from one UTF-8 char to one UTF-16 char |
* |
* Normally should be handled by mb_convert_encoding, but |
* provides a slower PHP-only method for installations |
* that lack the multibye string extension. |
* |
* @param string $utf8 UTF-8 character |
* @return string UTF-16 character |
* @access private |
*/ |
function utf82utf16($utf8) |
{ |
// oh please oh please oh please oh please oh please |
if(function_exists('mb_convert_encoding')) { |
return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8'); |
} |
switch(strlen($utf8)) { |
case 1: |
// this case should never be reached, because we are in ASCII range |
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
return $utf8; |
case 2: |
// return a UTF-16 character from a 2-byte UTF-8 char |
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
return chr(0x07 & (ord($utf8{0}) >> 2)) |
. chr((0xC0 & (ord($utf8{0}) << 6)) |
| (0x3F & ord($utf8{1}))); |
case 3: |
// return a UTF-16 character from a 3-byte UTF-8 char |
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
return chr((0xF0 & (ord($utf8{0}) << 4)) |
| (0x0F & (ord($utf8{1}) >> 2))) |
. chr((0xC0 & (ord($utf8{1}) << 6)) |
| (0x7F & ord($utf8{2}))); |
} |
// ignoring UTF-32 for now, sorry |
return ''; |
} |
/** |
* encodes an arbitrary variable into JSON format |
* |
* @param mixed $var any number, boolean, string, array, or object to be encoded. |
* see argument 1 to Services_JSON() above for array-parsing behavior. |
* if var is a strng, note that encode() always expects it |
* to be in ASCII or UTF-8 format! |
* |
* @return mixed JSON string representation of input var or an error if a problem occurs |
* @access public |
*/ |
function encode($var) |
{ |
switch (gettype($var)) { |
case 'boolean': |
return $var ? 'true' : 'false'; |
case 'NULL': |
return 'null'; |
case 'integer': |
return (int) $var; |
case 'double': |
case 'float': |
return (float) $var; |
case 'string': |
// STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT |
$ascii = ''; |
$strlen_var = strlen($var); |
/* |
* Iterate over every character in the string, |
* escaping with a slash or encoding to UTF-8 where necessary |
*/ |
for ($c = 0; $c < $strlen_var; ++$c) { |
$ord_var_c = ord($var{$c}); |
switch (true) { |
case $ord_var_c == 0x08: |
$ascii .= '\b'; |
break; |
case $ord_var_c == 0x09: |
$ascii .= '\t'; |
break; |
case $ord_var_c == 0x0A: |
$ascii .= '\n'; |
break; |
case $ord_var_c == 0x0C: |
$ascii .= '\f'; |
break; |
case $ord_var_c == 0x0D: |
$ascii .= '\r'; |
break; |
case $ord_var_c == 0x22: |
case $ord_var_c == 0x2F: |
case $ord_var_c == 0x5C: |
// double quote, slash, slosh |
$ascii .= '\\'.$var{$c}; |
break; |
case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): |
// characters U-00000000 - U-0000007F (same as ASCII) |
$ascii .= $var{$c}; |
break; |
case (($ord_var_c & 0xE0) == 0xC0): |
// characters U-00000080 - U-000007FF, mask 110XXXXX |
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$char = pack('C*', $ord_var_c, ord($var{$c + 1})); |
$c += 1; |
$utf16 = $this->utf82utf16($char); |
$ascii .= sprintf('\u%04s', bin2hex($utf16)); |
break; |
case (($ord_var_c & 0xF0) == 0xE0): |
// characters U-00000800 - U-0000FFFF, mask 1110XXXX |
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$char = pack('C*', $ord_var_c, |
ord($var{$c + 1}), |
ord($var{$c + 2})); |
$c += 2; |
$utf16 = $this->utf82utf16($char); |
$ascii .= sprintf('\u%04s', bin2hex($utf16)); |
break; |
case (($ord_var_c & 0xF8) == 0xF0): |
// characters U-00010000 - U-001FFFFF, mask 11110XXX |
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$char = pack('C*', $ord_var_c, |
ord($var{$c + 1}), |
ord($var{$c + 2}), |
ord($var{$c + 3})); |
$c += 3; |
$utf16 = $this->utf82utf16($char); |
$ascii .= sprintf('\u%04s', bin2hex($utf16)); |
break; |
case (($ord_var_c & 0xFC) == 0xF8): |
// characters U-00200000 - U-03FFFFFF, mask 111110XX |
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$char = pack('C*', $ord_var_c, |
ord($var{$c + 1}), |
ord($var{$c + 2}), |
ord($var{$c + 3}), |
ord($var{$c + 4})); |
$c += 4; |
$utf16 = $this->utf82utf16($char); |
$ascii .= sprintf('\u%04s', bin2hex($utf16)); |
break; |
case (($ord_var_c & 0xFE) == 0xFC): |
// characters U-04000000 - U-7FFFFFFF, mask 1111110X |
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$char = pack('C*', $ord_var_c, |
ord($var{$c + 1}), |
ord($var{$c + 2}), |
ord($var{$c + 3}), |
ord($var{$c + 4}), |
ord($var{$c + 5})); |
$c += 5; |
$utf16 = $this->utf82utf16($char); |
$ascii .= sprintf('\u%04s', bin2hex($utf16)); |
break; |
} |
} |
return '"'.$ascii.'"'; |
case 'array': |
/* |
* As per JSON spec if any array key is not an integer |
* we must treat the the whole array as an object. We |
* also try to catch a sparsely populated associative |
* array with numeric keys here because some JS engines |
* will create an array with empty indexes up to |
* max_index which can cause memory issues and because |
* the keys, which may be relevant, will be remapped |
* otherwise. |
* |
* As per the ECMA and JSON specification an object may |
* have any string as a property. Unfortunately due to |
* a hole in the ECMA specification if the key is a |
* ECMA reserved word or starts with a digit the |
* parameter is only accessible using ECMAScript's |
* bracket notation. |
*/ |
// treat as a JSON object |
if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) { |
$properties = array_map(array($this, 'name_value'), |
array_keys($var), |
array_values($var)); |
foreach($properties as $property) { |
if(Services_JSON::isError($property)) { |
return $property; |
} |
} |
return '{' . join(',', $properties) . '}'; |
} |
// treat it like a regular array |
$elements = array_map(array($this, 'encode'), $var); |
foreach($elements as $element) { |
if(Services_JSON::isError($element)) { |
return $element; |
} |
} |
return '[' . join(',', $elements) . ']'; |
case 'object': |
$vars = get_object_vars($var); |
$properties = array_map(array($this, 'name_value'), |
array_keys($vars), |
array_values($vars)); |
foreach($properties as $property) { |
if(Services_JSON::isError($property)) { |
return $property; |
} |
} |
return '{' . join(',', $properties) . '}'; |
default: |
return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS) |
? 'null' |
: new Services_JSON_Error(gettype($var)." can not be encoded as JSON string"); |
} |
} |
/** |
* array-walking function for use in generating JSON-formatted name-value pairs |
* |
* @param string $name name of key to use |
* @param mixed $value reference to an array element to be encoded |
* |
* @return string JSON-formatted name-value pair, like '"name":value' |
* @access private |
*/ |
function name_value($name, $value) |
{ |
$encoded_value = $this->encode($value); |
if(Services_JSON::isError($encoded_value)) { |
return $encoded_value; |
} |
return $this->encode(strval($name)) . ':' . $encoded_value; |
} |
/** |
* reduce a string by removing leading and trailing comments and whitespace |
* |
* @param $str string string value to strip of comments and whitespace |
* |
* @return string string value stripped of comments and whitespace |
* @access private |
*/ |
function reduce_string($str) |
{ |
$str = preg_replace(array( |
// eliminate single line comments in '// ...' form |
'#^\s*//(.+)$#m', |
// eliminate multi-line comments in '/* ... */' form, at start of string |
'#^\s*/\*(.+)\*/#Us', |
// eliminate multi-line comments in '/* ... */' form, at end of string |
'#/\*(.+)\*/\s*$#Us' |
), '', $str); |
// eliminate extraneous space |
return trim($str); |
} |
/** |
* decodes a JSON string into appropriate variable |
* |
* @param string $str JSON-formatted string |
* |
* @return mixed number, boolean, string, array, or object |
* corresponding to given JSON input string. |
* See argument 1 to Services_JSON() above for object-output behavior. |
* Note that decode() always returns strings |
* in ASCII or UTF-8 format! |
* @access public |
*/ |
function decode($str) |
{ |
$str = $this->reduce_string($str); |
switch (strtolower($str)) { |
case 'true': |
return true; |
case 'false': |
return false; |
case 'null': |
return null; |
default: |
$m = array(); |
if (is_numeric($str)) { |
// Lookie-loo, it's a number |
// This would work on its own, but I'm trying to be |
// good about returning integers where appropriate: |
// return (float)$str; |
// Return float or int, as appropriate |
return ((float)$str == (integer)$str) |
? (integer)$str |
: (float)$str; |
} elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) { |
// STRINGS RETURNED IN UTF-8 FORMAT |
$delim = substr($str, 0, 1); |
$chrs = substr($str, 1, -1); |
$utf8 = ''; |
$strlen_chrs = strlen($chrs); |
for ($c = 0; $c < $strlen_chrs; ++$c) { |
$substr_chrs_c_2 = substr($chrs, $c, 2); |
$ord_chrs_c = ord($chrs{$c}); |
switch (true) { |
case $substr_chrs_c_2 == '\b': |
$utf8 .= chr(0x08); |
++$c; |
break; |
case $substr_chrs_c_2 == '\t': |
$utf8 .= chr(0x09); |
++$c; |
break; |
case $substr_chrs_c_2 == '\n': |
$utf8 .= chr(0x0A); |
++$c; |
break; |
case $substr_chrs_c_2 == '\f': |
$utf8 .= chr(0x0C); |
++$c; |
break; |
case $substr_chrs_c_2 == '\r': |
$utf8 .= chr(0x0D); |
++$c; |
break; |
case $substr_chrs_c_2 == '\\"': |
case $substr_chrs_c_2 == '\\\'': |
case $substr_chrs_c_2 == '\\\\': |
case $substr_chrs_c_2 == '\\/': |
if (($delim == '"' && $substr_chrs_c_2 != '\\\'') || |
($delim == "'" && $substr_chrs_c_2 != '\\"')) { |
$utf8 .= $chrs{++$c}; |
} |
break; |
case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)): |
// single, escaped unicode character |
$utf16 = chr(hexdec(substr($chrs, ($c + 2), 2))) |
. chr(hexdec(substr($chrs, ($c + 4), 2))); |
$utf8 .= $this->utf162utf8($utf16); |
$c += 5; |
break; |
case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F): |
$utf8 .= $chrs{$c}; |
break; |
case ($ord_chrs_c & 0xE0) == 0xC0: |
// characters U-00000080 - U-000007FF, mask 110XXXXX |
//see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$utf8 .= substr($chrs, $c, 2); |
++$c; |
break; |
case ($ord_chrs_c & 0xF0) == 0xE0: |
// characters U-00000800 - U-0000FFFF, mask 1110XXXX |
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$utf8 .= substr($chrs, $c, 3); |
$c += 2; |
break; |
case ($ord_chrs_c & 0xF8) == 0xF0: |
// characters U-00010000 - U-001FFFFF, mask 11110XXX |
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$utf8 .= substr($chrs, $c, 4); |
$c += 3; |
break; |
case ($ord_chrs_c & 0xFC) == 0xF8: |
// characters U-00200000 - U-03FFFFFF, mask 111110XX |
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$utf8 .= substr($chrs, $c, 5); |
$c += 4; |
break; |
case ($ord_chrs_c & 0xFE) == 0xFC: |
// characters U-04000000 - U-7FFFFFFF, mask 1111110X |
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 |
$utf8 .= substr($chrs, $c, 6); |
$c += 5; |
break; |
} |
} |
return $utf8; |
} elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) { |
// array, or object notation |
if ($str{0} == '[') { |
$stk = array(SERVICES_JSON_IN_ARR); |
$arr = array(); |
} else { |
if ($this->use & SERVICES_JSON_LOOSE_TYPE) { |
$stk = array(SERVICES_JSON_IN_OBJ); |
$obj = array(); |
} else { |
$stk = array(SERVICES_JSON_IN_OBJ); |
$obj = new stdClass(); |
} |
} |
array_push($stk, array('what' => SERVICES_JSON_SLICE, |
'where' => 0, |
'delim' => false)); |
$chrs = substr($str, 1, -1); |
$chrs = $this->reduce_string($chrs); |
if ($chrs == '') { |
if (reset($stk) == SERVICES_JSON_IN_ARR) { |
return $arr; |
} else { |
return $obj; |
} |
} |
//print("\nparsing {$chrs}\n"); |
$strlen_chrs = strlen($chrs); |
for ($c = 0; $c <= $strlen_chrs; ++$c) { |
$top = end($stk); |
$substr_chrs_c_2 = substr($chrs, $c, 2); |
if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) { |
// found a comma that is not inside a string, array, etc., |
// OR we've reached the end of the character list |
$slice = substr($chrs, $top['where'], ($c - $top['where'])); |
array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false)); |
//print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
if (reset($stk) == SERVICES_JSON_IN_ARR) { |
// we are in an array, so just push an element onto the stack |
array_push($arr, $this->decode($slice)); |
} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { |
// we are in an object, so figure |
// out the property name and set an |
// element in an associative array, |
// for now |
$parts = array(); |
if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { |
// "name":value pair |
$key = $this->decode($parts[1]); |
$val = $this->decode($parts[2]); |
if ($this->use & SERVICES_JSON_LOOSE_TYPE) { |
$obj[$key] = $val; |
} else { |
$obj->$key = $val; |
} |
} elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) { |
// name:value pair, where name is unquoted |
$key = $parts[1]; |
$val = $this->decode($parts[2]); |
if ($this->use & SERVICES_JSON_LOOSE_TYPE) { |
$obj[$key] = $val; |
} else { |
$obj->$key = $val; |
} |
} |
} |
} elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) { |
// found a quote, and we are not inside a string |
array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c})); |
//print("Found start of string at {$c}\n"); |
} elseif (($chrs{$c} == $top['delim']) && |
($top['what'] == SERVICES_JSON_IN_STR) && |
((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) { |
// found a quote, we're in a string, and it's not escaped |
// we know that it's not escaped becase there is _not_ an |
// odd number of backslashes at the end of the string so far |
array_pop($stk); |
//print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n"); |
} elseif (($chrs{$c} == '[') && |
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { |
// found a left-bracket, and we are in an array, object, or slice |
array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false)); |
//print("Found start of array at {$c}\n"); |
} elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) { |
// found a right-bracket, and we're in an array |
array_pop($stk); |
//print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
} elseif (($chrs{$c} == '{') && |
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { |
// found a left-brace, and we are in an array, object, or slice |
array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false)); |
//print("Found start of object at {$c}\n"); |
} elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) { |
// found a right-brace, and we're in an object |
array_pop($stk); |
//print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
} elseif (($substr_chrs_c_2 == '/*') && |
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) { |
// found a comment start, and we are in an array, object, or slice |
array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false)); |
$c++; |
//print("Found start of comment at {$c}\n"); |
} elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) { |
// found a comment end, and we're in one now |
array_pop($stk); |
$c++; |
for ($i = $top['where']; $i <= $c; ++$i) |
$chrs = substr_replace($chrs, ' ', $i, 1); |
//print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n"); |
} |
} |
if (reset($stk) == SERVICES_JSON_IN_ARR) { |
return $arr; |
} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) { |
return $obj; |
} |
} |
} |
} |
/** |
* @todo Ultimately, this should just call PEAR::isError() |
*/ |
function isError($data, $code = null) |
{ |
if (class_exists('pear')) { |
return PEAR::isError($data, $code); |
} elseif (is_object($data) && (get_class($data) == 'services_json_error' || |
is_subclass_of($data, 'services_json_error'))) { |
return true; |
} |
return false; |
} |
} |
if (class_exists('PEAR_Error')) { |
class Services_JSON_Error extends PEAR_Error |
{ |
function Services_JSON_Error($message = 'unknown error', $code = null, |
$mode = null, $options = null, $userinfo = null) |
{ |
parent::PEAR_Error($message, $code, $mode, $options, $userinfo); |
} |
} |
} else { |
/** |
* @todo Ultimately, this class shall be descended from PEAR_Error |
*/ |
class Services_JSON_Error |
{ |
function Services_JSON_Error($message = 'unknown error', $code = null, |
$mode = null, $options = null, $userinfo = null) |
{ |
} |
} |
} |
?> |
/trunk/services/bibliotheque/Maillage.php |
---|
New file |
0,0 → 1,151 |
<?php |
class Maillage { |
private $bbox = array(); |
private $zoom = ''; |
private $source = ''; |
private $indexLongitude = array(); |
private $indexLatitude = array(); |
private $mailles = array(); |
private $bdd = null; |
public function __construct($bbox, $zoom, $source) { |
$this->bbox = $this->calculerLimiteBboxGlobale($bbox); |
$this->zoom = $zoom; |
$this->source = $source; |
$this->indexLongitude = array(); |
$this->indexLatitude = array(); |
$this->mailles = array(); |
} |
private function calculerLimiteBboxGlobale($bbox) { |
$bboxGlobale = $bbox[0]; |
for ($index = 1; $index < count($bbox); $index ++) { |
if ($bbox[$index]['ouest'] < $bboxGlobale['ouest']) { |
$bboxGlobale['ouest'] = $bbox[$index]['ouest']; |
} |
if ($bbox[$index]['sud'] < $bboxGlobale['sud']) { |
$bboxGlobale['sud'] = $bbox[$index]['sud']; |
} |
if ($bbox[$index]['est'] > $bboxGlobale['est']) { |
$bboxGlobale['est'] = $bbox[$index]['est']; |
} |
if ($bbox[$index]['nord'] > $bboxGlobale['nord']) { |
$bboxGlobale['nord'] = $bbox[$index]['nord']; |
} |
} |
return $bboxGlobale; |
} |
public function genererMaillesVides() { |
$this->recupererIndexMaillesDansBbox(); |
foreach ($this->indexLatitude as $indexLat => $intervalleLat) { |
$ligne = array(); |
foreach ($this->indexLongitude as $indexLng => $intervalleLng) { |
$ligne[] = new Maille($intervalleLat[0], $intervalleLng[0], $intervalleLat[1], |
$intervalleLng[1], $indexLat, $indexLng); |
} |
$this->mailles[] = $ligne; |
} |
} |
private function recupererIndexMaillesDansBbox() { |
$conditionsLongitude = ""; |
if ($this->bbox['ouest'] > $this->bbox['est']) { |
$conditionsLongitude = "NOT(debut>=".$this->bbox['ouest']." AND fin<=".$this->bbox['est'].")"; |
} else { |
$conditionsLongitude = "fin>=".$this->bbox['ouest']." AND debut <=".$this->bbox['est']; |
} |
$requete = |
"SELECT axe, position, debut, fin FROM mailles_index WHERE zoom=".$this->zoom." ". |
"AND (". |
"(axe='lat' AND fin>=".$this->bbox['sud']." AND debut<=".$this->bbox['nord'].") ". |
"OR (axe='lng' AND {$conditionsLongitude})". |
") ORDER BY axe, position"; |
$indexMailles = $this->getBdd()->recupererTous($requete); |
foreach ($indexMailles as $index) { |
if ($index['axe'] == 'lng') { |
$this->indexLongitude[$index['position']] = array($index['debut'], $index['fin']); |
} else { |
$this->indexLatitude[$index['position']] = array($index['debut'], $index['fin']); |
} |
} |
} |
private function getBdd() { |
if (is_null($this->bdd)) { |
$this->bdd = new Bdd(); |
} |
$nomBdd = Config::get('bdd_nom_eflore'); |
$this->bdd->requeter("USE ".$nomBdd); |
return $this->bdd; |
} |
public function ajouterStations(& $stations) { |
foreach ($stations as $station) { |
$longitude = $station['longitude']; |
$latitude = $station['latitude']; |
list($indexLongitude, $indexLatitude) = $this->rechercherIndexMaille($longitude, $latitude); |
$this->mailles[$indexLatitude][$indexLongitude]->ajouterStation($station, $this->source); |
} |
} |
public function ajouterMailles(& $mailles) { |
foreach ($mailles as $maille) { |
$longitude = ($maille['ouest'] + $maille['est']) / 2; |
$latitude = ($maille['sud'] + $maille['nord']) / 2; |
list($indexLongitude, $indexLatitude) = $this->rechercherIndexMaille($longitude, $latitude); |
$this->mailles[$indexLatitude][$indexLongitude]->combinerMailles($maille, $this->source); |
} |
} |
private function rechercherIndexMaille($longitude, $latitude) { |
$indexLatitude = 0; |
$indexLongitude = 0; |
while ($indexLatitude < count($this->indexLatitude) - 1 |
&& $this->mailles[$indexLatitude][0]->getLatitudeNord() < $latitude) { |
$indexLatitude ++; |
} |
while ($indexLongitude < count($this->indexLongitude) - 1 |
&& $this->mailles[$indexLatitude][$indexLongitude]->getLongitudeEst() < $longitude) { |
$indexLongitude ++; |
} |
return array($indexLongitude, $indexLatitude); |
} |
public function formaterSortie() { |
$mailles_resume = array(); |
foreach ($this->mailles as $ligne) { |
foreach ($ligne as $maille) { |
$nombreStations = $maille->getNombrestations(); |
if ($nombreStations > 0) { |
$mailles_resume[] = array( |
'type_site' => 'MAILLE', |
'sud' => $maille->getLatitudeSud(), |
'ouest' => $maille->getLongitudeOuest(), |
'nord' => $maille->getLatitudeNord(), |
'est' => $maille->getLongitudeEst(), |
'stations' => $maille->getStations(), |
'observations' => $maille->getObservations() |
); |
} |
} |
} |
if (count($mailles_resume) == 0 || count($mailles_resume[0]) == 0) |
return array(); |
return $mailles_resume; |
} |
} |
?> |
/trunk/services/bibliotheque/ReponseHttp.php |
---|
New file |
0,0 → 1,87 |
<?php |
class ReponseHttp { |
private $resultatService = null; |
private $erreurs = array(); |
public function __construct() { |
$this->resultatService = new ResultatService(); |
if (function_exists('json_decode') == false){ |
require_once (dirname(__FILE__).'/JSON.php'); |
function json_decode($content, $assoc = false){ |
if ($assoc) { |
$json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE); |
} else { |
$json = new Services_JSON; |
} |
return $json->decode($content); |
} |
} |
if ( !function_exists('json_encode') ){ |
function json_encode($content){ |
$json = new Services_JSON; |
return $json->encode($content); |
} |
} |
} |
public function setResultatService($resultat) { |
if (!($resultat instanceof ResultatService)) { |
$this->resultatService->corps = $resultat; |
} else { |
$this->resultatService = $resultat; |
} |
} |
public function getCorps() { |
if ($this->etreEnErreur()) { |
$this->resultatService->corps = $this->erreurs[0]['message']; |
} else { |
$this->transformerReponseCorpsSuivantMime(); |
} |
return $this->resultatService->corps; |
} |
public function ajouterErreur(Exception $e) { |
$this->erreurs[] = array('entete' => $e->getCode(), 'message' => $e->getMessage()); |
} |
public function emettreLesEntetes() { |
$enteteHttp = new EnteteHttp(); |
if ($this->etreEnErreur()) { |
$enteteHttp->code = $this->erreurs[0]['entete']; |
$enteteHttp->mime = 'text/html'; |
} else { |
$enteteHttp->encodage = $this->resultatService->encodage; |
$enteteHttp->mime = $this->resultatService->mime; |
} |
header("Content-Type: $enteteHttp->mime; charset=$enteteHttp->encodage"); |
RestServeur::envoyerEnteteStatutHttp($enteteHttp->code); |
} |
private function etreEnErreur() { |
$enErreur = false; |
if (count($this->erreurs) > 0) { |
$enErreur = true; |
} |
return $enErreur; |
} |
private function transformerReponseCorpsSuivantMime() { |
switch ($this->resultatService->mime) { |
case 'application/json' : |
if (isset($_GET['callback'])) { |
$contenu = $_GET['callback'].'('.json_encode($this->resultatService->corps).');'; |
} else { |
$contenu = json_encode($this->resultatService->corps); |
} |
$this->resultatService->corps = $contenu; |
break; |
} |
} |
} |
?> |
/trunk/services/index.php |
---|
New file |
0,0 → 1,43 |
<?php |
// Encodage : UTF-8 |
// Permet d'afficher le temps d'execution du service |
$temps_debut = (isset($_GET['chrono']) && $_GET['chrono'] == 1) ? microtime(true) : ''; |
// +-------------------------------------------------------------------------------------------------------------------+ |
/** |
* Serveur |
* |
* Description : initialise le chargement et l'exécution des services web. |
* |
//Auteur original : |
* @author auteur <aut@tela-botanica.org> |
* @copyright Tela-Botanica 1999-2008 |
* @licence GPL v3 & CeCILL v2 |
* @version $Id$ |
*/ |
// +-------------------------------------------------------------------------------------------------------------------+ |
// Le fichier autoload.inc.php du Framework de Tela Botanica doit être appelée avant tout autre chose dans l'application. |
// Sinon, rien ne sera chargé. |
// Chemin du fichier chargeant le framework requis |
$framework = dirname(__FILE__).DIRECTORY_SEPARATOR.'framework.php'; |
if (!file_exists($framework)) { |
$e = "Veuillez paramétrer l'emplacement et la version du Framework dans le fichier $framework"; |
trigger_error($e, E_USER_ERROR); |
} else { |
// Inclusion du Framework |
require_once $framework; |
// Ajout d'information concernant cette application |
Framework::setCheminAppli(__FILE__);// Obligatoire |
Framework::setInfoAppli(Config::get('info')); |
// Initialisation et lancement du serveur |
$Serveur = new RestServeur(); |
$Serveur->executer(); |
// Affiche le temps d'execution du service |
if (isset($_GET['chrono']) && $_GET['chrono'] == 1) { |
$temps_fin = microtime(true); |
echo 'Temps d\'execution : '.round($temps_fin - $temps_debut, 4); |
} |
} |
?> |
/trunk/services/framework.php |
---|
New file |
0,0 → 1,6 |
<?php |
// Inclusion du Framework |
// Renomer ce fichier en "framework.php" |
// Indiquer ci-dessous le chemin absolu vers le fichier autoload.inc.php de la bonne version du Framework |
require_once '/home/alex/web/framework-0.3/framework/Framework.php'; |
?> |
/trunk/services/modules/0.1/Projets.php |
---|
New file |
0,0 → 1,175 |
<?php |
class Projets extends RestService { |
private $parametres = array(); |
private $ressources = array(); |
private $squeletteDossier = ''; |
private $cache; |
public function __construct() { |
$this->squeletteDossier = dirname(__FILE__).DIRECTORY_SEPARATOR; |
} |
public function consulter($ressources, $parametres) { |
$resultat = ''; |
$reponseHttp = new ReponseHttp(); |
try { |
$this->initialiserRessourcesEtParametres($ressources, $parametres); |
$resultat = $this->traiterRessources(); |
$reponseHttp->setResultatService($resultat); |
} catch (Exception $e) { |
$reponseHttp->ajouterErreur($e); |
} |
$reponseHttp->emettreLesEntetes(); |
$corps = $reponseHttp->getCorps(); |
return $corps; |
} |
private function initialiserRessourcesEtParametres($ressources, $parametres) { |
$this->ressources = $ressources; |
$this->parametres = $parametres; |
} |
private function traiterRessources() { |
$retour = ''; |
if ($this->avoirRessources()) { |
if ($this->avoirRessourceService()) { |
$retour = $this->initialiserService(); |
} |
} |
return $retour; |
} |
private function avoirRessources() { |
$presenceDeRessources = false; |
if (isset($this->ressources) && count($this->ressources) > 0) { |
$presenceDeRessources = true; |
} else { |
$message = "Accès au service refusé : aucune ressource indiquée.\n" |
. "Veuillez indiquer au moins une source de données à interroger" |
. " et le type d'informations a renvoyer."; |
$code = RestServeur::HTTP_CODE_MAUVAISE_REQUETE; |
throw new Exception($message, $code); |
} |
return $presenceDeRessources; |
} |
private function chargerConfiguration($nomParametre) { |
$tableau = array(); |
$tableauPartiel = explode(',', Config::get($nomParametre)); |
$tableauPartiel = array_map('trim', $tableauPartiel); |
foreach ($tableauPartiel as $champ) { |
if (strpos($champ, '=') === false) { |
$tableau[] = $champ; |
} else { |
list($cle, $val) = explode('=', $champ); |
$clePropre = trim($cle); |
$valeurPropre = trim($val); |
$tableau[$clePropre] = $valeurPropre; |
} |
} |
return $tableau; |
} |
public static function chargerConfigurationSource($nomSource) { |
$chemin = Config::get('chemin_configurations')."config_$nomSource.ini"; |
Config::charger($chemin); |
} |
private function chargerClasse($classe) { |
if (class_exists($classe)) { |
return null; |
} |
$cheminBiblio = Config::get('chemin_bibliotheque'); |
$chemins = array(); |
$chemins[] = $this->squeletteDossier; |
$chemins[] = $this->squeletteDossier.'commun' .DIRECTORY_SEPARATOR; |
$chemins[] = $this->squeletteDossier.'sources'.DIRECTORY_SEPARATOR; |
$chemins[] = $cheminBiblio; |
$chemins[] = $cheminBiblio.'robots'.DIRECTORY_SEPARATOR; |
foreach ($chemins as $chemin) { |
$chemin = $chemin.$classe.'.php'; |
if (file_exists($chemin)) { |
require_once $chemin; |
break; |
} |
} |
} |
private function avoirRessourceService() { |
$presenceRessourceService = false; |
$servicesDispo = $this->chargerConfiguration('services_dispo'); |
if (isset($this->ressources[0])) { |
$service = $this->ressources[0]; |
if (in_array($service, $servicesDispo)) { |
$presenceRessourceService = true; |
} else { |
$message = "La service demandé '$service' n'est pas disponible !\n" |
. "Les services disponibles sont : ".implode(', ', $servicesDispo); |
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE; |
throw new Exception($message, $code); |
} |
} else { |
$message = "Vous n'avez pas indiqué de service !\n" |
. "Les services disponibles sont : ".implode(', ', $servicesDispo); |
$code = RestServeur::HTTP_CODE_MAUVAISE_REQUETE; |
throw new Exception($message, $code); |
} |
return $presenceRessourceService; |
} |
private function initialiserService() { |
$nomService = 'commun'; |
$classe = $this->obtenirNomClasseService($nomService); |
$chemins = array(); |
$chemins[] = $this->squeletteDossier.'commun'.DIRECTORY_SEPARATOR.'Commun.php'; |
// php5.3 : Enregistrement en première position des autoload de la méthode gérant les classes des services |
if (phpversion() < 5.3) { |
spl_autoload_register(array($this, 'chargerClasse')); |
} else { |
spl_autoload_register(array($this, 'chargerClasse'), true , true); |
} |
$retour = ''; |
$service = null; |
foreach ($chemins as $chemin) { |
if (file_exists($chemin)) { |
$service = new $classe($this->getBdd()); |
$ressourcesPourService = $this->filtrerRessourcesPourService(); |
$this->cache = new CacheMoissonnage($service, $nomService, |
Config::get('cache')); |
$retour = $this->cache->consulter($ressourcesPourService, $this->parametres); |
if (get_class($retour) == 'Exception') { |
throw new Exception($retour->getMessage(), RestServeur::HTTP_CODE_MAUVAISE_REQUETE); |
} |
} |
} |
if (is_null($service)) { |
$message = "Le service demandé '{$nomService}' n'existe pas !"; |
$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 filtrerRessourcesPourService() { |
return $this->ressources; |
} |
} |
?> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/trunk/services/modules/0.1/commun/Commun.php |
---|
New file |
0,0 → 1,404 |
<?php |
/** |
* |
* Classe principale du web service qui peut traiter des requetes provenant d'un navigateur web |
* (stations dans bbox ou observations sur un point), ou d'un client SIG via appel au protocole/service WFS |
* (demande d'observations par stations selon des filtres optionnels). Le web service analyse et verifie |
* les parametres de l'URL de la requete qu'il recoit. S'ils sont tous valides, il va appeler une autre classe |
* pour recuperer les informations demandees dans les differentes sources de donnees. |
* Les donnees recuperees sont ensuite combinees si plusieurs sources sont demandees et mises en forme |
* au format de sortie. Les formats de sortie utilises sont le GeoJSON (extension de JSON pour les donnees |
* geographiques) en destination des navigateurs web et le GML adapte au service WFS pour les clients SIG. |
* Dans le cas ou des erreurs sont levees, le web service renvoie un message d'erreur expliquant le probleme |
* recnontre dans son fonctionnement. |
* |
* |
* @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) |
* |
*/ |
class Commun { |
private $parametres = array(); |
private $ressources = array(); |
private $nomSource = ''; |
private $nomService = ''; |
private $verificateur = null; |
private $parametresRecherche = null; |
private $retour = array(); |
const MIME_WFS = 'text/xml'; |
public function consulter($ressources, $parametres) { |
$this->recupererRessourcesEtParametres($ressources, $parametres); |
$retour = null; |
if (in_array("wfs", $ressources)) { |
$retour = $this->traiterRequeteWfs(); |
} else { |
$retour = $this->traiterRequeteNavigateur(); |
} |
return $retour; |
} |
/*********************************************/ |
// Verification parametres URL non-WFS |
private function traiterRequeteWfs() { |
$retour = null; |
try { |
$this->parametresRecherche = new StdClass(); |
$this->traiterParametreOperation(); |
if ($this->parametresRecherche->operation != 'GetCapabilities') { |
$this->traiterParametreSource(); |
} |
if ($this->parametresRecherche->operation == 'GetFeature') { |
$retour = $this->getFeature(); |
} else { |
$formateurWfs = new FormateurWfs(); |
$nomMethode = 'formater'.$this->parametresRecherche->operation; |
$parametre = isset($this->parametresRecherche->sources) |
? $this->parametresRecherche->sources : null; |
$retour = new ResultatService(); |
$retour->mime = self::MIME_WFS; |
$retour->corps = $formateurWfs->$nomMethode($parametre); |
} |
} catch (Exception $erreur) { |
$formateurWfs = new FormateurWfs(); |
$retour = new ResultatService(); |
$retour->mime = self::MIME_WFS; |
$retour->corps = $formateurWfs->formaterException($erreur); |
} |
return $retour; |
} |
private function getFeature() { |
if (array_key_exists('bbox', $this->parametres)) { |
$this->traiterParametreBbox(); |
} elseif (array_key_exists('filter', $this->parametres)) { |
$this->traiterParametreFilter(); |
} |
$this->recupererStationsWfs(); |
$formateurWfs = new FormateurWfs(); |
$retour = new ResultatService(); |
$retour->mime = self::MIME_WFS; |
$retour->corps = $formateurWfs->formaterGetFeature($this->retour, $this->parametresRecherche->sources); |
return $retour; |
} |
private function traiterParametreOperation() { |
if ($this->verifierExistenceParametre('request')) { |
if (!$this->estOperationWfsAutorisee()) { |
$message = "L'opération '".$this->parametres['request']."' n'est pas autorisée.\n". |
"Les opérations suivantes sont permises par le service : ".Config::get('operations_wfs'); |
throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE); |
} else { |
$this->parametresRecherche->operation = $this->parametres['request']; |
} |
} |
} |
private function verifierExistenceParametre($nomParametre) { |
$estParametreExistant = false; |
if (!array_key_exists($nomParametre, $this->parametres)) { |
$message = "Le paramètre nom de l'opération '{$nomParametre}' ". |
"n'a pas été trouvé dans la liste des paramètres."; |
throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE); |
} else { |
$estParametreExistant = true; |
} |
return $estParametreExistant; |
} |
private function estOperationWfsAutorisee() { |
$operationsWfsService = explode(',' , Config::get('operations_wfs')); |
return (in_array($this->parametres['request'], $operationsWfsService)); |
} |
private function traiterParametreSource() { |
// le parametre source (typename) est optionnel par defaut |
if (array_key_exists('typename', $this->parametres)) { |
$sources = explode(',', $this->parametres['typename']); |
$estSourceValide = true; |
foreach ($sources as $source) { |
if (!$this->verifierExistenceSourcesDonnees($source)) { |
$message = "Source de donnees '{$source}' indisponible. Les sources disponibles sont : ". |
Config::get('sources_dispo'); |
$estSourceValide = false; |
throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE); |
} |
} |
if ($estSourceValide) { |
$this->parametresRecherche->sources = $sources; |
} |
} |
} |
private function traiterParametreBbox() { |
$bboxVerifiee = $this->verifierCoordonneesBbox($this->parametres['bbox']); |
if (is_array($bboxVerifiee) && count($bboxVerifiee) == 4) { |
$this->parametresRecherche->bbox = array($bboxVerifiee); |
} |
} |
private function verifierCoordonneesBbox($bbox) { |
$bboxVerifiee = null; |
// verifier que la chaine de caracteres $bbox est une serie de chaque nombre decimaux |
// separes entre eux par une virgule |
if (preg_match('/^(-?\d{1,3}(.\d+)?,){3}(-?\d{1,3}(.\d+)?)$/', $bbox) == 0) { |
$message = "Format de saisie des coordonnees de la bounding box non valide. Le service ". |
"n'accepte seulement qu'une serie de 4 nombre décimaux séparés par des virgules."; |
throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE); |
} else { |
$coordonnees = explode(',', $bbox); |
$nomsIndexBbox = array("ouest", "sud", "est", "nord"); |
$bbox = array(); |
for ($i = 0; $i < count($coordonnees); $i ++) { |
$bbox[$nomsIndexBbox[$i]] = $coordonnees[$i]; |
} |
// verifier que les coordonnees de chaque bord de la bbox sont valides |
if ($this->estUneBboxValide($bbox)) { |
$bboxVerifiee = $bbox; |
} else { |
$message = "Certaines coordonnées de la bounding box sont situés en dehors des limites ". |
"de notre monde"; |
throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE); |
} |
} |
return $bboxVerifiee; |
} |
private function estUneBboxValide($bbox) { |
$monde = array( |
'ouest' => floatval(Config::get('carte.limite_ouest')), |
'est' => floatval(Config::get('carte.limite_est')), |
'sud' => floatval(Config::get('carte.limite_sud')), |
'nord' => floatval(Config::get('carte.limite_nord')) |
); |
return (floatval($bbox['ouest']) >= $monde['ouest'] && floatval($bbox['ouest']) <= $monde['est'] |
&& floatval($bbox['est']) >= $monde['ouest'] && floatval($bbox['est']) <= $monde['est'] |
&& floatval($bbox['nord']) >= $monde['sud'] && floatval($bbox['nord']) <= $monde['nord'] |
&& floatval($bbox['sud']) >= $monde['sud'] && floatval($bbox['sud']) <= $monde['nord']); |
} |
private function traiterParametreFilter() { |
// la valeur du parametre filter est une chaine de texte qui compose en realite un document XML |
// plus d'infos a l'URL suivante : http://mapserver.org/fr/ogc/filter_encoding.html |
$filtreTexte = $this->recupererTexteParametreFilter(); |
$documentXML = new DomDocument(); |
$documentXML->loadXML($filtreTexte); |
$filtres = $documentXML->documentElement->childNodes; |
for ($index = 0; $index < $filtres->length; $index ++) { |
$this->verifierFiltre($filtres->item($index)); |
} |
} |
private function recupererTexteParametreFilter() { |
$parametresUrl = explode("&", $_SERVER['QUERY_STRING']); |
$filtreTexte = ''; |
foreach ($parametresUrl as $parametre) { |
list($cle, $valeur) = explode("=", $parametre); |
if ($cle == 'filter') { |
$filtreTexte = rawurldecode($valeur); |
} |
} |
return $filtreTexte; |
} |
private function verifierFiltre($filtre) { |
$operateursAcceptes = explode(',', Config::get('operateurs_wfs')); |
$nomOperateur = $filtre->tagName; |
if (!in_array($nomOperateur, $operateursAcceptes)) { |
$message = "Le filtre '$nomOperateur' n'est pas pris en compte par le serrvice. ". |
"Les opérateurs acceptés sont :".implode(', ', $operateursAcceptes); |
throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE); |
} else { |
if ($nomOperateur == 'BBOX') { |
$bboxUrl = $filtre->lastChild->nodeValue; |
$bboxVerifiee = $this->verifierCoordonneesBbox($bboxUrl); |
$this->parametresRecherche->bbox = array($bboxVerifiee); |
} else { |
$this->traiterOperateurScalaire($filtre); |
} |
} |
} |
private function traiterOperateurScalaire($filtre) { |
$nomOperateur = $filtre->tagName; |
$champ = $filtre->childNodes->item(0)->nodeValue; |
if ($champ != Config::get('champ_filtrage_wfs')) { |
$message = "Le filtre ne peut pas être appliqué sur le champ '$champ'. ". |
"Il est seulement accepté sur le champ '".Config::get('champ_filtrage_wfs')."'"; |
throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE); |
} else { |
$valeur = $filtre->childNodes->item(1)->nodeValue; |
$operateur = $nomOperateur == 'PropertyIsEqualTo' ? "=" : "LIKE"; |
$this->parametresRecherche->filtre = array("champ" => $champ, "operateur" => $operateur, |
"valeur" => $valeur); |
} |
} |
private function recupererStationsWfs() { |
$this->nomMethode = $this->ressources[0]; |
foreach ($this->parametresRecherche->sources as $source) { |
$source = trim($source); |
$resultat = $this->traiterSource($source); |
$this->ajouterResultat($resultat, $source); |
} |
} |
/*********************************************/ |
// Verification parametres URL non-WFS |
private function traiterRequeteNavigateur() { |
$retour = null; |
try { |
if (!$this->estParametreSourceExistant()) { |
$message = "Le paramètre source de données n'a pas été indiqué."; |
throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE); |
} else { |
$this->verifierParametres(); |
$listeSources = explode(',', $this->parametres['source']); |
foreach ($listeSources as $source) { |
$source = trim($source); |
$resultat = $this->traiterSource($source); |
$this->ajouterResultat($resultat, $source); |
} |
} |
$formateur = new FormateurJson(); |
$nomMethode = 'formater'.ucfirst($this->ressources[0]); |
$retour = new ResultatService(); |
$retour->corps = $formateur->$nomMethode($this->retour); |
} catch (Exception $erreur) { |
$retour = $erreur; |
} |
return $retour; |
} |
private function recupererRessourcesEtParametres($ressources, $parametres) { |
$this->ressources = $ressources; |
$this->parametres = array(); |
foreach ($parametres as $nomParametre => $valeur) { |
$this->parametres[strtolower($nomParametre)] = $valeur; |
} |
} |
private function estParametreSourceExistant() { |
$parametreExiste = false; |
if (isset($this->parametres['source'])) { |
$parametreExiste = true; |
} |
return $parametreExiste; |
} |
private function verifierExistenceSourcesDonnees($source) { |
$sourcesDisponibles = explode(',', Config::get('sources_dispo')); |
$estDisponible = false; |
if (in_array($source, $sourcesDisponibles)) { |
$estDisponible = true; |
} |
return $estDisponible; |
} |
private function verifierParametres() { |
$this->verificateur = new VerificateurParametres($this->parametres); |
$this->verificateur->verifierParametres(); |
if ($this->verificateur->contientErreurs()) { |
$this->verificateur->leverException(); |
} else { |
$this->recupererParametresRecherche(); |
} |
} |
private function traiterSource($source) { |
$retour = array(); |
if (!$this->verifierExistenceSourcesDonnees($source)) { |
$message = "Source de donnees indisponible"; |
throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE); |
} else { |
$this->chargerNomService($source); |
$retour = $this->executerServicePourSource($source); |
} |
return $retour; |
} |
private function recupererParametresRecherche() { |
$this->parametresRecherche = $this->verificateur->renvoyerResultatVerification(); |
} |
private function chargerNomSource($source) { |
if (isset($this->parametres['source'])) { |
$this->nomSource = $this->parametres['source']; |
} else { |
$this->nomSource = Config::get('source_defaut'); |
} |
} |
private function chargerNomService($source) { |
$this->nomService = ($source == 'floradata' ? 'Floradata' : 'Moissonnage').'Formateur'; |
Projets::chargerConfigurationSource($source); |
} |
private function executerServicePourSource($source) { |
$objetTraitement = new $this->nomService($this->parametresRecherche, $source); |
$methode = $this->genererNomMethodeAExecuter(); |
return $objetTraitement->$methode(); |
} |
private function genererNomMethodeAExecuter() { |
return 'recuperer' . ucfirst($this->ressources[0]); |
} |
private function ajouterResultat(& $resultat, $source) { |
if (count($this->retour) > 0) { |
if ($this->ressources[0] == 'stations' && count($resultat) > 0 |
&& $this->doitTransformerTypeDonnees($resultat)) { |
$this->combinerResultats($resultat, $source); |
} else { |
$this->retour = array_merge($this->retour, $resultat); |
} |
} else { |
$this->retour = array_merge($this->retour, $resultat); |
} |
} |
private function doitTransformerTypeDonnees(& $resultat) { |
return ($this->parametresRecherche->zoom <= Config::get('zoom_maximal_maillage') && |
(($resultat[0]['type_site'] == 'MAILLE' || $this->retour[0]['type_site'] == 'MAILLE') |
|| ($resultat[0]['type_site'] != 'MAILLE' && $this->retour[0]['type_site'] != 'MAILLE' |
&& count($resultat) + count($this->retour) > Config::get('seuil_maillage'))) |
); |
} |
private function combinerResultats(& $resultat, $source) { |
$maillage = new Maillage($this->parametresRecherche->bbox, $this->parametresRecherche->zoom, $source); |
$maillage->genererMaillesVides(); |
if ($resultat[0]['type_site'] == 'MAILLE') { |
$maillage->ajouterMailles($resultat); |
} else { |
$maillage->ajouterStations($resultat); |
} |
if ($this->retour[0]['type_site'] == 'MAILLE') { |
$maillage->ajouterMailles($this->retour); |
} else { |
$maillage->ajouterStations($this->retour); |
} |
$this->retour = $maillage->formaterSortie(); |
} |
} |
?> |
/trunk/services/modules/0.1/sources/FloradataFormateur.php |
---|
New file |
0,0 → 1,289 |
<?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; |
} |
} |
?> |
/trunk/services/modules/0.1/sources/Formateur.php |
---|
New file |
0,0 → 1,131 |
<?php |
abstract class Formateur { |
protected $criteresRecherche; |
protected $bdd = null; |
protected $nomSource = ''; |
public function __construct($criteresRecherche, $source) { |
$this->criteresRecherche = $criteresRecherche; |
$this->nomSource = $source; |
} |
protected function getBdd() { |
if (is_null($this->bdd)) { |
$this->bdd = new Bdd(); |
$nomBdd = $this->nomSource == 'floradata' ? Config::get('bdd_nom_floradata') : Config::get('bdd_nom_eflore'); |
$this->bdd->requeter("USE {$nomBdd}"); |
} |
return $this->bdd; |
} |
public function recupererStations() { |
$stations = array(); |
if ($this->nomSource == 'floradata' || $this->calculerNombreCriteresNonSpatiaux() > 0) { |
$requeteSql = $this->construireRequeteStations(); |
$stations = $this->getBdd()->recupererTous($requeteSql); |
if ($this->determinerFormatRetour(count($stations)) == 'maille') { |
$maillage = new Maillage($this->criteresRecherche->bbox, |
$this->criteresRecherche->zoom, $this->nomSource); |
$maillage->genererMaillesVides(); |
$maillage->ajouterStations($stations); |
$stations = $maillage->formaterSortie(); |
} |
} else { |
$nombreStations = $this->obtenirNombreStationsDansBbox(); |
if ($this->determinerFormatRetour($nombreStations) == 'maille') { |
$stations = $this->recupererMaillesDansBbox(); |
} else { |
$requeteSql = $this->construireRequeteStations(); |
$stations = $this->getBdd()->recupererTous($requeteSql); |
} |
} |
return $stations; |
} |
public function recupererWfs() { |
$requeteSql = $this->construireRequeteWfs(); |
return $this->getBdd()->recupererTous($requeteSql); |
} |
protected function determinerFormatRetour($nombreStations) { |
$formatRetour = 'point'; |
$zoomMaxMaillage = Config::get('zoom_maximal_maillage'); |
if (isset($this->criteresRecherche->format) && $this->criteresRecherche->format == 'maille' |
&& $this->criteresRecherche->zoom <= $zoomMaxMaillage) { |
$formatRetour = 'maille'; |
} else { |
$seuilMaillage = Config::get('seuil_maillage'); |
if ($this->criteresRecherche->zoom <= $zoomMaxMaillage && $nombreStations > $seuilMaillage) { |
$formatRetour = 'maille'; |
} |
} |
return $formatRetour; |
} |
protected function calculerNombreCriteresNonSpatiaux() { |
$nombreParametresNonSpatiaux = 0; |
$criteresAIgnorer = array('zoom', 'bbox', 'stations', 'referentiel', 'format'); |
foreach ($this->criteresRecherche as $nomCritere => $valeur) { |
if (!in_array($nomCritere, $criteresAIgnorer)) { |
$nombreParametresNonSpatiaux ++; |
} |
} |
return $nombreParametresNonSpatiaux; |
} |
abstract protected function construireRequeteStations(); |
protected function obtenirNombreStationsDansBbox() {} |
protected function recupererMaillesDansBbox() {} |
public function recupererObservations() { |
$requeteSql = $this->construireRequeteObservations(); |
$observations = $this->getBdd()->recupererTous($requeteSql); |
if ($this->nomSource != 'floradata') { |
$this->recupererNumeroNomenclaturauxTaxons($observations); |
} |
$nomStation = $this->obtenirNomsStationsSurPoint(); |
if (strlen($nomStation) == 0) { |
$nomStation = 'station sans nom'; |
} |
for ($index = 0; $index < count($observations); $index ++) { |
$observations[$index]['nom_station'] = $nomStation; |
} |
return $observations; |
} |
abstract protected function construireRequeteObservations(); |
protected function recupererNumeroNomenclaturauxTaxons(& $observations) { |
for ($index = 0; $index < count($observations); $index ++) { |
if (strlen (trim($observations[$index]['nomSci'])) == 0) { |
continue; |
} |
$numeroNomenclatural = isset($observations[$index]['nn']) ? $observations[$index]['nn'] : null; |
$referentiels = Referentiel::recupererListeReferentielsDisponibles(); |
$taxon = null; |
$indexRef = 0; |
while ($indexRef < count($referentiels) && is_null($taxon)) { |
$referentiel = new Referentiel($referentiels[$indexRef]); |
$taxon = $referentiel->obtenirNumeroNomenclatural($observations[$index]['nomSci'], |
$numeroNomenclatural); |
$indexRef ++; |
} |
if (!is_null($taxon)) { |
$observations[$index]['nn'] = $taxon['nn']; |
$observations[$index]['nom_referentiel'] = $taxon['referentiel']; |
} else { |
$observations[$index]['nn'] = ''; |
} |
} |
} |
abstract protected function obtenirNomsStationsSurPoint(); |
} |
?> |
/trunk/services/modules/0.1/sources/MoissonnageFormateur.php |
---|
New file |
0,0 → 1,266 |
<?php |
/** |
* |
* Classe en charge de recuperer les donnees d'observation ou liees a leur localisation |
* Le jeu de donnees a interroger est partage en commun avec l'application EFlore |
* |
* 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) |
* |
*/ |
class MoissonnageFormateur extends Formateur { |
final protected function construireRequeteStations() { |
$requete = |
"SELECT COUNT(guid) AS observations, lieu_station_nom AS nom, lieu_station_latitude AS latitude, ". |
"lieu_station_longitude AS longitude, 'STATION' AS type_site, lieu_commune_code_insee AS code_insee, ". |
"'{$this->nomSource}' AS source FROM {$this->nomSource}_tapir WHERE 1 ". |
$this->construireWhereDepartement().' '. |
$this->construireWhereAuteur().' '. |
$this->construireWhereDate().' '. |
$this->construireWhereReferentiel().' '. |
$this->construireWhereTaxon().' '. |
$this->construireWhereCoordonneesBbox().' '. |
"GROUP BY lieu_station_longitude, lieu_station_latitude"; |
return $requete; |
} |
final protected function construireRequeteObservations() { |
$requete = |
"SELECT observation_id AS id_obs, nom_scientifique_complet AS nomSci, ". |
"observation_date AS date, lieu_station_nom AS lieu, observateur_nom_complet AS observateur, ". |
"'{$this->nomSource}' AS projet FROM {$this->nomSource}_tapir WHERE 1 ". |
$this->construireWhereAuteur().' '. |
$this->construireWhereReferentiel().' '. |
$this->construireWhereDate().' '. |
$this->construireWhereTaxon().' '. |
$this->construireWhereCoordonneesPoint().' '. |
"ORDER BY nom_scientifique_complet, date, observateur"; |
return $requete; |
} |
final protected function construireRequeteWfs() { |
$requete = |
"SELECT nom_scientifique_complet AS taxon, lieu_station_nom AS nom, lieu_station_latitude AS latitude, ". |
"lieu_station_longitude AS longitude, 'station' AS type_site, lieu_commune_code_insee AS code_insee, ". |
"'{$this->nomSource}' AS source, observateur_nom_complet AS auteur ". |
"FROM {$this->nomSource}_tapir WHERE 1 ". |
$this->construireWhereCoordonneesBbox().' '. |
$this->construireWhereNomScientifique().' '. |
"ORDER BY lieu_station_longitude, lieu_station_latitude"; |
return $requete; |
} |
private function construireWhereTaxon() { |
$sql = ''; |
if (isset($this->criteresRecherche->taxon)) { |
$taxons = $this->criteresRecherche->taxon; |
$criteres = array(); |
foreach ($taxons as $taxon) { |
$criteres[] = "nom_scientifique_complet LIKE ".$this->getBdd()->proteger($taxon['nom']."%"); |
if ($taxon['rang'] >= Config::get('rang.espece')) { |
$criteres = array_merge($criteres, $this->concatenerSynonymesEtSousEspeces($taxon)); |
} elseif ($taxon['rang'] == Config::get('rang.famille')) { |
$criteres = array_merge($criteres, $this->concatenerTaxonsGenres($taxon)); |
} |
} |
$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[] = "nom_scientifique_complet LIKE ".$this->getBdd()->proteger($sousTaxon['nom']."%"); |
} |
return $criteres; |
} |
private function concatenerTaxonsGenres($taxon) { |
$referentiel = new Referentiel($this->criteresRecherche->referentiel, $taxon); |
$sousTaxons = $referentiel->recupererGenres(); |
$criteres = array(); |
foreach ($sousTaxons as $sousTaxon) { |
$criteres[] = "nom_scientifique_complet LIKE ".$this->getBdd()->proteger($sousTaxon['nom']."%"); |
} |
return $criteres; |
} |
private function construireWhereReferentiel() { |
$sql = ''; |
if (isset($this->criteresRecherche->referentiel)) { |
$referentielSource = Config::get('referentiel_source'); |
if (strstr($this->criteresRecherche->referentiel, $referentielSource) === false) { |
$sql = "AND 0"; |
} |
} |
return $sql; |
} |
private function construireWhereDepartement() { |
$sql = ''; |
if (isset($this->criteresRecherche->departement)) { |
$valeurs_a_proteger = $this->criteresRecherche->departement; |
foreach ($valeurs_a_proteger as $valeur) { |
$aProteger = $this->getBdd()->proteger($valeur . '%'); |
$valeurs_protegees[] = "lieu_commune_code_insee LIKE {$aProteger}"; |
} |
$valeurs = implode(' OR ', $valeurs_protegees); |
$sql = "AND ($valeurs)"; |
} |
return $sql; |
} |
private function construireWhereAuteur() { |
$sql = ''; |
if (isset($this->criteresRecherche->auteur)) { |
$auteur = $this->getBdd()->proteger($this->criteresRecherche->auteur); |
$sql = "AND observateur_nom_complet = $auteur"; |
} |
return $sql; |
} |
private function construireWhereDate() { |
$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)) { |
$dateDebut = !is_null($dateDebut) ? substr($dateDebut, 0, 4) : null; |
$dateFin = !is_null($dateFin) ? substr($dateFin, 0, 4) : date('Y'); |
$condition = ''; |
if ($dateDebut == $dateFin) { |
$condition = "observation_date=".$dateDebut; |
} elseif (is_null($dateFin)) { |
$condition = "observation_date>=".$dateDebut; |
} elseif (is_null($dateDebut)) { |
$condition = "observation_date<=".$dateFin; |
} else { |
$condition = "observation_date BETWEEN ".$dateDebut." AND ".$dateFin; |
} |
$sql = "AND ($condition)"; |
} |
return $sql; |
} |
private function construireWhereCoordonneesBbox() { |
$sql = ''; |
if (isset($this->criteresRecherche->bbox)) { |
$bboxRecherche = $this->criteresRecherche->bbox; |
$conditions = array(); |
foreach ($bboxRecherche as $bbox) { |
$conditions[] = "(lieu_station_longitude BETWEEN ".$bbox['ouest']." AND ".$bbox['est']." ". |
"AND lieu_station_latitude BETWEEN ".$bbox['sud']." AND ".$bbox['nord'].")"; |
} |
$sql = 'AND ('.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_scientifique_complet {$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[2])); |
$latitude = str_replace(",", ".", strval($station[3])); |
$conditions[] = "(lieu_station_latitude={$longitude} AND lieu_station_longitude={$latitude})"; |
} |
} |
if (count($conditions) > 0) { |
$sql = "AND (".implode(" OR ", $conditions).")"; |
} |
return $sql; |
} |
final protected function obtenirNomsStationsSurPoint() { |
$requete = "SELECT DISTINCTROW lieu_station_nom FROM {$this->nomSource}_tapir WHERE 1 ". |
$this->construireWhereTaxon().' '. |
$this->construireWhereCoordonneesPoint(); |
$stations = $this->getBdd()->recupererTous($requete); |
$nomsStations = array(); |
foreach ($stations as $station) { |
$nomsStations[] = $station['lieu_station_nom']; |
} |
return implode(', ', $nomsStations); |
} |
final protected function obtenirNombreStationsDansBbox() { |
$bbox = $this->criteresRecherche->bbox; |
$zoom = $this->criteresRecherche->zoom; |
$requete = |
"SELECT zoom, Sum(nombre_sites) AS total_points FROM mailles_{$this->nomSource} ". |
"WHERE zoom=".$zoom." ".$this->construireWhereMaillesBbox()." GROUP BY zoom"; |
$resultat = $this->getBdd()->recuperer($requete); |
return $resultat['total_points']; |
} |
final protected function recupererMaillesDansBbox() { |
$bbox = $this->criteresRecherche->bbox; |
$zoom = $this->criteresRecherche->zoom; |
$requete = |
"SELECT limite_sud AS sud, limite_ouest AS ouest, limite_est AS est, limite_nord AS nord, ". |
"nombre_sites AS stations, nombre_observations AS observations FROM mailles_{$this->nomSource} ". |
"WHERE zoom=".$zoom." ".$this->construireWhereMaillesBbox(); |
$mailles = $this->getBdd()->recupererTous($requete); |
// placer les totaux des nombres de stations dans des mailles vides |
$maillage = new Maillage($this->criteresRecherche->bbox, $zoom, $this->nomSource); |
$maillage->genererMaillesVides(); |
$maillage->ajouterMailles($mailles); |
return $maillage->formaterSortie(); |
} |
private function construireWhereMaillesBbox() { |
$bboxRecherche = $this->criteresRecherche->bbox; |
$conditions = array(); |
$sql = ''; |
foreach ($bboxRecherche as $bbox) { |
$conditions[] = "(limite_sud<=".$bbox['nord']." AND limite_nord>=".$bbox['sud']." ". |
"AND limite_ouest<=". $bbox['est']." AND limite_est>=".$bbox['ouest'].")"; |
} |
if (count($conditions) > 0) { |
$sql = 'AND ('.implode(' OR ', $conditions).')'; |
} |
return $sql; |
} |
} |
?> |
/trunk/services/configurations/config.defaut.ini |
---|
New file |
0,0 → 1,97 |
; Encodage : UTF-8 |
; +------------------------------------------------------------------------------------------------------+ |
; URLs |
; Le séparateur utilisé par le framework lorsqu'il génère des URL pour séparer les arguments. |
; Pour remettre les valeurs par défaut, utitliser : "php:ini_get('arg_separator.output')" |
url_arg_separateur_sortie = "&" |
; +------------------------------------------------------------------------------------------------------+ |
; Info sur l'application |
info.nom = Services d'eFlore |
; Abréviation de l'application |
info.abr = carto-services |
; Version du Framework nécessaire au fonctionnement de cette application |
info.framework.version = 0.3 |
;Encodage de l'application |
encodage_appli = "UTF-8" |
; +------------------------------------------------------------------------------------------------------+ |
; Débogage |
; Indique si oui ou non on veut afficher le débogage. |
debogage = true |
; Indique sous quelle forme les méssages de débogage doivent s'afficher : |
; - "php:Debug::MODE_ECHO" : le message est affiché en utilisant echo |
; - "php:Debug::MODE_NOTICE" : le message est affiché en utilisant une erreur de type notice |
; - "php:Debug::MODE_ENTETE_HTTP" : les messages sont envoyés dans un entête HTTP "X_REST_DEBOGAGE". |
; - "Autre valeur" : les messages sont formatés puis retournés par la méthode de débogage utilisée. |
debogage_mode = "php:Debug::MODE_ECHO" |
; Indique si oui ou non on veut lancer le chronométrage |
chronometrage = false |
; +------------------------------------------------------------------------------------------------------+ |
; Paramètrage de la base de données. |
; Abstraction de la base de données. |
bdd_abstraction = pdo |
; Protocole de la base de données. |
bdd_protocole = mysql |
; Nom du serveur de bases de données. |
bdd_serveur = localhost |
; Nom de l'utilisateur de la base de données. |
bdd_utilisateur = "" |
; Mot de passe de l'utilisateur de la base de données. |
bdd_mot_de_passe = "" |
; Nom de la base de données principale. |
bdd_nom = "tb_eflore" |
; Encodage de la base de données principale au format base de données (ex. pour l'utf-8 ne pas mettre le tiret!). |
bdd_encodage = "utf8" |
; +------------------------------------------------------------------------------------------------------+ |
; Infos sur les services |
;chemin direct aux services |
serveur.baseURL = /moissonnage/services/ |
;URL à rediriger |
serveur.baseAlternativeURL = /service:moissonnage:0.1/ |
; Version des service web du projet |
service_version = 0.1 |
; Standard utilisé pour les codes de langue |
langue_source = "ISO-639-1"; |
; Standard utilisé pour les codes de zones géographiques |
zone_geo_source = "ISO-3166-1"; |
; URL de base des services |
url_base="http://localhost/" |
; URL de base des services |
url_service_base='{ref:url_base}service:moissonnage:0.1/' |
; +------------------------------------------------------------------------------------------------------+ |
; Infos sur les controles a effectuer sur les cartes et les donnees a afficher |
carte.limite_ouest = -180 |
carte.limite_est = 180 |
carte.limite_sud = -85.051129 |
carte.limite_nord = 85.051129 |
carte.zoom_minimal = 3 |
carte.zoom_maximal = 18 |
zoom_maximal_maillage = 13 |
seuil_maillage = 250 |
; valeurs des rangs au niveau de la classification des taxons |
rang.genre = 220 |
rang.famille = 180 |
rang.espece = 290 |
rang.sous_espece = 320 |
; +------------------------------------------------------------------------------------------------------+ |
; Autres informations |
sources_dispo = "floradata,sophy,baznat" |
source_defaut = "floradata" |
services_dispo = "stations,observations,wfs" |
referentiels_dispo = "bdtfx_v1_01,bdtxa_v1_00" |
operations_wfs = "GetCapabilities,DescribeFeatureType,GetFeature" |
operateurs_wfs = "PropertyIsEqualTo,PropertyIsLike,BBOX" |
champ_filtrage_wfs = "taxon" |
/trunk/services/configurations/config_floradata.ini |
---|
New file |
0,0 → 1,15 |
; Encodage : UTF-8 |
; Nom du projet |
nom_source = "floradata" |
; Nom de la base utilisée. |
bdd_nom_floradata = "tb_cel" |
bdd_nom_eflore = "tb_eflore" |
; URL de base des services de ce projet |
url_service="{ref:url_base}service:moissonnage:0.1/floradata" |
[meta-donnees] |
dureecache = 3600 |
/trunk/services/configurations/config_baznat.ini |
---|
New file |
0,0 → 1,16 |
; Encodage : UTF-8 |
; Nom du projet |
nom_source = "baznat" |
; Nom de la base utilisée. |
bdd_nom_eflore = "tb_eflore" |
; URL de base des services de ce projet |
url_service="{ref:url_base}service:moissonnage:0.1/baznat" |
referentiel_source = "bdtfx" |
[meta-donnees] |
dureecache = 3600 |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/trunk/services/configurations/config_sophy.ini |
---|
New file |
0,0 → 1,15 |
; Encodage : UTF-8 |
; Nom du projet |
nom_source = "sophy" |
; Nom de la base utilisée. |
bdd_nom_eflore = "tb_eflore" |
; URL de base des services de ce projet |
url_service="{ref:url_base}service:moissonnage:0.1/sophy" |
referentiel_source = "bdtfx" |
[meta-donnees] |
dureecache = 3600 |
/trunk/services/configurations |
---|
New file |
Property changes: |
Added: svn:ignore |
+config.ini |
/trunk/services/framework.defaut.php |
---|
New file |
0,0 → 1,6 |
<?php |
// Inclusion du Framework |
// Renomer ce fichier en "framework.php" |
// Indiquer ci-dessous le chemin absolu vers le fichier autoload.inc.php de la bonne version du Framework |
require_once '/home/alex/web/framework-0.3/framework/Framework.php'; |
?> |
/trunk/services |
---|
New file |
Property changes: |
Added: svn:ignore |
+.htaccess |
/trunk/widget/modules/carto/config.defaut.ini |
---|
New file |
0,0 → 1,19 |
[carto] |
communeImageUrl = "http://www.tela-botanica.org/commun/icones/carto/commune.png" |
pointImageUrl = "http://www.tela-botanica.org/commun/icones/carto/point2.png" |
clusterImageUrl = "http://www.tela-botanica.org/commun/icones/carto/cluster.png" |
sourcesDispo = "floradata,sophy" |
sourceParDefaut = "floradata" |
liensVersSources = "http://www.tela-botanica.org/page:cel,http://sophy.u-3mrs.fr/" |
nomSourcesDispo = "Observations Flora Data,Données Sophy" |
titreLegende = "Nombre Stations par maille" |
; Chemin vers le dossier contenant les fichiers kmz des limites communales |
communesKmzChemin = "/home/telabotap/www/carto/kml/communes/,/home/telabotap/www/carto/kml/communes_incompletes/" |
; Template de l'url où charger les fichiers kml des limites communales. |
limitesCommunaleUrlTpl = "http://www.tela-botanica.org/carto/kml/%s/%s" |
;parametres lies a l'affichage des donnees sur la carte |
zoomMaximumMaillage = 13 |
seuilMaillage = 250 |
/trunk/widget/modules/carto/Carto.php |
---|
New file |
0,0 → 1,174 |
<?php |
class Carto extends WidgetCommun { |
const SERVICE_CARTO_NOM = 'carto'; |
const SERVICE_CARTO_ACTION_DEFAUT = 'carto'; |
private $carte = null; |
private $source = null; |
private $titre = null; |
private $logo = null; |
private $urlSite = null; |
private $numeroNomenclatural = '*'; |
private $numeroTaxon = '*'; |
private $referentiel = '*'; |
private $departement = '*'; |
private $auteur = '*'; |
private $dateDebut = '*'; |
private $dateFin = '*'; |
private $nbJours = 0; |
/** |
* Methode appelee par defaut pour executer ce widget |
*/ |
public function executer() { |
$retour = null; |
// recuperer les parametres de l'URL |
$this->extraireParametres(); |
// verifier la disponibilite des services et ressources demandees |
$methode = $this->traiterNomMethodeExecuter($this->carte); |
if (method_exists($this, $methode)) { |
$retour = $this->$methode(); |
} else { |
$this->messages[] = "Ce type de service '$methode' n'est pas disponible."; |
} |
if (is_null($retour)) { |
$info = 'Un problème est survenu : '.print_r($this->messages, true); |
$this->envoyer($info); |
} else { |
$squelette = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'squelettes' . DIRECTORY_SEPARATOR |
. $retour['squelette'] . '.tpl.html'; |
$html = $this->traiterSquelettePhp($squelette, $retour['donnees']); |
$this->envoyer($html); |
} |
} |
public function extraireParametres() { |
extract($this->parametres); |
$this->carte = (isset($carte) ? $carte : self::SERVICE_CARTO_ACTION_DEFAUT); |
$this->source = (isset($source) ? $source : $this->config['carto']['sourceParDefaut']); |
$this->logo = (isset($logo) ? $logo : null); |
$this->titre = (isset($titre) ? $titre : null); |
$this->urlSite = (isset($url_site) ? $url_site : null); |
$this->numeroTaxon = (isset($num_taxon) ? $num_taxon : '*'); |
$this->numeroNomenclatural = (isset($nn) ? $nn : '*'); |
$this->departement = (isset($dept) ? $dept : '*'); |
$this->referentiel = (isset($referentiel) ? $referentiel : '*'); |
$this->auteur = (isset($auteur) ? $auteur : '*'); |
$this->dateDebut = (isset($date_debut) ? $date_debut : '*'); |
$this->dateFin = (isset($date_fin) ? $date_fin : '*'); |
$this->nbJours = (isset($nb_jours) ? intval($nb_jours) : 0); |
} |
/** |
* Carte par défaut |
*/ |
public function executerCarto() { |
$widget = null; |
$url_base = sprintf($this->config['chemins']['baseURLAbsoluDyn'], ''); |
// Création des infos du widget |
$widget['donnees']['url_serivce_carto'] = $this->contruireUrlServiceCarto(); |
$widget['donnees']['url_base'] = $url_base; |
$widget['donnees']['source'] = $this->source; |
$widget['donnees']['titre'] = $this->titre; |
$widget['donnees']['logo'] = $this->logo; |
$widget['donnees']['url_site'] = $this->urlSite; |
$widget['donnees']['auteur'] = $this->auteur; |
$widget['donnees']['nn'] = $this->numeroNomenclatural; |
$widget['donnees']['num_taxon'] = $this->numeroTaxon; |
$widget['donnees']['departement'] = $this->departement; |
$widget['donnees']['referentiel'] = $this->referentiel; |
$widget['donnees']['date_debut'] = $this->dateDebut; |
$widget['donnees']['date_fin'] = $this->dateFin; |
$widget['donnees']['nb_jours'] = $this->nbJours; |
$widget['donnees']['communeImageUrl'] = $this->config['carto']['communeImageUrl']; |
$widget['donnees']['pointImageUrl'] = $this->config['carto']['pointImageUrl']; |
$widget['donnees']['clusterImageUrl'] = $this->config['carto']['clusterImageUrl']; |
$widget['donnees']['liensVersSources'] = $this->config['carto']['liensVersSources']; |
$widget['donnees']['listeSources'] = $this->config['carto']['sourcesDispo']; |
$widget['donnees']['nomListeSources'] = $this->config['carto']['nomSourcesDispo']; |
$widget['donnees']['titreLegende'] = $this->config['carto']['titreLegende']; |
$widget['donnees']['urlLimitesCommunales'] = $this->obtenirUrlsLimitesCommunales(); |
$widget['donnees']['zoomMaximumMaillage'] = $this->config['carto']['zoomMaximumMaillage']; |
$widget['donnees']['seuilMaillage'] = $this->config['carto']['seuilMaillage']; |
$widget['squelette'] = 'carto'; |
return $widget; |
} |
private function contruireUrlServiceCarto($action = null) { |
// Création url données json |
$url = sprintf($this->config['chemins']['baseURLServicesTpl'], ''); |
if ($action) { |
$url .= "/$action"; |
$parametres_retenus = array(); |
$parametres_a_tester = array('source', 'utilisateur', 'referentiel', 'dept', 'num_taxon'); |
foreach ($parametres_a_tester as $param) { |
if (isset($this->$param) && $this->$param != '*') { |
$parametres_retenus[$param] = $this->$param; |
} |
} |
if (count($parametres_retenus) > 0) { |
$parametres_url = array(); |
foreach ($parametres_retenus as $cle => $valeur) { |
$parametres_url[] = $cle.'='.$valeur; |
} |
$url .= '?'.implode('&', $parametres_url); |
} |
} |
return $url; |
} |
private function obtenirUrlsLimitesCommunales() { |
$urls = null; |
if (isset($this->departement)) { |
// si on veut afficher les limites départementales on va compter et chercher les noms de fichiers |
$fichiersKml = $this->chercherFichierKml(); |
if (count($fichiersKml) > 0) { |
foreach ($fichiersKml as $kml => $dossier){ |
$url_limites_communales = sprintf($this->config['carto']['limitesCommunaleUrlTpl'], $dossier, $kml); |
$urls[] = $url_limites_communales; |
} |
} |
} |
$urls = json_encode($urls); |
return $urls; |
} |
private function chercherFichierKml(){ |
$fichiers = array(); |
$chemins = explode(',', $this->config['carto']['communesKmzChemin']); |
$departements = explode(',', $this->departement);// plrs code de départements peuvent être demandés séparés par des virgules |
$departements_trouves = array(); |
foreach ($chemins as $dossier_chemin) { |
if ($dossier_ressource = opendir($dossier_chemin)) { |
while ($element = readdir($dossier_ressource)) { |
if ($element != '.' && $element != '..') { |
foreach ($departements as $departement) { |
$nom_dossier = basename($dossier_chemin); |
if (!isset($departements_trouves[$departement]) || $departements_trouves[$departement] == $nom_dossier) { |
$dept_protege = preg_quote($departement); |
if (!is_dir($dossier_chemin.'/'.$element) && preg_match("/^$dept_protege(?:_[0-9]+|)\.kml$/", $element)) { |
$fichiers[$element] = $nom_dossier; |
$departements_trouves[$departement] = $nom_dossier; |
} |
} |
} |
} |
} |
closedir($dossier_ressource); |
} |
} |
return $fichiers; |
} |
} |
?> |
/trunk/widget/modules/carto/squelettes/images/tri_decroissant.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
/trunk/widget/modules/carto/squelettes/images/tri_decroissant.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+image/png |
\ No newline at end of property |
/trunk/widget/modules/carto/squelettes/images/chargement.gif |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/trunk/widget/modules/carto/squelettes/images/chargement.gif |
---|
New file |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/trunk/widget/modules/carto/squelettes/images/fermeture.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
/trunk/widget/modules/carto/squelettes/images/fermeture.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+image/png |
\ No newline at end of property |
/trunk/widget/modules/carto/squelettes/images/tri.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
/trunk/widget/modules/carto/squelettes/images/tri.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+image/png |
\ No newline at end of property |
/trunk/widget/modules/carto/squelettes/images/ouverture.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
/trunk/widget/modules/carto/squelettes/images/ouverture.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+image/png |
\ No newline at end of property |
/trunk/widget/modules/carto/squelettes/images/tri_croissant.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
/trunk/widget/modules/carto/squelettes/images/tri_croissant.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+image/png |
\ No newline at end of property |
/trunk/widget/modules/carto/squelettes/images/information.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
/trunk/widget/modules/carto/squelettes/images/information.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+image/png |
\ No newline at end of property |
/trunk/widget/modules/carto/squelettes/scripts/L.KML.js |
---|
New file |
0,0 → 1,393 |
/* |
* |
* Copyright (c) 2011-2012, Pavel Shramov |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without modification, are |
* permitted provided that the following conditions are met: |
* |
* 1. Redistributions of source code must retain the above copyright notice, this list of |
* conditions and the following disclaimer. |
* |
* 2. Redistributions in binary form must reproduce the above copyright notice, this list |
* of conditions and the following disclaimer in the documentation and/or other materials |
* provided with the distribution. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY |
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
*/ |
// Adaptation Alexandre GALIBERT : |
// - Define fill opacity for polygons at 0 for transparent rendering |
// - Disable creation of icons for KML elements |
// - Specific beahaviour to add an array of files by their urls. A variable will define |
// the status of the processing (BUSY or READY) and managed with a counter for the number |
// of files remaining to parse. Once all files parsed, the map zooms on KML spatial elements |
const KML_READY = 0; |
const KML_BUSY = 1; |
L.KML = L.FeatureGroup.extend({ |
options: { |
async: true |
}, |
initialize: function(kml, options) { |
L.Util.setOptions(this, options); |
this._kml = kml; |
this._status = KML_READY; |
this._onWaiting = 0; |
this._layers = {}; |
if (kml) { |
this.addKML(kml, options, this.options.async); |
} |
}, |
loadXML: function(url, cb, options, async) { |
if (async == undefined) async = this.options.async; |
if (options == undefined) options = this.options; |
var req = new window.XMLHttpRequest(); |
req.open('GET', url, async); |
try { |
req.overrideMimeType('text/xml'); // unsupported by IE |
} catch(e) {} |
req.onreadystatechange = function() { |
if (req.readyState != 4) return; |
if(req.status == 200) cb(req.responseXML, options); |
}; |
req.send(null); |
}, |
addKMLFiles: function(urlList, options, async) { |
this._status = KML_BUSY; |
this._onWaiting = urlList.length; |
for (var index = 0; index < urlList.length; index ++) { |
this.addKML(urlList[index], options, async); |
} |
}, |
addKML: function(url, options, async) { |
var _this = this; |
var cb = function(gpx, options) { _this._addKML(gpx, options) }; |
this.loadXML(url, cb, options, async); |
}, |
_addKML: function(xml, options) { |
var layers = L.KML.parseKML(xml); |
if (!layers || !layers.length) return; |
for (var i = 0; i < layers.length; i++) |
{ |
this.fire('addlayer', { |
layer: layers[i] |
}); |
this.addLayer(layers[i]); |
} |
this.latLngs = L.KML.getLatLngs(xml); |
this.fire("loaded"); |
this._onWaiting --; |
if (this._onWaiting == 0) { |
this._status = KML_READY; |
this._map.fitBounds(this.getBounds()); |
} |
}, |
getStatus: function() { |
return this._status; |
}, |
latLngs: [] |
}); |
L.Util.extend(L.KML, { |
parseKML: function (xml) { |
var style = this.parseStyle(xml); |
var el = xml.getElementsByTagName("Folder"); |
var layers = [], l; |
for (var i = 0; i < el.length; i++) { |
if (!this._check_folder(el[i])) { continue; } |
l = this.parseFolder(el[i], style); |
if (l) { layers.push(l); } |
} |
el = xml.getElementsByTagName('Placemark'); |
for (var j = 0; j < el.length; j++) { |
if (!this._check_folder(el[j])) { continue; } |
l = this.parsePlacemark(el[j], xml, style); |
if (l) { layers.push(l); } |
} |
return layers; |
}, |
// Return false if e's first parent Folder is not [folder] |
// - returns true if no parent Folders |
_check_folder: function (e, folder) { |
e = e.parentElement; |
while (e && e.tagName !== "Folder") |
{ |
e = e.parentElement; |
} |
return !e || e === folder; |
}, |
parseStyle: function (xml) { |
var style = {}; |
var sl = xml.getElementsByTagName("Style"); |
//for (var i = 0; i < sl.length; i++) { |
var attributes = {color: true, width: true, Icon: true, href: true, |
hotSpot: true}; |
function _parse(xml) { |
var options = {}; |
for (var i = 0; i < xml.childNodes.length; i++) { |
var e = xml.childNodes[i]; |
var key = e.tagName; |
if (!attributes[key]) { continue; } |
if (key === 'hotSpot') |
{ |
for (var j = 0; j < e.attributes.length; j++) { |
options[e.attributes[j].name] = e.attributes[j].nodeValue; |
} |
} else { |
var value = e.childNodes[0].nodeValue; |
if (key === 'color') { |
options.opacity = parseInt(value.substring(0, 2), 16) / 255.0; |
options.color = "#" + value.substring(2, 8); |
} else if (key === 'width') { |
options.weight = value; |
} else if (key === 'Icon') { |
ioptions = _parse(e); |
if (ioptions.href) { options.href = ioptions.href; } |
} else if (key === 'href') { |
options.href = value; |
} |
} |
} |
options.fillOpacity = 0; |
return options; |
} |
for (var i = 0; i < sl.length; i++) { |
var e = sl[i], el; |
var options = {}, poptions = {}, ioptions = {}; |
el = e.getElementsByTagName("LineStyle"); |
if (el && el[0]) { options = _parse(el[0]); } |
el = e.getElementsByTagName("PolyStyle"); |
if (el && el[0]) { poptions = _parse(el[0]); } |
if (poptions.color) { options.fillColor = poptions.color; } |
if (poptions.opacity) { options.fillOpacity = poptions.opacity; } |
el = e.getElementsByTagName("IconStyle"); |
if (el && el[0]) { ioptions = _parse(el[0]); } |
if (ioptions.href) { |
// save anchor info until the image is loaded |
options.icon = new L.KMLIcon({ |
iconUrl: ioptions.href, |
shadowUrl: null, |
iconAnchorRef: {x: ioptions.x, y: ioptions.y}, |
iconAnchorType: {x: ioptions.xunits, y: ioptions.yunits} |
}); |
} |
style['#' + e.getAttribute('id')] = options; |
} |
return style; |
}, |
parseFolder: function (xml, style) { |
var el, layers = [], l; |
el = xml.getElementsByTagName('Folder'); |
for (var i = 0; i < el.length; i++) { |
if (!this._check_folder(el[i], xml)) { continue; } |
l = this.parseFolder(el[i], style); |
if (l) { layers.push(l); } |
} |
el = xml.getElementsByTagName('Placemark'); |
for (var j = 0; j < el.length; j++) { |
if (!this._check_folder(el[j], xml)) { continue; } |
l = this.parsePlacemark(el[j], xml, style); |
if (l) { layers.push(l); } |
} |
if (!layers.length) { return; } |
if (layers.length === 1) { return layers[0]; } |
return new L.FeatureGroup(layers); |
}, |
parsePlacemark: function (place, xml, style) { |
var i, j, el, options = {}; |
el = place.getElementsByTagName('styleUrl'); |
for (i = 0; i < el.length; i++) { |
var url = el[i].childNodes[0].nodeValue; |
for (var a in style[url]) |
{ |
// for jshint |
if (true) |
{ |
options[a] = style[url][a]; |
} |
} |
} |
var layers = []; |
var parse = ['LineString', 'Polygon', 'Point']; |
for (j in parse) { |
// for jshint |
if (true) |
{ |
var tag = parse[j]; |
el = place.getElementsByTagName(tag); |
for (i = 0; i < el.length; i++) { |
var l = this["parse" + tag](el[i], xml, options); |
if (l) { layers.push(l); } |
} |
} |
} |
if (!layers.length) { |
return; |
} |
var layer = layers[0]; |
if (layers.length > 1) { |
layer = new L.FeatureGroup(layers); |
} |
var name, descr = ""; |
el = place.getElementsByTagName('name'); |
if (el.length) { |
name = el[0].childNodes[0].nodeValue; |
} |
el = place.getElementsByTagName('description'); |
for (i = 0; i < el.length; i++) { |
for (j = 0; j < el[i].childNodes.length; j++) { |
descr = descr + el[i].childNodes[j].nodeValue; |
} |
} |
/*if (name) { |
layer.bindPopup("<h2>" + name + "</h2>" + descr); |
}*/ |
return layer; |
}, |
parseCoords: function (xml) { |
var el = xml.getElementsByTagName('coordinates'); |
return this._read_coords(el[0]); |
}, |
parseLineString: function (line, xml, options) { |
var coords = this.parseCoords(line); |
if (!coords.length) { return; } |
return new L.Polyline(coords, options); |
}, |
parsePoint: function (line, xml, options) { |
var el = line.getElementsByTagName('coordinates'); |
if (!el.length) { |
return; |
} |
var ll = el[0].childNodes[0].nodeValue.split(','); |
return new L.KMLMarker(new L.LatLng(ll[1], ll[0]), options); |
}, |
parsePolygon: function (line, xml, options) { |
var el, polys = [], inner = [], i, coords; |
el = line.getElementsByTagName('outerBoundaryIs'); |
for (i = 0; i < el.length; i++) { |
coords = this.parseCoords(el[i]); |
if (coords) { |
polys.push(coords); |
} |
} |
el = line.getElementsByTagName('innerBoundaryIs'); |
for (i = 0; i < el.length; i++) { |
coords = this.parseCoords(el[i]); |
if (coords) { |
inner.push(coords); |
} |
} |
if (!polys.length) { |
return; |
} |
if (options.fillColor) { |
options.fill = true; |
} |
if (polys.length === 1) { |
return new L.Polygon(polys.concat(inner), options); |
} |
return new L.MultiPolygon(polys, options); |
}, |
getLatLngs: function (xml) { |
var el = xml.getElementsByTagName('coordinates'); |
var coords = []; |
for (var j = 0; j < el.length; j++) { |
// text might span many childnodes |
coords = coords.concat(this._read_coords(el[j])); |
} |
return coords; |
}, |
_read_coords: function (el) { |
var text = "", coords = [], i; |
for (i = 0; i < el.childNodes.length; i++) { |
text = text + el.childNodes[i].nodeValue; |
} |
text = text.split(/[\s\n]+/); |
for (i = 0; i < text.length; i++) { |
var ll = text[i].split(','); |
if (ll.length < 2) { |
continue; |
} |
coords.push(new L.LatLng(ll[1], ll[0])); |
} |
return coords; |
} |
}); |
L.KMLIcon = L.Icon.extend({ |
createIcon: function () { |
var img = this._createIcon('icon'); |
img.onload = function () { |
var i = new Image(); |
i.src = this.src; |
this.style.width = i.width + 'px'; |
this.style.height = i.height + 'px'; |
if (this.anchorType.x === 'UNITS_FRACTION' || this.anchorType.x === 'fraction') { |
img.style.marginLeft = (-this.anchor.x * i.width) + 'px'; |
} |
if (this.anchorType.y === 'UNITS_FRACTION' || this.anchorType.x === 'fraction') { |
img.style.marginTop = (-(1 - this.anchor.y) * i.height) + 'px'; |
} |
this.style.display = ""; |
}; |
return img; |
}, |
_setIconStyles: function (img, name) { |
L.Icon.prototype._setIconStyles.apply(this, [img, name]) |
// save anchor information to the image |
img.anchor = this.options.iconAnchorRef; |
img.anchorType = this.options.iconAnchorType; |
} |
}); |
L.KMLMarker = L.Marker.extend({ |
options: { |
icon: new L.KMLIcon.Default() |
} |
}); |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/trunk/widget/modules/carto/squelettes/scripts/leaflet.markercluster.js |
---|
New file |
0,0 → 1,6 |
/* |
Copyright (c) 2012, Smartrak, David Leaver |
Leaflet.markercluster is an open-source JavaScript library for Marker Clustering on leaflet powered maps. |
https://github.com/danzel/Leaflet.markercluster |
*/ |
(function(){L.MarkerClusterGroup=L.FeatureGroup.extend({options:{maxClusterRadius:80,iconCreateFunction:null,spiderfyOnMaxZoom:!0,showCoverageOnHover:!0,zoomToBoundsOnClick:!0,singleMarkerMode:!1,disableClusteringAtZoom:null,removeOutsideVisibleBounds:!0,animateAddingMarkers:!1,spiderfyDistanceMultiplier:1,polygonOptions:{}},initialize:function(t){L.Util.setOptions(this,t),this.options.iconCreateFunction||(this.options.iconCreateFunction=this._defaultIconCreateFunction),L.FeatureGroup.prototype.initialize.call(this,[]),this._inZoomAnimation=0,this._needsClustering=[],this._needsRemoving=[],this._currentShownBounds=null},addLayer:function(t){if(t instanceof L.LayerGroup){var e=[];for(var i in t._layers)e.push(t._layers[i]);return this.addLayers(e)}if(!this._map)return this._needsClustering.push(t),this;if(this.hasLayer(t))return this;this._unspiderfy&&this._unspiderfy(),this._addLayer(t,this._maxZoom);var n=t,r=this._map.getZoom();if(t.__parent)for(;n.__parent._zoom>=r;)n=n.__parent;return this._currentShownBounds.contains(n.getLatLng())&&(this.options.animateAddingMarkers?this._animationAddLayer(t,n):this._animationAddLayerNonAnimated(t,n)),this},removeLayer:function(t){return this._map?t.__parent?(this._unspiderfy&&(this._unspiderfy(),this._unspiderfyLayer(t)),this._removeLayer(t,!0),t._icon&&(L.FeatureGroup.prototype.removeLayer.call(this,t),t.setOpacity(1)),this):this:(!this._arraySplice(this._needsClustering,t)&&this.hasLayer(t)&&this._needsRemoving.push(t),this)},addLayers:function(t){var e,i,n;if(!this._map)return this._needsClustering=this._needsClustering.concat(t),this;for(e=0,i=t.length;i>e;e++)if(n=t[e],!this.hasLayer(n)&&(this._addLayer(n,this._maxZoom),n.__parent&&2===n.__parent.getChildCount())){var r=n.__parent.getAllChildMarkers(),s=r[0]===n?r[1]:r[0];L.FeatureGroup.prototype.removeLayer.call(this,s)}for(e in this._layers)n=this._layers[e],n instanceof L.MarkerCluster&&n._iconNeedsUpdate&&n._updateIcon();return this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,this._currentShownBounds),this},removeLayers:function(t){var e,i,n;if(!this._map){for(e=0,i=t.length;i>e;e++)this._arraySplice(this._needsClustering,t[e]);return this}for(e=0,i=t.length;i>e;e++)n=t[e],n.__parent&&(this._removeLayer(n,!0,!0),n._icon&&(L.FeatureGroup.prototype.removeLayer.call(this,n),n.setOpacity(1)));this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,this._currentShownBounds);for(e in this._layers)n=this._layers[e],n instanceof L.MarkerCluster&&n._updateIcon();return this},clearLayers:function(){this._map||(this._needsClustering=[],delete this._gridClusters,delete this._gridUnclustered),this._noanimationUnspiderfy&&this._noanimationUnspiderfy();for(var t in this._layers)L.FeatureGroup.prototype.removeLayer.call(this,this._layers[t]);return this.eachLayer(function(t){delete t.__parent}),this._map&&this._generateInitialClusters(),this},getBounds:function(){var t=new L.LatLngBounds;if(this._topClusterLevel)t.extend(this._topClusterLevel._bounds);else for(var e=this._needsClustering.length-1;e>=0;e--)t.extend(this._needsClustering[e].getLatLng());return t},eachLayer:function(t,e){var i,n=this._needsClustering.slice();for(this._topClusterLevel&&this._topClusterLevel.getAllChildMarkers(n),i=n.length-1;i>=0;i--)t.call(e,n[i])},hasLayer:function(t){if(t._noHas)return!1;var e,i=this._needsClustering;for(e=i.length-1;e>=0;e--)if(i[e]===t)return!0;for(i=this._needsRemoving,e=i.length-1;e>=0;e--)if(i[e]===t)return!1;return!(!t.__parent||t.__parent._group!==this)},zoomToShowLayer:function(t,e){var i=function(){if((t._icon||t.__parent._icon)&&!this._inZoomAnimation)if(this._map.off("moveend",i,this),this.off("animationend",i,this),t._icon)e();else if(t.__parent._icon){var n=function(){this.off("spiderfied",n,this),e()};this.on("spiderfied",n,this),t.__parent.spiderfy()}};t._icon?e():t.__parent._zoom<this._map.getZoom()?(this._map.on("moveend",i,this),t._icon||this._map.panTo(t.getLatLng())):(this._map.on("moveend",i,this),this.on("animationend",i,this),this._map.setView(t.getLatLng(),t.__parent._zoom+1),t.__parent.zoomToBounds())},onAdd:function(t){this._map=t;var e,i,n;for(this._gridClusters||this._generateInitialClusters(),e=0,i=this._needsRemoving.length;i>e;e++)n=this._needsRemoving[e],this._removeLayer(n);for(this._needsRemoving=[],e=0,i=this._needsClustering.length;i>e;e++)n=this._needsClustering[e],n.__parent||this._addLayer(n,this._maxZoom);this._needsClustering=[],this._map.on("zoomend",this._zoomEnd,this),this._map.on("moveend",this._moveEnd,this),this._spiderfierOnAdd&&this._spiderfierOnAdd(),this._bindEvents(),this._zoom=this._map.getZoom(),this._currentShownBounds=this._getExpandedVisibleBounds(),this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,this._currentShownBounds)},onRemove:function(t){t.off("zoomend",this._zoomEnd,this),t.off("moveend",this._moveEnd,this),this._unbindEvents(),this._map._mapPane.className=this._map._mapPane.className.replace(" leaflet-cluster-anim",""),this._spiderfierOnRemove&&this._spiderfierOnRemove();for(var e in this._layers)L.FeatureGroup.prototype.removeLayer.call(this,this._layers[e]);this._map=null},_arraySplice:function(t,e){for(var i=t.length-1;i>=0;i--)if(t[i]===e)return t.splice(i,1),!0},_removeLayer:function(t,e,i){var n=this._gridClusters,r=this._gridUnclustered,s=this._map;if(e)for(var o=this._maxZoom;o>=0&&r[o].removeObject(t,s.project(t.getLatLng(),o));o--);var a,l=t.__parent,_=l._markers;for(this._arraySplice(_,t);l&&(l._childCount--,!(0>l._zoom));)e&&1>=l._childCount?(a=l._markers[0]===t?l._markers[1]:l._markers[0],n[l._zoom].removeObject(l,s.project(l._cLatLng,l._zoom)),r[l._zoom].addObject(a,s.project(a.getLatLng(),l._zoom)),this._arraySplice(l.__parent._childClusters,l),l.__parent._markers.push(a),a.__parent=l.__parent,l._icon&&(L.FeatureGroup.prototype.removeLayer.call(this,l),i||L.FeatureGroup.prototype.addLayer.call(this,a))):(l._recalculateBounds(),i&&l._icon||l._updateIcon()),l=l.__parent;delete t.__parent},_propagateEvent:function(t){t.target instanceof L.MarkerCluster&&(t.type="cluster"+t.type),L.FeatureGroup.prototype._propagateEvent.call(this,t)},_defaultIconCreateFunction:function(t){var e=t.getChildCount(),i=" marker-cluster-";return i+=10>e?"small":100>e?"medium":"large",new L.DivIcon({html:"<div><span>"+e+"</span></div>",className:"marker-cluster"+i,iconSize:new L.Point(40,40)})},_bindEvents:function(){var t=null,e=this._map,i=this.options.spiderfyOnMaxZoom,n=this.options.showCoverageOnHover,r=this.options.zoomToBoundsOnClick;(i||r)&&this.on("clusterclick",function(t){e.getMaxZoom()===e.getZoom()?i&&t.layer.spiderfy():r&&t.layer.zoomToBounds()},this),n&&(this.on("clustermouseover",function(i){this._inZoomAnimation||(t&&e.removeLayer(t),i.layer.getChildCount()>2&&i.layer!==this._spiderfied&&(t=new L.Polygon(i.layer.getConvexHull(),this.options.polygonOptions),e.addLayer(t)))},this),this.on("clustermouseout",function(){t&&(e.removeLayer(t),t=null)},this),e.on("zoomend",function(){t&&(e.removeLayer(t),t=null)},this),e.on("layerremove",function(i){t&&i.layer===this&&(e.removeLayer(t),t=null)},this))},_unbindEvents:function(){var t=this.options.spiderfyOnMaxZoom,e=this.options.showCoverageOnHover,i=this.options.zoomToBoundsOnClick,n=this._map;(t||i)&&this.off("clusterclick",null,this),e&&(this.off("clustermouseover",null,this),this.off("clustermouseout",null,this),n.off("zoomend",null,this),n.off("layerremove",null,this))},_zoomEnd:function(){this._map&&(this._mergeSplitClusters(),this._zoom=this._map._zoom,this._currentShownBounds=this._getExpandedVisibleBounds())},_moveEnd:function(){if(!this._inZoomAnimation){var t=this._getExpandedVisibleBounds();this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,this._zoom,t),this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,t),this._currentShownBounds=t}},_generateInitialClusters:function(){var t=this._map.getMaxZoom(),e=this.options.maxClusterRadius;this.options.disableClusteringAtZoom&&(t=this.options.disableClusteringAtZoom-1),this._maxZoom=t,this._gridClusters={},this._gridUnclustered={};for(var i=t;i>=0;i--)this._gridClusters[i]=new L.DistanceGrid(e),this._gridUnclustered[i]=new L.DistanceGrid(e);this._topClusterLevel=new L.MarkerCluster(this,-1)},_addLayer:function(t,e){var i,n,r=this._gridClusters,s=this._gridUnclustered;for(this.options.singleMarkerMode&&(t.options.icon=this.options.iconCreateFunction({getChildCount:function(){return 1},getAllChildMarkers:function(){return[t]}}));e>=0;e--){i=this._map.project(t.getLatLng(),e);var o=r[e].getNearObject(i);if(o)return o._addChild(t),t.__parent=o,void 0;if(o=s[e].getNearObject(i)){var a=o.__parent;a&&this._removeLayer(o,!1);var l=new L.MarkerCluster(this,e,o,t);r[e].addObject(l,this._map.project(l._cLatLng,e)),o.__parent=l,t.__parent=l;var _=l;for(n=e-1;n>a._zoom;n--)_=new L.MarkerCluster(this,n,_),r[n].addObject(_,this._map.project(o.getLatLng(),n));for(a._addChild(_),n=e;n>=0&&s[n].removeObject(o,this._map.project(o.getLatLng(),n));n--);return}s[e].addObject(t,i)}this._topClusterLevel._addChild(t),t.__parent=this._topClusterLevel},_mergeSplitClusters:function(){this._zoom<this._map._zoom?(this._animationStart(),this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,this._zoom,this._getExpandedVisibleBounds()),this._animationZoomIn(this._zoom,this._map._zoom)):this._zoom>this._map._zoom?(this._animationStart(),this._animationZoomOut(this._zoom,this._map._zoom)):this._moveEnd()},_getExpandedVisibleBounds:function(){if(!this.options.removeOutsideVisibleBounds)return this.getBounds();var t=this._map,e=t.getBounds(),i=e._southWest,n=e._northEast,r=L.Browser.mobile?0:Math.abs(i.lat-n.lat),s=L.Browser.mobile?0:Math.abs(i.lng-n.lng);return new L.LatLngBounds(new L.LatLng(i.lat-r,i.lng-s,!0),new L.LatLng(n.lat+r,n.lng+s,!0))},_animationAddLayerNonAnimated:function(t,e){if(e===t)L.FeatureGroup.prototype.addLayer.call(this,t);else if(2===e._childCount){e._addToMap();var i=e.getAllChildMarkers();L.FeatureGroup.prototype.removeLayer.call(this,i[0]),L.FeatureGroup.prototype.removeLayer.call(this,i[1])}else e._updateIcon()}}),L.MarkerClusterGroup.include(L.DomUtil.TRANSITION?{_animationStart:function(){this._map._mapPane.className+=" leaflet-cluster-anim",this._inZoomAnimation++},_animationEnd:function(){this._map&&(this._map._mapPane.className=this._map._mapPane.className.replace(" leaflet-cluster-anim","")),this._inZoomAnimation--,this.fire("animationend")},_animationZoomIn:function(t,e){var i,n=this,r=this._getExpandedVisibleBounds();this._topClusterLevel._recursively(r,t,0,function(s){var o,a=s._latlng,l=s._markers;for(s._isSingleParent()&&t+1===e?(L.FeatureGroup.prototype.removeLayer.call(n,s),s._recursivelyAddChildrenToMap(null,e,r)):(s.setOpacity(0),s._recursivelyAddChildrenToMap(a,e,r)),i=l.length-1;i>=0;i--)o=l[i],r.contains(o._latlng)||L.FeatureGroup.prototype.removeLayer.call(n,o)}),this._forceLayout();var s,o;n._topClusterLevel._recursivelyBecomeVisible(r,e);for(s in n._layers)o=n._layers[s],o instanceof L.MarkerCluster||!o._icon||o.setOpacity(1);n._topClusterLevel._recursively(r,t,e,function(t){t._recursivelyRestoreChildPositions(e)}),setTimeout(function(){n._topClusterLevel._recursively(r,t,0,function(t){L.FeatureGroup.prototype.removeLayer.call(n,t),t.setOpacity(1)}),n._animationEnd()},200)},_animationZoomOut:function(t,e){this._animationZoomOutSingle(this._topClusterLevel,t-1,e),this._topClusterLevel._recursivelyAddChildrenToMap(null,e,this._getExpandedVisibleBounds()),this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,t,this._getExpandedVisibleBounds())},_animationZoomOutSingle:function(t,e,i){var n=this._getExpandedVisibleBounds();t._recursivelyAnimateChildrenInAndAddSelfToMap(n,e+1,i);var r=this;this._forceLayout(),t._recursivelyBecomeVisible(n,i),setTimeout(function(){if(1===t._childCount){var s=t._markers[0];s.setLatLng(s.getLatLng()),s.setOpacity(1)}else t._recursively(n,i,0,function(t){t._recursivelyRemoveChildrenFromMap(n,e+1)});r._animationEnd()},200)},_animationAddLayer:function(t,e){var i=this;L.FeatureGroup.prototype.addLayer.call(this,t),e!==t&&(e._childCount>2?(e._updateIcon(),this._forceLayout(),this._animationStart(),t._setPos(this._map.latLngToLayerPoint(e.getLatLng())),t.setOpacity(0),setTimeout(function(){L.FeatureGroup.prototype.removeLayer.call(i,t),t.setOpacity(1),i._animationEnd()},200)):(this._forceLayout(),i._animationStart(),i._animationZoomOutSingle(e,this._map.getMaxZoom(),this._map.getZoom())))},_forceLayout:function(){L.Util.falseFn(document.body.offsetWidth)}}:{_animationStart:function(){},_animationZoomIn:function(t,e){this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,t),this._topClusterLevel._recursivelyAddChildrenToMap(null,e,this._getExpandedVisibleBounds())},_animationZoomOut:function(t,e){this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,t),this._topClusterLevel._recursivelyAddChildrenToMap(null,e,this._getExpandedVisibleBounds())},_animationAddLayer:function(t,e){this._animationAddLayerNonAnimated(t,e)}}),L.MarkerCluster=L.Marker.extend({initialize:function(t,e,i,n){L.Marker.prototype.initialize.call(this,i?i._cLatLng||i.getLatLng():new L.LatLng(0,0),{icon:this}),this._group=t,this._zoom=e,this._markers=[],this._childClusters=[],this._childCount=0,this._iconNeedsUpdate=!0,this._bounds=new L.LatLngBounds,i&&this._addChild(i),n&&this._addChild(n)},getAllChildMarkers:function(t){t=t||[];for(var e=this._childClusters.length-1;e>=0;e--)this._childClusters[e].getAllChildMarkers(t);for(var i=this._markers.length-1;i>=0;i--)t.push(this._markers[i]);return t},getChildCount:function(){return this._childCount},zoomToBounds:function(){this._group._map.fitBounds(this._bounds)},getBounds:function(){var t=new L.LatLngBounds;return t.extend(this._bounds),t},_updateIcon:function(){this._iconNeedsUpdate=!0,this._icon&&this.setIcon(this)},createIcon:function(){return this._iconNeedsUpdate&&(this._iconObj=this._group.options.iconCreateFunction(this),this._iconNeedsUpdate=!1),this._iconObj.createIcon()},createShadow:function(){return this._iconObj.createShadow()},_addChild:function(t,e){this._iconNeedsUpdate=!0,this._expandBounds(t),t instanceof L.MarkerCluster?(e||(this._childClusters.push(t),t.__parent=this),this._childCount+=t._childCount):(e||this._markers.push(t),this._childCount++),this.__parent&&this.__parent._addChild(t,!0)},_expandBounds:function(t){var e,i=t._wLatLng||t._latlng;t instanceof L.MarkerCluster?(this._bounds.extend(t._bounds),e=t._childCount):(this._bounds.extend(i),e=1),this._cLatLng||(this._cLatLng=t._cLatLng||i);var n=this._childCount+e;this._wLatLng?(this._wLatLng.lat=(i.lat*e+this._wLatLng.lat*this._childCount)/n,this._wLatLng.lng=(i.lng*e+this._wLatLng.lng*this._childCount)/n):this._latlng=this._wLatLng=new L.LatLng(i.lat,i.lng)},_addToMap:function(t){t&&(this._backupLatlng=this._latlng,this.setLatLng(t)),this._noHas=!0,L.FeatureGroup.prototype.addLayer.call(this._group,this),delete this._noHas},_recursivelyAnimateChildrenIn:function(t,e,i){this._recursively(t,0,i-1,function(t){var i,n,r=t._markers;for(i=r.length-1;i>=0;i--)n=r[i],n._icon&&(n._setPos(e),n.setOpacity(0))},function(t){var i,n,r=t._childClusters;for(i=r.length-1;i>=0;i--)n=r[i],n._icon&&(n._setPos(e),n.setOpacity(0))})},_recursivelyAnimateChildrenInAndAddSelfToMap:function(t,e,i){this._recursively(t,i,0,function(n){n._recursivelyAnimateChildrenIn(t,n._group._map.latLngToLayerPoint(n.getLatLng()).round(),e),n._isSingleParent()&&e-1===i?(n.setOpacity(1),n._recursivelyRemoveChildrenFromMap(t,e)):n.setOpacity(0),n._addToMap()})},_recursivelyBecomeVisible:function(t,e){this._recursively(t,0,e,null,function(t){t.setOpacity(1)})},_recursivelyAddChildrenToMap:function(t,e,i){this._recursively(i,-1,e,function(n){if(e!==n._zoom)for(var r=n._markers.length-1;r>=0;r--){var s=n._markers[r];i.contains(s._latlng)&&(t&&(s._backupLatlng=s.getLatLng(),s.setLatLng(t),s.setOpacity(0)),s._noHas=!0,L.FeatureGroup.prototype.addLayer.call(n._group,s),delete s._noHas)}},function(e){e._addToMap(t)})},_recursivelyRestoreChildPositions:function(t){for(var e=this._markers.length-1;e>=0;e--){var i=this._markers[e];i._backupLatlng&&(i.setLatLng(i._backupLatlng),delete i._backupLatlng)}if(t-1===this._zoom)for(var n=this._childClusters.length-1;n>=0;n--)this._childClusters[n]._restorePosition();else for(var r=this._childClusters.length-1;r>=0;r--)this._childClusters[r]._recursivelyRestoreChildPositions(t)},_restorePosition:function(){this._backupLatlng&&(this.setLatLng(this._backupLatlng),delete this._backupLatlng)},_recursivelyRemoveChildrenFromMap:function(t,e,i){var n,r;this._recursively(t,-1,e-1,function(t){for(r=t._markers.length-1;r>=0;r--)n=t._markers[r],i&&i.contains(n._latlng)||(L.FeatureGroup.prototype.removeLayer.call(t._group,n),n.setOpacity(1))},function(t){for(r=t._childClusters.length-1;r>=0;r--)n=t._childClusters[r],i&&i.contains(n._latlng)||((!L.FeatureGroup.prototype.hasLayer||L.FeatureGroup.prototype.hasLayer.call(t._group,n))&&L.FeatureGroup.prototype.removeLayer.call(t._group,n),n.setOpacity(1))})},_recursively:function(t,e,i,n,r){var s,o,a=this._childClusters,l=this._zoom;if(e>l)for(s=a.length-1;s>=0;s--)o=a[s],t.intersects(o._bounds)&&o._recursively(t,e,i,n,r);else if(n&&n(this),r&&this._zoom===i&&r(this),i>l)for(s=a.length-1;s>=0;s--)o=a[s],t.intersects(o._bounds)&&o._recursively(t,e,i,n,r)},_recalculateBounds:function(){var t,e=this._markers,i=this._childClusters;for(this._bounds=new L.LatLngBounds,delete this._wLatLng,t=e.length-1;t>=0;t--)this._expandBounds(e[t]);for(t=i.length-1;t>=0;t--)this._expandBounds(i[t])},_isSingleParent:function(){return this._childClusters.length>0&&this._childClusters[0]._childCount===this._childCount}}),L.DistanceGrid=function(t){this._cellSize=t,this._sqCellSize=t*t,this._grid={},this._objectPoint={}},L.DistanceGrid.prototype={addObject:function(t,e){var i=this._getCoord(e.x),n=this._getCoord(e.y),r=this._grid,s=r[n]=r[n]||{},o=s[i]=s[i]||[],a=L.Util.stamp(t);this._objectPoint[a]=e,o.push(t)},updateObject:function(t,e){this.removeObject(t),this.addObject(t,e)},removeObject:function(t,e){var i,n,r=this._getCoord(e.x),s=this._getCoord(e.y),o=this._grid,a=o[s]=o[s]||{},l=a[r]=a[r]||[];for(delete this._objectPoint[L.Util.stamp(t)],i=0,n=l.length;n>i;i++)if(l[i]===t)return l.splice(i,1),1===n&&delete a[r],!0},eachObject:function(t,e){var i,n,r,s,o,a,l,_=this._grid;for(i in _){o=_[i];for(n in o)for(a=o[n],r=0,s=a.length;s>r;r++)l=t.call(e,a[r]),l&&(r--,s--)}},getNearObject:function(t){var e,i,n,r,s,o,a,l,_=this._getCoord(t.x),h=this._getCoord(t.y),u=this._objectPoint,d=this._sqCellSize,p=null;for(e=h-1;h+1>=e;e++)if(r=this._grid[e])for(i=_-1;_+1>=i;i++)if(s=r[i])for(n=0,o=s.length;o>n;n++)a=s[n],l=this._sqDist(u[L.Util.stamp(a)],t),d>l&&(d=l,p=a);return p},_getCoord:function(t){return Math.floor(t/this._cellSize)},_sqDist:function(t,e){var i=e.x-t.x,n=e.y-t.y;return i*i+n*n}},function(){L.QuickHull={getDistant:function(t,e){var i=e[1].lat-e[0].lat,n=e[0].lng-e[1].lng;return n*(t.lat-e[0].lat)+i*(t.lng-e[0].lng)},findMostDistantPointFromBaseLine:function(t,e){var i,n,r,s=0,o=null,a=[];for(i=e.length-1;i>=0;i--)n=e[i],r=this.getDistant(n,t),r>0&&(a.push(n),r>s&&(s=r,o=n));return{maxPoint:o,newPoints:a}},buildConvexHull:function(t,e){var i=[],n=this.findMostDistantPointFromBaseLine(t,e);return n.maxPoint?(i=i.concat(this.buildConvexHull([t[0],n.maxPoint],n.newPoints)),i=i.concat(this.buildConvexHull([n.maxPoint,t[1]],n.newPoints))):[t]},getConvexHull:function(t){var e,i=!1,n=!1,r=null,s=null;for(e=t.length-1;e>=0;e--){var o=t[e];(i===!1||o.lat>i)&&(r=o,i=o.lat),(n===!1||n>o.lat)&&(s=o,n=o.lat)}var a=[].concat(this.buildConvexHull([s,r],t),this.buildConvexHull([r,s],t));return a}}}(),L.MarkerCluster.include({getConvexHull:function(){var t,e,i,n=this.getAllChildMarkers(),r=[],s=[];for(i=n.length-1;i>=0;i--)e=n[i].getLatLng(),r.push(e);for(t=L.QuickHull.getConvexHull(r),i=t.length-1;i>=0;i--)s.push(t[i][0]);return s}}),L.MarkerCluster.include({_2PI:2*Math.PI,_circleFootSeparation:25,_circleStartAngle:Math.PI/6,_spiralFootSeparation:28,_spiralLengthStart:11,_spiralLengthFactor:5,_circleSpiralSwitchover:9,spiderfy:function(){if(this._group._spiderfied!==this&&!this._group._inZoomAnimation){var t,e=this.getAllChildMarkers(),i=this._group,n=i._map,r=n.latLngToLayerPoint(this._latlng);this._group._unspiderfy(),this._group._spiderfied=this,e.length>=this._circleSpiralSwitchover?t=this._generatePointsSpiral(e.length,r):(r.y+=10,t=this._generatePointsCircle(e.length,r)),this._animationSpiderfy(e,t)}},unspiderfy:function(t){this._group._inZoomAnimation||(this._animationUnspiderfy(t),this._group._spiderfied=null)},_generatePointsCircle:function(t,e){var i,n,r=this._group.options.spiderfyDistanceMultiplier*this._circleFootSeparation*(2+t),s=r/this._2PI,o=this._2PI/t,a=[];for(a.length=t,i=t-1;i>=0;i--)n=this._circleStartAngle+i*o,a[i]=new L.Point(e.x+s*Math.cos(n),e.y+s*Math.sin(n))._round();return a},_generatePointsSpiral:function(t,e){var i,n=this._group.options.spiderfyDistanceMultiplier*this._spiralLengthStart,r=this._group.options.spiderfyDistanceMultiplier*this._spiralFootSeparation,s=this._group.options.spiderfyDistanceMultiplier*this._spiralLengthFactor,o=0,a=[];for(a.length=t,i=t-1;i>=0;i--)o+=r/n+5e-4*i,a[i]=new L.Point(e.x+n*Math.cos(o),e.y+n*Math.sin(o))._round(),n+=this._2PI*s/o;return a},_noanimationUnspiderfy:function(){var t,e,i=this._group,n=i._map,r=this.getAllChildMarkers();for(this.setOpacity(1),e=r.length-1;e>=0;e--)t=r[e],L.FeatureGroup.prototype.removeLayer.call(i,t),t._preSpiderfyLatlng&&(t.setLatLng(t._preSpiderfyLatlng),delete t._preSpiderfyLatlng),t.setZIndexOffset(0),t._spiderLeg&&(n.removeLayer(t._spiderLeg),delete t._spiderLeg)}}),L.MarkerCluster.include(L.DomUtil.TRANSITION?{SVG_ANIMATION:function(){return(""+document.createElementNS("http://www.w3.org/2000/svg","animate")).indexOf("SVGAnimate")>-1}(),_animationSpiderfy:function(t,e){var i,n,r,s,o=this,a=this._group,l=a._map,_=l.latLngToLayerPoint(this._latlng);for(i=t.length-1;i>=0;i--)n=t[i],n.setZIndexOffset(1e6),n.setOpacity(0),n._noHas=!0,L.FeatureGroup.prototype.addLayer.call(a,n),delete n._noHas,n._setPos(_);a._forceLayout(),a._animationStart();var h=L.Path.SVG?0:.3,u=L.Path.SVG_NS;for(i=t.length-1;i>=0;i--)if(s=l.layerPointToLatLng(e[i]),n=t[i],n._preSpiderfyLatlng=n._latlng,n.setLatLng(s),n.setOpacity(1),r=new L.Polyline([o._latlng,s],{weight:1.5,color:"#222",opacity:h}),l.addLayer(r),n._spiderLeg=r,L.Path.SVG&&this.SVG_ANIMATION){var d=r._path.getTotalLength();r._path.setAttribute("stroke-dasharray",d+","+d);var p=document.createElementNS(u,"animate");p.setAttribute("attributeName","stroke-dashoffset"),p.setAttribute("begin","indefinite"),p.setAttribute("from",d),p.setAttribute("to",0),p.setAttribute("dur",.25),r._path.appendChild(p),p.beginElement(),p=document.createElementNS(u,"animate"),p.setAttribute("attributeName","stroke-opacity"),p.setAttribute("attributeName","stroke-opacity"),p.setAttribute("begin","indefinite"),p.setAttribute("from",0),p.setAttribute("to",.5),p.setAttribute("dur",.25),r._path.appendChild(p),p.beginElement()}if(o.setOpacity(.3),L.Path.SVG)for(this._group._forceLayout(),i=t.length-1;i>=0;i--)n=t[i]._spiderLeg,n.options.opacity=.5,n._path.setAttribute("stroke-opacity",.5);setTimeout(function(){a._animationEnd(),a.fire("spiderfied")},200)},_animationUnspiderfy:function(t){var e,i,n,r=this._group,s=r._map,o=t?s._latLngToNewLayerPoint(this._latlng,t.zoom,t.center):s.latLngToLayerPoint(this._latlng),a=this.getAllChildMarkers(),l=L.Path.SVG&&this.SVG_ANIMATION;for(r._animationStart(),this.setOpacity(1),i=a.length-1;i>=0;i--)e=a[i],e._preSpiderfyLatlng&&(e.setLatLng(e._preSpiderfyLatlng),delete e._preSpiderfyLatlng,e._setPos(o),e.setOpacity(0),l&&(n=e._spiderLeg._path.childNodes[0],n.setAttribute("to",n.getAttribute("from")),n.setAttribute("from",0),n.beginElement(),n=e._spiderLeg._path.childNodes[1],n.setAttribute("from",.5),n.setAttribute("to",0),n.setAttribute("stroke-opacity",0),n.beginElement(),e._spiderLeg._path.setAttribute("stroke-opacity",0)));setTimeout(function(){var t=0;for(i=a.length-1;i>=0;i--)e=a[i],e._spiderLeg&&t++;for(i=a.length-1;i>=0;i--)e=a[i],e._spiderLeg&&(e.setOpacity(1),e.setZIndexOffset(0),t>1&&L.FeatureGroup.prototype.removeLayer.call(r,e),s.removeLayer(e._spiderLeg),delete e._spiderLeg);r._animationEnd()},200)}}:{_animationSpiderfy:function(t,e){var i,n,r,s,o=this._group,a=o._map;for(i=t.length-1;i>=0;i--)s=a.layerPointToLatLng(e[i]),n=t[i],n._preSpiderfyLatlng=n._latlng,n.setLatLng(s),n.setZIndexOffset(1e6),L.FeatureGroup.prototype.addLayer.call(o,n),r=new L.Polyline([this._latlng,s],{weight:1.5,color:"#222"}),a.addLayer(r),n._spiderLeg=r;this.setOpacity(.3),o.fire("spiderfied")},_animationUnspiderfy:function(){this._noanimationUnspiderfy()}}),L.MarkerClusterGroup.include({_spiderfied:null,_spiderfierOnAdd:function(){this._map.on("click",this._unspiderfyWrapper,this),this._map.options.zoomAnimation?this._map.on("zoomstart",this._unspiderfyZoomStart,this):this._map.on("zoomend",this._unspiderfyWrapper,this),L.Path.SVG&&!L.Browser.touch&&this._map._initPathRoot()},_spiderfierOnRemove:function(){this._map.off("click",this._unspiderfyWrapper,this),this._map.off("zoomstart",this._unspiderfyZoomStart,this),this._map.off("zoomanim",this._unspiderfyZoomAnim,this),this._unspiderfy()},_unspiderfyZoomStart:function(){this._map&&this._map.on("zoomanim",this._unspiderfyZoomAnim,this)},_unspiderfyZoomAnim:function(t){L.DomUtil.hasClass(this._map._mapPane,"leaflet-touching")||(this._map.off("zoomanim",this._unspiderfyZoomAnim,this),this._unspiderfy(t))},_unspiderfyWrapper:function(){this._unspiderfy()},_unspiderfy:function(t){this._spiderfied&&this._spiderfied.unspiderfy(t)},_noanimationUnspiderfy:function(){this._spiderfied&&this._spiderfied._noanimationUnspiderfy()},_unspiderfyLayer:function(t){t._spiderLeg&&(L.FeatureGroup.prototype.removeLayer.call(this,t),t.setOpacity(1),t.setZIndexOffset(0),this._map.removeLayer(t._spiderLeg),delete t._spiderLeg)}})})(this); |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/trunk/widget/modules/carto/squelettes/scripts/L.Control.Zoomslider.js |
---|
New file |
0,0 → 1,248 |
/* |
* |
* Copyright (c) 2012, Kartena AB |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* 1. Redistributions of source code must retain the above copyright notice, this |
* list of conditions and the following disclaimer. |
* 2. Redistributions in binary form must reproduce the above copyright notice, |
* this list of conditions and the following disclaimer in the documentation |
* and/or other materials provided with the distribution. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR |
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
*/ |
L.Control.Zoomslider = (function(){ |
var Knob = L.Draggable.extend({ |
initialize: function (element, steps, stepHeight, knobHeight) { |
var sliderHeight = steps * stepHeight; |
L.Draggable.prototype.initialize.call(this, element, element); |
this._element = element; |
this._maxValue = steps - 1; |
// conversion parameters |
// the conversion is just a common linear function. |
this._k = -stepHeight; |
this._m = sliderHeight - (stepHeight + knobHeight) / 2; |
this.on('predrag', function() { |
this._newPos.x = 0; |
this._newPos.y = this._adjust(this._newPos.y); |
}, this); |
}, |
_adjust: function (y) { |
var value = Math.round(this._toValue(y)); |
value = Math.max(0, Math.min(this._maxValue, value)); |
return this._toY(value); |
}, |
// y = k*v + m |
_toY: function (value) { |
return this._k * value + this._m; |
}, |
// v = (y - m) / k |
_toValue: function (y) { |
return (y - this._m) / this._k; |
}, |
setPosition: function (y) { |
L.DomUtil.setPosition(this._element, |
L.point(0, this._adjust(y))); |
}, |
setValue: function (v) { |
this.setPosition(this._toY(v)); |
}, |
getValue: function () { |
return this._toValue(L.DomUtil.getPosition(this._element).y); |
} |
}); |
var Zoomslider = L.Control.extend({ |
options: { |
position: 'topleft', |
// Height of zoom-slider.png in px |
stepHeight: 9, |
// Height of the knob div in px |
knobHeight: 5, |
styleNS: 'leaflet-control-zoomslider' |
}, |
onAdd: function (map) { |
var container = L.DomUtil.create('div', this.options.styleNS + ' leaflet-bar'); |
L.DomEvent.disableClickPropagation(container); |
this._map = map; |
this._zoomInButton = this._createZoomButton( |
'in', 'top', container, this._zoomIn); |
this._sliderElem = L.DomUtil.create( |
'div', |
this.options.styleNS + "-slider leaflet-bar-part", |
container); |
this._zoomOutButton = this._createZoomButton( |
'out', 'bottom', container, this._zoomOut); |
map .on('layeradd layerremove', this._refresh, this) |
.on("zoomend", this._updateSlider, this) |
.on("zoomend", this._updateDisabled, this) |
.whenReady(this._createSlider, this) |
.whenReady(this._createKnob, this) |
.whenReady(this._updateSlider, this) |
.whenReady(this._updateDisabled, this); |
return container; |
}, |
onRemove: function (map) { |
map .off("zoomend", this._updateSlider) |
.off("zoomend", this._updateDisabled) |
.off('layeradd layerremove', this._refresh); |
}, |
_refresh: function () { |
// TODO: listen to zoomlevelschange-event instead in 0.6.x |
this._map |
.removeControl(this) |
.addControl(this); |
}, |
_zoomLevels: function(){ |
return this._map.getMaxZoom() - this._map.getMinZoom() + 1; |
}, |
_createSlider: function () { |
var zoomLevels = this._zoomLevels(); |
// No tilelayer probably |
if(zoomLevels == Infinity){ |
return; |
} |
this._sliderBody = L.DomUtil.create('div', |
this.options.styleNS + '-slider-body', |
this._sliderElem); |
this._sliderBody.style.height |
= (this.options.stepHeight * zoomLevels) + "px"; |
L.DomEvent.on(this._sliderBody, 'click', this._onSliderClick, this); |
}, |
_createKnob: function () { |
var knobElem, |
zoomLevels = this._zoomLevels(); |
// No tilelayer probably |
if(zoomLevels == Infinity) { |
return; |
} |
knobElem = L.DomUtil.create('div', this.options.styleNS + '-slider-knob', |
this._sliderBody); |
L.DomEvent.disableClickPropagation(knobElem); |
this._knob = new Knob(knobElem, |
this._zoomLevels(), |
this.options.stepHeight, |
this.options.knobHeight) |
.on('dragend', this._updateZoom, this); |
this._knob.enable(); |
}, |
_onSliderClick: function (e) { |
var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e); |
var y = L.DomEvent.getMousePosition(first).y |
- L.DomUtil.getViewportOffset(this._sliderBody).y; // Cache this? |
this._knob.setPosition(y); |
this._updateZoom(); |
}, |
_zoomIn: function (e) { |
this._map.zoomIn(e.shiftKey ? 3 : 1); |
}, |
_zoomOut: function (e) { |
this._map.zoomOut(e.shiftKey ? 3 : 1); |
}, |
_createZoomButton: function (zoomDir, end, container, fn) { |
var barPart = 'leaflet-bar-part', |
classDef = this.options.styleNS + '-' + zoomDir |
+ ' ' + barPart |
+ ' ' + barPart + '-' + end, |
title = 'Zoom ' + zoomDir, |
link = L.DomUtil.create('a', classDef, container); |
link.href = '#'; |
link.title = title; |
L.DomEvent |
.on(link, 'click', L.DomEvent.preventDefault) |
.on(link, 'click', fn, this); |
return link; |
}, |
_toZoomLevel: function (sliderValue) { |
return sliderValue + this._map.getMinZoom(); |
}, |
_toSliderValue: function (zoomLevel) { |
return zoomLevel - this._map.getMinZoom(); |
}, |
_updateZoom: function(){ |
this._map.setZoom(this._toZoomLevel(this._knob.getValue())); |
}, |
_updateSlider: function(){ |
if(this._knob){ |
this._knob.setValue(this._toSliderValue(this._map.getZoom())); |
} |
}, |
_updateDisabled: function () { |
var map = this._map, |
className = this.options.styleNS + '-disabled'; |
L.DomUtil.removeClass(this._zoomInButton, className); |
L.DomUtil.removeClass(this._zoomOutButton, className); |
if (map.getZoom() === map.getMinZoom()) { |
L.DomUtil.addClass(this._zoomOutButton, className); |
} |
if (map.getZoom() === map.getMaxZoom()) { |
L.DomUtil.addClass(this._zoomInButton, className); |
} |
} |
}); |
return Zoomslider; |
})(); |
L.Map.mergeOptions({ |
zoomControl: false, |
zoomsliderControl: true |
}); |
L.Map.addInitHook(function () { |
if (this.options.zoomsliderControl) { |
this.zoomsliderControl = new L.Control.Zoomslider(); |
this.addControl(this.zoomsliderControl); |
} |
}); |
L.control.zoomslider = function (options) { |
return new L.Control.Zoomslider(options); |
}; |
/trunk/widget/modules/carto/squelettes/scripts/cluster.js |
---|
New file |
0,0 → 1,117 |
L.Cluster = L.Marker.extend({ |
initialize: function(marker, options) { |
L.Marker.prototype.initialize.call(this, marker, options); |
this._markers = [this]; |
}, |
ajouterMarker: function(marker) { |
this._markers.push(marker); |
}, |
recupererMarkers: function() { |
return this._markers; |
}, |
obtenirNombreMarkers: function() { |
return this._markers.length; |
}, |
supprimerSource: function(sourceSupression) { |
var index = 0; |
while (index < this._markers.length) { |
if (this._markers[index].source == sourceSupression) { |
this._markers.splice(index, 1); |
} else { |
index ++; |
} |
} |
if (this._markers.length == 0) { |
if (this._map != null) { |
this._map.removeLayer(this); |
//this._map.getPanes().markerPane.removeChild(this._icon); |
} |
delete this; |
} |
}, |
supprimer: function() { |
while (this._markers.length > 0) { |
this._markers.splice(0, 1); |
} |
if (this._map != null) { |
this._map.removeLayer(this); |
//this._map.getPanes().markerPane.removeChild(this._icon); |
} |
delete this; |
} |
}); |
L.ClusterGroup = L.FeatureGroup.extend({ |
initialize: function(layers) { |
L.FeatureGroup.prototype.initialize.call(this, layers); |
this._distance = 10; |
this._resolution = 0; |
this._nombreClusters = 0; |
}, |
ajouterPoint: function(layer) { |
if (this._resolution == 0) { |
this._resolution = (2 * Math.PI * 6378137) / (256 * Math.pow(2, this._map.getZoom())); |
} |
var seuilCluster = this._distance * this._resolution; |
if (typeof(layer._latlng) != 'undefined') { |
var indexClusterPlusProche = this._chercherVoisinPlusProche(layer); |
var ajoute = false; |
if (indexClusterPlusProche != null) { |
var distance = this._layers[indexClusterPlusProche].getLatLng().distanceTo(layer.getLatLng()); |
if (distance < seuilCluster) { |
this._layers[indexClusterPlusProche].ajouterMarker(layer); |
ajoute = true; |
} |
} |
if (!ajoute) { |
this._layers[this._nombreClusters] = layer; |
this._nombreClusters ++; |
} |
} |
}, |
_chercherVoisinPlusProche: function(layer) { |
var distance = -1; |
var plusProche = null; |
for (var numeroLayer in this._layers) { |
if (typeof(this._layers[numeroLayer]) != 'undefined') { |
var centre = this._layers[numeroLayer].getLatLng(); |
if (distance == -1 || centre.distanceTo(layer.getLatLng()) < distance) { |
plusProche = numeroLayer; |
distance = centre.distanceTo(layer.getLatLng()); |
} |
} |
} |
return plusProche; |
}, |
afficherClusters: function() { |
for (var numeroLayer in this._layers) { |
if (typeof(this._layers[numeroLayer]) != 'undefined') { |
var layer = this._layers[numeroLayer]; |
if (layer.obtenirNombreMarkers() > 1) { |
layer.setIcon(new L.Icon({ iconUrl : clusterImageUrl, iconSize : [20, 20] })) |
} |
layer.addTo(map); |
} |
} |
}, |
supprimerPoint: function(layer) { |
layer.supprimer(); |
} |
}); |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/trunk/widget/modules/carto/squelettes/scripts/carto.js |
---|
New file |
0,0 → 1,960 |
var map = null, |
optionsCoucheOSM = { |
attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors,' |
+ ' <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>', |
maxZoom: 18 |
}, |
optionsCoucheGoogle = { |
attribution: 'Map data ©'+new Date().getFullYear()+' <a href="http://maps.google.com">Google</a>', |
maxZoom: 18 |
}, |
coucheOSM = new L.TileLayer("http://a.tile.openstreetmap.org/{z}/{x}/{y}.png", |
optionsCoucheOSM), |
coucheRelief = new L.TileLayer("http://c.tile3.opencyclemap.org/landscape/{z}/{x}/{y}.png", |
optionsCoucheOSM), |
coucheSatellite = new L.TileLayer("http://mt1.google.com/vt/lyrs=y@218131653&hl=fr&src=app&x={x}&y={y}&z={z}", |
optionsCoucheGoogle), |
optionsCarte = { |
center : new L.LatLng(46, 2), |
zoom : 6, |
minZoom : 3, |
maxBounds : [[-85.051129, -180], [85.051129, 180]], |
layers : [coucheOSM] |
}, |
zoom = 6, |
legende = null, |
coucheDepartement = null, |
infoBulle = null; |
var coucheSites = null, |
sources = new Object(), |
typeSite = 'maille', |
overlays = []; |
var requeteChargementPoints = null, |
timer = null, |
ancienneRequete = null, |
deplacement = true, |
url = ''; |
$(document).ready(function() { |
initialiserWidget(); |
}); |
$(window).resize(function() { |
dimensionnerCarte(); |
}); |
function initialiserWidget() { |
initialiserCarte(); |
chargerLimitesCommunales(); |
initialiserPanneauControle(); |
initialiserSources(); |
initialiserListeners(); |
chargerLocalisations(); |
} |
function initialiserCarte() { |
dimensionnerCarte(); |
map = L.map('map', optionsCarte); |
coucheSatellite.addTo(map); |
coucheRelief.addTo(map); |
coucheOSM.addTo(map); |
var echelle = new L.Control.Scale({ |
maxWidth : 50, |
metric : true, |
imperial : false, |
updateWhenIdle : true |
}); |
map.addControl(echelle); |
zoom = map.getZoom(); |
} |
function dimensionnerCarte() { |
$('#map').height($(window).height()); |
$('#map').width($(window).width()); |
} |
function initialiserListeners() { |
map.on('moveend', surChangementVueCarte); |
map.on('zoomend', surChangementVueCarte); |
map.on('popupclose', function(e) { |
masquerInfoBulle(); |
programmerRafraichissementCarte(); |
}); |
} |
function initialiserPanneauControle() { |
var baseMaps = { |
"Satellite" : coucheSatellite, |
"Relief" : coucheRelief, |
"Plan" : coucheOSM |
}; |
var overlayMaps = {}; |
for (var index = 0; index < listeSources.length; index ++) { |
sources[listeSources[index]] = estValeurDansTableau(source, listeSources[index]); |
overlayMaps[listeSources[index]] = new L.LayerGroup(); |
} |
L.control.layers(baseMaps, overlayMaps).addTo(map); |
coucheOSM.bringToFront(); |
map.removeLayer(coucheRelief); |
map.removeLayer(coucheOSM); |
// garder par defaut la couche plan google comme selectionnee dans le panel |
var selecteursFonds = $('.leaflet-control-layers-base .leaflet-control-layers-selector'); |
selecteursFonds[0].checked = true; |
selecteursFonds[1].checked = false; |
selecteursFonds[2].checked = false; |
} |
function chargerLimitesCommunales() { |
coucheDepartement = new L.KML(null, {async : true}).addTo(map); |
if (urlsLimitesCommunales != null) { |
coucheDepartement.addKMLFiles(urlsLimitesCommunales); |
} |
} |
function initialiserSources() { |
overlays = $('.leaflet-control-layers-overlays .leaflet-control-layers-selector'); |
$.each(overlays, function (index, input) { |
input.value = listeSources[index]; |
input.id = 'overlay' + (index+1); |
var lien = '<a href="' + liensVersSources[index] + '" target="_blank">' + nomListeSources[index] + '</a>'; |
$('#overlay' + (index+1) + ' ~ span').html(lien); |
input.checked = sources[listeSources[index]]; |
input.onclick = function(event) { |
changerSource(event.target.value); |
} |
}); |
} |
function changerSource(projetClique) { |
var indexProjetClique; |
for (var index = 0; index < overlays.length; index ++) { |
if (overlays[index].value == projetClique) { |
indexProjetClique = index; |
} |
} |
masquerInfoBulle(); |
sources[projetClique] = overlays[indexProjetClique].checked; |
if (sources[projetClique] == true) { |
programmerRafraichissementCarte(projetClique); |
} else { |
if (requeteEnCours()) { |
stopperRequeteAjax(); |
} |
supprimerFeaturesSource(projetClique); |
} |
} |
function supprimerFeaturesSource(source) { |
if (coucheSites != null) { |
coucheSites.eachLayer(function(layer) { |
if (layer.typeSite == 'maille') { |
retirerStationsEtObservations(layer, source); |
} else { |
layer.supprimerSource(source, coucheSites); |
if (layer._map == 'null') { |
couheSites.removeLayer(layer); |
} |
} |
}); |
if (typeSite == 'maille') { |
var nombreMailles = calculerNombreMaillesVisibles(); |
if (nombreMailles == 0) { |
coucheSites.clearLayers(); |
masquerLegende(); |
typeSite = 'point'; |
} |
} |
} |
} |
function retirerStationsEtObservations(maille, sourceRetrait) { |
var sources = maille.properties.source; |
var nombreStations = 0; |
for (var index = 0; index < sources.length; index ++) { |
var source = sources[index]; |
if (source == sourceRetrait) { |
delete maille.properties.stations[source]; |
delete maille.properties.observations[source]; |
} else if (typeof(maille.properties.stations[source]) != 'undefined') { |
nombreStations += parseInt(maille.properties.stations[source]); |
} |
} |
if (nombreStations == 0) { |
coucheSites.removeLayer(maille); |
} else { |
colorerMaille(maille) |
genererInfobulle(maille); |
} |
} |
function calculerNombreMaillesVisibles() { |
var nombreMailles = 0; |
coucheSites.eachLayer(function(layer) { |
if($(layer._path).attr('fill-opacity') != '0') { |
nombreMailles ++; |
} |
}); |
return nombreMailles; |
} |
function estValeurDansTableau(tableau, valeur) { |
var index; |
for (index = 0; index < tableau.length && tableau[index] != valeur; index ++); |
return (tableau.length > 0 && index != tableau.length); |
} |
//************************************ |
// requetes stations |
function surChangementVueCarte() { |
programmerRafraichissementCarte(); |
} |
function programmerRafraichissementCarte(source) { |
$('#tooltip').css('display', 'none'); |
source = (source == null || source == 'null') ? null : source; |
if (timer != null) { |
window.clearTimeout(timer); |
} |
if (requeteChargementPoints != null) { |
stopperRequeteAjax(); |
} |
var nombreSourcesVisibles = 0; |
for (var index = 0; index < overlays.length; index ++) { |
if (overlays[index].checked) { |
nombreSourcesVisibles ++; |
} |
} |
if (source == null) { |
timer = window.setTimeout("chargerLocalisations()", 100); |
} else { |
timer = window.setTimeout("chargerSource('"+source+"')", 100); |
} |
} |
function stopperRequeteAjax() { |
requeteChargementPoints.abort(); |
requeteChargementPoints = null; |
} |
function chargerLocalisations() { |
if (requeteEnCours()) { |
requeteChargementPoints.abort(); |
} |
afficherMessageChargement('stations'); |
if (!(ancienneRequete != null && ancienneRequete[1] == map.getZoom() |
&& map.getBounds().intersects(ancienneRequete[0]))) { |
supprimerFeatures(); |
deplacement = false; |
} |
var bboxRequete = calculerBboxRequete(); |
var parametres = { |
"bbox" : bboxRequete, |
"zoom" : map.getZoom(), |
"source" : recupererSourcesActivees(), |
"num_taxon" : numTaxon, |
"nn" : nn, |
"referentiel" : referentiel, |
"dept" : dept, |
"auteur" : auteur, |
"date_debut" : dateDebut, |
"date_fin" : dateFin, |
"nb_jours" : nbJours |
}; |
if (deplacement == true) { |
parametres.format = typeSite; |
} |
ancienneRequete = [map.getBounds(), map.getZoom()]; |
url = urlBase + "stations?" + convertirEnParametresUrl(parametres); |
fonctionCallback = traiterDonneesStations; |
executerAJAX(); |
} |
function supprimerFeatures() { |
if (coucheSites != null) { |
coucheSites.clearLayers(); |
coucheSites = null; |
} |
} |
function recupererSourcesActivees(sourceAIgnorer) { |
sourceAIgnorer = typeof(sourceAIgnorer) == 'undefined' ? '' : sourceAIgnorer; |
var sourcesActivees = []; |
for (var index = 0; index < overlays.length; index ++) { |
if (overlays[index].checked == true && overlays[index].value != sourceAIgnorer) { |
sourcesActivees.push(overlays[index].value); |
} |
} |
return sourcesActivees.join(','); |
} |
function chargerSource(sourceAjout) { |
if (requeteEnCours()) { |
requeteChargementPoints.abort(); |
} |
afficherMessageChargement('stations'); |
var bboxRequete = determinerCoordonneesBordure(); |
var parametres = { |
"bbox" : bboxRequete, |
"zoom" : map.getZoom(), |
"format" : typeSite, |
"source" : sourceAjout, |
"num_taxon" : numTaxon, |
"nn" : nn, |
"referentiel" : referentiel, |
"dept" : dept, |
"auteur" : auteur, |
"date_debut" : dateDebut, |
"date_fin" : dateFin, |
"nb_jours" : nbJours |
}; |
ancienneRequete = [map.getBounds(), map.getZoom()]; |
url = urlBase + "stations?" + convertirEnParametresUrl(parametres); |
fonctionCallback = traiterRetourChargementSource; |
executerAJAX(); |
} |
function calculerBboxRequete() { |
var bordure = map.getBounds(); |
var bboxRequete = ""; |
if (ancienneRequete != null && ancienneRequete[1] == map.getZoom() |
&& bordure.intersects(ancienneRequete[0])) { |
bboxRequete = calculerIntersectionRectangle(ancienneRequete[0], bordure); |
} else { |
bboxRequete = determinerCoordonneesBordure(); |
} |
return bboxRequete; |
} |
function calculerIntersectionRectangle(rectangle1, rectangle2) { |
var bbox1 = [rectangle2.getSouthWest().lng.toFixed(6), rectangle2.getSouthWest().lat.toFixed(6), |
rectangle2.getNorthEast().lng.toFixed(6), rectangle2.getNorthEast().lat.toFixed(6)]; |
var bbox2 = [rectangle2.getSouthWest().lng.toFixed(6), rectangle2.getSouthWest().lat.toFixed(6), |
rectangle2.getNorthEast().lng.toFixed(6), rectangle2.getNorthEast().lat.toFixed(6)]; |
if (rectangle2.getSouthWest().lng >= rectangle1.getSouthWest().lng |
&& rectangle2.getSouthWest().lng <= rectangle1.getNorthEast().lng) { |
bbox2[0] = bbox1[2] = rectangle1.getNorthEast().lng.toFixed(6); |
if (rectangle2.getSouthWest().lat >= rectangle1.getSouthWest().lat |
&& rectangle2.getSouthWest().lat <= rectangle1.getNorthEast().lat) { |
bbox1[1] = rectangle1.getNorthEast().lat.toFixed(6); |
} else { |
bbox1[3] = rectangle1.getSouthWest().lat.toFixed(6); |
} |
} else { |
bbox2[0] = bbox1[2] = rectangle1.getSouthWest().lng.toFixed(6); |
if (rectangle2.getSouthWest().lat >= rectangle1.getSouthWest().lat |
&& rectangle2.getSouthWest().lat <= rectangle1.getNorthEast().lat) { |
bbox2[1] = rectangle1.getNorthEast().lat.toFixed(6); |
} else { |
bbox2[3] = rectangle1.getSouthWest().lat.toFixed(6); |
} |
} |
return bbox1.join(',')+'|'+bbox2.join(','); |
} |
function determinerCoordonneesBordure() { |
var ouest = map.getBounds().getSouthWest().lng.toFixed(6), |
sud = Math.max(map.getBounds().getSouthWest().lat, -85.051129).toFixed(6), |
est = map.getBounds().getNorthEast().lng.toFixed(6), |
nord = Math.min(map.getBounds().getNorthEast().lat, 85.051129).toFixed(6); |
// appliquer les limites possibles de la projection actuellement utilisee aux coordonnees |
// longitudes ouest et est de la bbox (permettra d'eviter de renvoyer des messages d'erreur) |
if (ouest < -180) { |
ouest += 360; |
} else if (ouest > 180) { |
ouest -= 360; |
} |
if (est < -180) { |
est += 360; |
} else if (est > 180) { |
est -= 360; |
} |
return [ouest, sud, est, nord].join(','); |
} |
function afficherMessageChargement(element) { |
if ($("#zone-chargement").css('display') == 'none') { |
var divTmplElement = 'tpl-chargement-' + element; |
$("#zone-chargement").append($("#" + divTmplElement).text()); |
$("#zone-chargement").css('display', 'block'); |
} |
} |
function masquerMessageChargement() { |
$("#zone-chargement").css('display', 'none'); |
$("#zone-chargement").children().remove(); |
} |
function executerAJAX() { |
if (requeteEnCours()) { |
requeteChargementPoints.abort(); |
} |
requeteChargementPoints = $.getJSON(url).complete(function() { |
fonctionCallback(); |
}); |
} |
function requeteEnCours() { |
return (requeteChargementPoints != null && requeteChargementPoints.readyState != 4); |
} |
function estStatutRequeteOK() { |
return ((requeteChargementPoints.status == 200 || requeteChargementPoints.status == 304) |
|| requeteChargementPoints.status == 0); |
} |
function convertirEnParametresUrl(objet) { |
var parametresUrl = ''; |
for (attribut in objet) { |
if (typeof(objet[attribut]) == 'function' || typeof(objet[attribut]) == 'undefined' || |
objet[attribut] == null || objet[attribut] == '*' || objet[attribut] == 0) |
continue; |
parametresUrl += (parametresUrl == '' ? '' : '&') + attribut + "=" + objet[attribut]; |
} |
return parametresUrl; |
}; |
function traiterDonneesStations() { |
masquerMessageChargement(); |
masquerLegende(); |
if (deplacement == true) { |
supprimerFeaturesHorsBbox(); |
} |
deplacement = true; |
var texte = requeteChargementPoints.responseText; |
if (!estStatutRequeteOK()) { |
alert(texte); |
} else { |
var donneesJSON = eval("(function(){return " + texte + ";})()"); |
if (donneesJSON != null && donneesJSON.features.length > 0) { |
ajouterStationsSurCarte(donneesJSON); |
} |
} |
} |
function traiterRetourChargementSource() { |
masquerMessageChargement(); |
var texte = requeteChargementPoints.responseText; |
if (!estStatutRequeteOK()) { |
alert(texte); |
} else { |
var donneesJSON = eval("(function(){return " + texte + ";})()"); |
if (donneesJSON != null && donneesJSON.features.length > 0) { |
var formatRetourDifferent = donneesJSON.stats.formeDonnees != typeSite; |
ajouterStationsSurCarte(donneesJSON); |
if (formatRetourDifferent) { |
var sourceAIgnorer = donneesJSON.stats.source[0]; |
var sourcesARecharger = recupererSourcesActivees(sourceAIgnorer); |
if (sourcesARecharger.length > 0) { |
rechargerSources(sourcesARecharger); |
} |
} |
} |
} |
} |
function supprimerFeaturesHorsBbox() { |
var bordure = map.getBounds(); |
var layersRestants = 0; |
if (coucheSites != null) { |
coucheSites.eachLayer(function(layer) { |
if (typeof(layer._latlng) != 'undefined') { |
if (bordure.contains(layer.getLatLng())) { |
layersRestants ++; |
} else { |
coucheSites.supprimerPoint(layer); |
} |
} else { |
if (bordure.intersects(layer.getBounds())) { |
layersRestants ++; |
} else { |
coucheSites.removeLayer(layer); |
} |
} |
}); |
} |
if (layersRestants == 0) { |
coucheSites = null; |
} |
} |
function rechargerSources(sourcesARecharger) { |
var listeSourcesASupprimer = sourcesARecharger.split(','); |
for (var index = 0; index < listeSourcesASupprimer.length; index ++) { |
supprimerFeaturesSource(listeSourcesASupprimer[index]); |
} |
chargerSource(sourcesARecharger); |
} |
function ajouterStationsSurCarte(donnees) { |
typeSite = donnees.stats.formeDonnees; |
if (coucheSites == null) { |
coucheSites = (typeSite == 'maille') ? new L.FeatureGroup() : new L.ClusterGroup(); |
map.addLayer(coucheSites); |
} |
for (var index = 0; index < donnees.features.length; index ++) { |
var feature = donnees.features[index]; |
if (typeSite == 'maille') { |
traiterMaille(feature); |
} else { |
ajouterPoint(feature); |
} |
} |
if (donnees.features.length > 0) { |
afficherLegende(); |
} |
if (typeSite == 'maille') { |
genererInfobulleMailles(); |
} else { |
coucheSites.afficherClusters(); |
} |
} |
// ========================================= |
// Gestion des mailles |
function traiterMaille(feature) { |
var coordonnees = []; |
for (var i = 0; i < feature.geometry.coordinates.length; i++) { |
var sommet = new L.LatLng(feature.geometry.coordinates[i][0], feature.geometry.coordinates[i][1]); |
coordonnees.push(sommet); |
} |
var maille = rechercherMailleExistante(coordonnees); |
if (maille) { |
mettreAJourMaille(maille, feature); |
} else { |
maille = ajouterMaille(feature, coordonnees); |
} |
colorerMaille(maille); |
} |
function rechercherMailleExistante(coordonnees) { |
var mailleTrouvee = null; |
coucheSites.eachLayer(function(layer) { |
if ('typeSite' in layer && layer.typeSite == 'maille') { |
if (sontMaillesIdentiques(coordonnees, layer._latlngs)) { |
mailleTrouvee = layer; |
return; |
} |
} |
}); |
return mailleTrouvee; |
} |
function sontMaillesIdentiques(coordonnees1, coordonnees2) { |
return ( |
coordonnees1[0].lat == coordonnees2[0].lat && |
coordonnees1[0].lng == coordonnees2[0].lng && |
coordonnees1[2].lat == coordonnees2[2].lat && |
coordonnees1[2].lng == coordonnees2[2].lng |
); |
} |
function ajouterMaille(feature, coordonnees) { |
var maille = new L.Polygon(coordonnees); |
var optionsMaille = { |
color: '#FFFFFF', |
opacity : 0.7, |
weight: 1, |
fillOpacity : 0.6 |
}; |
maille.setStyle(optionsMaille); |
maille.typeSite = 'maille'; |
maille.properties = feature.properties; |
coucheSites.addLayer(maille); |
return maille; |
} |
function mettreAJourMaille(maille, feature) { |
var sources = feature.properties.source; |
for (var index = 0; index < sources.length; index ++) { |
var source = sources[index]; |
maille.properties.stations[source] = parseInt(feature.properties.stations[source]); |
maille.properties.observations[source] = parseInt(feature.properties.observations[source]); |
maille.properties.source.push(source); |
} |
} |
function colorerMaille(maille) { |
var nombreStations = 0; |
var sources = maille.properties.source; |
for (var index = 0; index < sources.length; index ++) { |
var source = sources[index]; |
if (typeof(maille.properties.stations[source]) != 'undefined') { |
nombreStations += parseInt(maille.properties.stations[source]); |
} |
} |
if (nombreStations > 0) { |
maille.on('click', surClicMaille); |
maille.setStyle({fillColor : genererCouleur(nombreStations), fillOpacity: 0.45, opacity: 0.7}); |
} else { |
maille.setStyle({fillOpacity: 0, opacity: 0}); |
maille.off('click'); |
} |
} |
function genererCouleur(nombrePoints) { |
var couleur = {'bleu': 231, 'vert': 224, 'rouge': 64}, |
seuils = [1, 10, 50 ,100, 500, 1000, 2500], |
pas = 26, |
position = 0; |
for (var index = 1; index < seuils.length-1 && nombrePoints >= seuils[index]; index ++) { |
position ++; |
} |
couleur.vert -= position*pas; |
return 'rgb('+couleur.bleu+','+couleur.vert+','+couleur.rouge+')'; |
} |
function surClicMaille(event) { |
map.fitBounds(event.layer.getBounds()); |
} |
function afficherLegende() { |
if (legende == null) { |
legende = new L.Control({position : 'bottomright'}); |
legende.onAdd = function(map) { |
var contenuHtml = ''; |
if (typeSite == 'maille') { |
contenuHtml = construireContenuHtmlLegendeMailles(); |
} else { |
contenuHtml = construireContenuHtmlLegendePoints(); |
} |
return contenuHtml; |
}; |
map.addControl(legende); |
} |
} |
function construireContenuHtmlLegendeMailles() { |
var div = L.DomUtil.create('div', 'info'); |
div.innerHTML = '<h4>' + titreLegende + '</h4>'; |
var seuils = [1, 10, 50 ,100, 500, 1000, 2500]; |
var labels = []; |
for (var i = 0; i < seuils.length; i ++) { |
div.innerHTML += |
'<div class="legend">'+ |
'<span class="couleur-maille" style="background:' + genererCouleur(seuils[i] + 1) + '">'+ |
'</span>'+seuils[i]+ (i + 1 < seuils.length ? '–' + seuils[i + 1] : '+')+ |
'</div>'; |
} |
return div; |
} |
function masquerLegende() { |
if (legende != null) { |
map.removeControl(legende); |
legende = null; |
} |
} |
function genererInfobulleMailles() { |
coucheSites.eachLayer(function(layer) { |
if (layer.typeSite == 'maille') { |
genererInfobulle(layer); |
} |
}); |
} |
function genererInfobulle(maille) { |
var sources = maille.properties.source; |
var textes = new Array(); |
for (var index = 0; index < sources.length; index ++) { |
var source = sources[index]; |
if (typeof(maille.properties.stations[source]) != 'undefined') { |
textes.push(source+" : "+maille.properties.stations[source]+" stations, " |
+maille.properties.observations[source]+" observations"); |
} |
} |
var contenu = textes.join('<br />'); |
maille.on('mouseover', function() { |
afficherTooltip(contenu, map.latLngToContainerPoint(maille.getBounds().getSouthWest())); |
}); |
maille.on('mouseout', function() { |
$("#tooltip").css('display', 'none'); |
}); |
} |
function afficherTooltip(texte, point) { |
$("#tooltip").html(texte); |
if ($("#tooltip").css('display') == 'none') { |
var x = point.x - 15; |
var y = point.y + (typeSite == 'maille' ? 1 : 10); |
$("#tooltip").css('display', 'block'); |
$("#tooltip").css('left', x + 'px'); |
$("#tooltip").css('top', y + 'px'); |
} |
} |
// ==================================================================== |
// Gestion des points |
function ajouterPoint(feature) { |
var iconePoint = new L.Icon({ iconUrl : pointImageUrl, iconSize : [16, 16] }), |
iconeCommune = new L.Icon({ iconUrl : communeImageUrl, iconSize : [24, 32] }), |
icone = (feature.properties.typeSite == 'STATION') ? iconePoint : iconeCommune, |
point = new L.LatLng(feature.geometry.coordinates[0], feature.geometry.coordinates[1]); |
var marker = new L.Cluster(point, { |
icon : icone, |
titre : feature.properties.nom |
}); |
marker.typeSite = feature.properties.typeSite.toLowerCase(); |
marker.source = feature.properties.source; |
marker.on('click', surClicMarqueur); |
marker.on('mouseover', function() { |
afficherTooltip(marker.options.titre, map.latLngToContainerPoint(marker.getLatLng())); |
}); |
marker.on('mouseout', function() { |
$("#tooltip").css('display', 'none'); |
}); |
coucheSites.ajouterPoint(marker); |
} |
function construireContenuHtmlLegendePoints() { |
var div = L.DomUtil.create('div', 'info'); |
div.innerHTML = |
'<h4>Stations</h4>'+ |
'<div class="legend"><table>'+ |
'<tr>'+ |
'<td class="image-station"><img src="'+communeImageUrl+'" width="24" height="32" /></td>'+ |
'<td class="label-station">Commune</td>'+ |
'</tr>'+ |
'<tr>'+ |
'<td class="image-station"><img src="'+pointImageUrl+'" /></td>'+ |
'<td class="label-station">Lieu précis</td>'+ |
'</tr>'+ |
'<tr>'+ |
'<td class="image-station"><img src="'+clusterImageUrl+'" width="20" height="20" /></td>'+ |
'<td class="label-station">Groupe de stations proches</td>'+ |
'</tr>'+ |
'</table></div>'; |
return div; |
} |
function surClicMarqueur(event) { |
var nombreMarkers = event.target.recupererMarkers().length; |
if (nombreMarkers == 1 || map.getZoom() == map.getMaxZoom()) { |
recupererObservations(event.target); |
} else { |
map.setView(event.target.getLatLng(), Math.min(map.getZoom()+2, map.getMaxZoom())); |
} |
} |
function recupererObservations(cluster) { |
pointClique = cluster; |
var latlng = cluster.getLatLng(); |
afficherMessageChargement('observations'); |
var parametres = { |
"source" : recupererSourcesCluster(cluster), |
"stations" : construireListeStationsCluster(cluster), |
"num_taxon" : numTaxon, |
"nn" : nn, |
"referentiel" : referentiel, |
"auteur" : auteur, |
"date_debut" : dateDebut, |
"date_fin" : dateFin, |
"nb_jours" : nbJours |
}; |
url = urlBase + "observations?" + convertirEnParametresUrl(parametres); |
fonctionCallback = traiterDonneesObservations; |
executerAJAX(); |
} |
function recupererSourcesCluster(cluster) { |
var markers = cluster.recupererMarkers(); |
var sourcesCluster = []; |
for (var index = 0; index < markers.length; index ++) { |
if (sourcesCluster.indexOf(markers[index].source) == -1) { |
sourcesCluster.push(markers[index].source); |
} |
} |
return sourcesCluster.join(','); |
} |
function construireListeStationsCluster(cluster) { |
var markers = cluster.recupererMarkers(); |
var listePoints = []; |
for (var index = 0; index < markers.length; index ++) { |
var latlng = markers[index].getLatLng(); |
listePoints.push(markers[index].source+":"+markers[index].typeSite+":"+latlng.lng+","+latlng.lat); |
} |
return listePoints.join('|'); |
} |
function traiterDonneesObservations() { |
masquerMessageChargement(); |
var texte = requeteChargementPoints.responseText; |
if (!estStatutRequeteOK()) { |
alert(texte); |
} else { |
obsJSON = eval("(function(){return " + texte + ";})()"); |
if (obsJSON != null) { |
viderListeObservations(); |
if (obsJSON.total > 0) { |
doitRafraichirCarte = false; |
map.setView(new L.LatLng(pointClique.getLatLng().lat, pointClique.getLatLng().lng), map.getZoom()); |
afficherInfoBulle(); |
} else if (infoBulle != null) { |
masquerInfoBulle(); |
} |
} |
} |
} |
// ==================================================================== |
// Gestion de l'infobulle |
var obsJSON = null, |
pointClique = null, |
obsStation = [], |
pagineur = {'limite':100, 'start':0, 'total':0, 'stationId':null, 'format':'tableau'}; |
function afficherInfoBulle() { |
var latitude = pointClique.getLatLng().lat; |
var longitude = pointClique.getLatLng().lng; |
infoBulle = new L.Popup({maxWidth : definirLargeurInfoBulle(), maxHeight : 380}); |
infoBulle.setLatLng(new L.LatLng(latitude, longitude)); |
infoBulle.setContent($("#tpl-obs").html()); |
infoBulle.openOn(map); |
remplirContenuPopup(); |
$('#info-bulle').css('width', '99%'); |
$('#observations').css('height', '250px'); |
$('#observations').css('overflow', 'auto'); |
$('.leaflet-popup-scrolled').css('overflow', 'visible'); |
} |
function viderListeObservations() { |
obsStation = new Array(); |
} |
function definirLargeurInfoBulle() { |
var largeurViewPort = $(window).width(); |
var lageurInfoBulle = null; |
if (largeurViewPort < 800) { |
largeurInfoBulle = 400; |
} else if (largeurViewPort >= 800 && largeurViewPort < 1200) { |
largeurInfoBulle = 500; |
} else if (largeurViewPort >= 1200) { |
largeurInfoBulle = 600; |
} |
return largeurInfoBulle; |
} |
function redimensionnerPopup() { |
$('.leaflet-popup-content*').css('width', definirLargeurInfoBulle()); |
$('#info-bulle').css('width', '99%'); |
} |
function remplirContenuPopup() { |
ajouterTableauTriable("#obs-tableau"); |
ajouterTitre(); |
afficherTableau(); |
afficherTexteStationId(); |
} |
function masquerInfoBulle() { |
if (infoBulle != null && map.hasLayer(infoBulle)) { |
map.removeLayer(infoBulle); |
} |
infoBulle = null; |
} |
function ajouterTitre() { |
var texteStationTitre = obsJSON.total + ' observation' + (obsJSON.total > 1 ? 's' : '') |
+ ' sur ' + (pointClique.typeSite=='station' ? 'la station : ' : 'la commune : ') |
+ pointClique.options.title; |
$('#obs-station-titre').text(texteStationTitre); |
} |
function afficherTableau() { |
construireListeObservations(); |
afficherPagination(); |
afficherObservationsDansHTML(); |
} |
function construireListeObservations() { |
if (obsStation.length==0) { |
// premiere execution de la fonction : faire une copie des objets JSON decrivant les observations |
for (var index = 0; index < obsJSON.observations.length; index ++) { |
obsStation.push(obsJSON.observations[index]); |
} |
} |
pagineur.total = obsStation.length; |
} |
function afficherPagination() { |
$(".navigation").pagination(pagineur.total, { |
items_per_page:pagineur.limite, |
callback:afficherObservationsDansHTML, |
next_text:'Suivant', |
prev_text:'Précédent', |
prev_show_always:false, |
num_edge_entries:1, |
num_display_entries:4, |
load_first_page:true |
}); |
} |
function afficherObservationsDansHTML(indexPage) { |
$("#obs-tableau-lignes").empty(); |
if (typeof(indexPage) == 'undefined') { |
indexPage = 0; |
} |
var depart = indexPage * pagineur.limite; |
var obsPage = []; |
for (var index = depart; index < depart + pagineur.limite; index ++) { |
obsPage.push(obsStation[index]); |
} |
$("#tpl-obs-tableau").tmpl(obsPage).appendTo("#obs-tableau-lignes"); |
mettreAJourTableauTriable(); |
} |
function ajouterTableauTriable() { |
$.tablesorter.addParser({ |
id: 'date_cel', |
is: function(s) { |
// doit retourner false si le parseur n'est pas autodétecté |
return /^\s*\d{2}[\/-]\d{2}[\/-]\d{4}\s*$/.test(s); |
}, |
format: function(date) { |
// Transformation date jj/mm/aaaa en aaaa/mm/jj |
date = date.replace(/^\s*(\d{2})[\/-](\d{2})[\/-](\d{4})\s*$/, "$3-$2-$1"); |
// Remplace la date par un nombre de millisecondes pour trier numériquement |
return $.tablesorter.formatFloat(new Date(date).getTime()); |
}, |
type: 'numeric' |
}); |
$("#obs-tableau").tablesorter({ |
headers: { |
1: { |
sorter:'date_cel' |
} |
} |
}); |
} |
function mettreAJourTableauTriable() { |
$("#obs-tableau").trigger('update'); |
} |
function afficherTexteStationId() { |
var latitude = pointClique.getLatLng().lat.toFixed(5); |
var longitude = pointClique.getLatLng().lng.toFixed(5); |
var texteStationId = pointClique.typeSite.toUpperCase() + ':' |
+ latitude + '|' + longitude + ', SOURCE:' + pointClique.source; |
$('#obs-station-id').text(texteStationId); |
} |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/trunk/widget/modules/carto/squelettes/scripts |
---|
New file |
Property changes: |
Added: svn:ignore |
+carto_old.js |
/trunk/widget/modules/carto/squelettes/css/L.Control.Zoomslider.css |
---|
New file |
0,0 → 1,106 |
/** Slider **/ |
.leaflet-control-zoomslider-slider { |
padding-top: 5px ; |
padding-bottom: 5px; |
} |
.leaflet-control-zoomslider-slider-body { |
background-image: url(images/zoom-slider.png); |
background-repeat: repeat-y; |
background-position: center 0px; |
height: 100%; |
cursor: default; |
} |
.leaflet-control-zoomslider-slider-knob { |
width: 13px; |
height:5px; |
background-color: black; |
background-position: center; |
-webkit-border-radius: 15px; |
border-radius: 15px; |
margin-left: 5px; |
/*border: 5px; */ |
position:relative; |
} |
.leaflet-control-zoomslider-slider-body:hover { |
cursor: pointer; |
} |
.leaflet-control-zoomslider-slider-knob:hover { |
cursor: default; |
cursor: -webkit-grab; |
cursor: -moz-grab; |
} |
.leaflet-dragging .leaflet-control-zoomslider, |
.leaflet-dragging .leaflet-control-zoomslider-slider, |
.leaflet-dragging .leaflet-control-zoomslider-slider-body, |
.leaflet-dragging .leaflet-control-zoomslider a, |
.leaflet-dragging .leaflet-control-zoomslider a.leaflet-control-zoomslider-disabled, |
.leaflet-dragging .leaflet-control-zoomslider-slider-knob:hover { |
cursor: move; |
cursor: -webkit-grabbing; |
cursor: -moz-grabbing; |
} |
/** Leaflet Zoom Styles **/ |
.leaflet-container .leaflet-control-zoomslider { |
margin-left: 13px; |
margin-top: 12px; |
} |
.leaflet-control-zoomslider a { |
width: 23px; |
height: 22px; |
text-align: center; |
text-decoration: none; |
color: black; |
display: block; |
} |
.leaflet-control-zoomslider a:hover { |
background-color: #fff; |
color: #777; |
} |
.leaflet-control-zoomslider-in { |
font: bold 19px/24px Arial, Helvetica, sans-serif; |
} |
.leaflet-control-zoomslider-in:after{ |
content:"+" |
} |
.leaflet-control-zoomslider-out { |
font: bold 23px/20px Tahoma, Verdana, sans-serif; |
} |
.leaflet-control-zoomslider-out:after{ |
content:"-" |
} |
.leaflet-control-zoomslider a.leaflet-control-zoomslider-disabled { |
cursor: default; |
color: #bbb; |
} |
/* Touch */ |
.leaflet-touch .leaflet-control-zoomslider-slider-knob { |
width:20px; |
} |
.leaflet-touch .leaflet-control-zoomslider a { |
width: 30px; |
height: 30px; |
} |
.leaflet-touch .leaflet-control-zoomslider-in { |
font-size: 24px; |
line-height: 29px; |
} |
.leaflet-touch .leaflet-control-zoomslider-out { |
font-size: 28px; |
line-height: 24px; |
} |
.leaflet-touch .leaflet-control-zoomslider { |
box-shadow: none; |
} |
.leaflet-touch .leaflet-control-zoomslider { |
border: 4px solid rgba(0,0,0,0.3); |
} |
/trunk/widget/modules/carto/squelettes/css/MarkerCluster.Default.ie.css |
---|
New file |
0,0 → 1,22 |
/* IE 6-8 fallback colors */ |
.marker-cluster-small { |
background-color: rgb(181, 226, 140); |
} |
.marker-cluster-small div { |
background-color: rgb(110, 204, 57); |
} |
.marker-cluster-medium { |
background-color: rgb(241, 211, 87); |
} |
.marker-cluster-medium div { |
background-color: rgb(240, 194, 12); |
} |
.marker-cluster-large { |
background-color: rgb(253, 156, 115); |
} |
.marker-cluster-large div { |
background-color: rgb(241, 128, 23); |
} |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/trunk/widget/modules/carto/squelettes/css/MarkerCluster.Default.css |
---|
New file |
0,0 → 1,38 |
.marker-cluster-small { |
background-color: rgba(181, 226, 140, 0.6); |
} |
.marker-cluster-small div { |
background-color: rgba(110, 204, 57, 0.6); |
} |
.marker-cluster-medium { |
background-color: rgba(241, 211, 87, 0.6); |
} |
.marker-cluster-medium div { |
background-color: rgba(240, 194, 12, 0.6); |
} |
.marker-cluster-large { |
background-color: rgba(253, 156, 115, 0.6); |
} |
.marker-cluster-large div { |
background-color: rgba(241, 128, 23, 0.6); |
} |
.marker-cluster { |
background-clip: padding-box; |
border-radius: 20px; |
} |
.marker-cluster div { |
width: 30px; |
height: 30px; |
margin-left: 5px; |
margin-top: 5px; |
text-align: center; |
border-radius: 15px; |
font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif; |
} |
.marker-cluster span { |
line-height: 30px; |
} |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/trunk/widget/modules/carto/squelettes/css/carto.css |
---|
New file |
0,0 → 1,539 |
@charset "UTF-8"; |
html { |
overflow:hidden; |
} |
body { |
overflow:hidden; |
padding:2px; |
margin:0; |
width:100%; |
height:100%; |
font-family:Arial; |
font-size:12px; |
} |
h1 { |
font-size:1.6em; |
} |
h2 { |
font-size:1.4em; |
} |
a, a:active, a:visited { |
border-bottom:1px dotted #666; |
color:#56B80E; |
text-decoration:none; |
} |
a:active { |
outline:none; |
} |
a:focus { |
outline:thin dotted; |
} |
a:hover { |
color:#56B80E; |
border-bottom:1px dotted #56B80E; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Présentation des listes de définitions */ |
dl { |
width:100%; |
margin:0; |
} |
dt { |
float:left; |
font-weight:bold; |
text-align:top left; |
margin-right:0.3em; |
line-height:0.8em; |
} |
dd { |
width:auto; |
margin:0.5em 0; |
line-height:0.8em; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Tableau : */ |
table { |
border:1px solid gray; |
border-collapse:collapse; |
width:100%; |
} |
table thead, table tfoot, table tbody { |
background-color:Gainsboro; |
border:1px solid gray; |
} |
table tbody { |
background-color:#FFF; |
} |
table th { |
font-family:monospace; |
border:1px dotted gray; |
padding:5px; |
background-color:Gainsboro; |
} |
table td { |
font-family:arial; |
border:1px dotted gray; |
padding:5px; |
text-align:left; |
} |
table caption { |
font-family:sans-serif; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Tableau : tablesorter */ |
th.header { |
background:url(../images/tri.png) no-repeat center right; |
padding-right:20px; |
} |
th.headerSortUp { |
background:url(../images/tri_croissant.png) no-repeat center right #56B80E; |
color:white; |
} |
th.headerSortDown { |
background:url(../images/tri_decroissant.png) no-repeat center right #56B80E; |
color:white; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Générique */ |
.nettoyage{ |
clear:both; |
} |
hr.nettoyage{ |
visibility:hidden; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Carte */ |
#carte { |
padding:0; |
margin:0; |
position:absolute; |
top:35px; |
left:24px; |
right:0; |
bottom:0; |
overflow:auto; |
} |
.bouton { |
background-color:white; |
border:2px solid black; |
cursor:pointer; |
text-align:center; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Message de chargement */ |
#chargement { |
margin:25px; |
text-align:center; |
} |
#chargement img{ |
display:block; |
margin:auto; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Avertissement */ |
#zone-avertissement { |
background-color:#4A4B4C; |
color:#CCC; |
padding:12px; |
text-align:justify; |
line-height:16px; |
} |
#zone-avertissement h1{ |
margin:0; |
} |
#zone-avertissement a { |
border-bottom:1px dotted gainsboro; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Carte titre */ |
#zone-titre { |
padding:0; |
margin:0; |
position:absolute; |
top:20px; |
left:0; |
width:auto; |
height:35px; |
overflow:hidden; |
background-color:#DDDDDD; |
z-index : 3000; |
border-radius: 4px; |
border: 1px solid black; |
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05) inset; |
display: inline-block; |
} |
#zone-info { |
position:absolute; |
top:0; |
right:8px; |
width:48px; |
text-align:right; |
} |
#zone-info img { |
display:inline; |
padding:4px; |
margin:0; |
border:none; |
} |
#carte-titre { |
display:inline-block; |
margin:0; |
padding:0.2em; |
color:black; |
} |
#carte-titre {/*Hack CSS fonctionne seulement dans ie6, 7 & 8 */ |
display:inline !hackCssIe6Et7;/*Hack CSS pour ie6 & ie7 */ |
display /*\**/:inline\9;/*Hack CSS pour ie8 */ |
} |
#logo { |
position:absolute; |
z-index:3000; |
top:20px; |
left:45px; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* message de chargement de donnees */ |
#zone-chargement { |
background-color: white; |
border: 5px solid #D7DBEA; |
display: none; |
height: 70px; |
left: 40%; |
padding: 10px; |
position: fixed; |
text-align: center; |
top: 40%; |
width: 230px; |
z-index: 3000; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Panneau latéral */ |
#panneau-lateral { |
padding:0; |
margin:0; |
position:absolute; |
top:35px; |
left:0; |
bottom:0; |
width:24px; |
overflow:hidden; |
background-color:#4A4B4C; |
border-right:1px solid grey; |
} |
#pl-contenu { |
display:none; |
} |
#pl-entete { |
height:95px; |
} |
#pl-corps { |
position:absolute; |
top:105px; |
bottom:0; |
overflow:auto; |
padding:5px; |
width:290px; |
} |
#pl-ouverture, #pl-fermeture { |
position:absolute; |
top:0; |
height:24px; |
width:24px; |
text-align:center; |
cursor:pointer; |
} |
#pl-ouverture { |
left:0; |
background:url(../images/ouverture.png) no-repeat top left #4A4B4C; |
height:100%; |
} |
#pl-fermeture { |
display:none; |
left:276px; |
background:url(../images/fermeture.png) no-repeat top right #4A4B4C; |
} |
#pl-ouverture span, #pl-fermeture span{ |
display:none; |
} |
/* Panneau latéral : balises */ |
#panneau-lateral h2, #panneau-lateral p { |
color:#CCCCCC;} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Liste des taxons de la carte */ |
#taxons { |
color:#999; |
} |
#taxons .taxon-actif, #taxons .taxon-actif span { |
color:#56B80E; |
} |
#taxons li span { |
border-bottom:1px dotted #666; |
color:#CCC; |
} |
#taxons li span:focus { |
outline:thin dotted; |
} |
#taxons li span:hover { |
color:#56B80E; |
border-bottom:1px dotted #56B80E; |
cursor:pointer; |
} |
.nt { |
display:none; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Pop-up observations */ |
#info-bulle{ |
min-height:500px; |
width:500px; |
} |
#observations { |
clear: both; |
overflow:none; |
margin:-1px 0 0 0; |
border: 1px solid #AAA; |
border-radius:0 0 4px 4px; |
} |
#obs-pieds-page { |
font-size:10px; |
color:#CCC; |
clear:both; |
} |
.ui-tabs { |
padding:0; |
} |
.ui-widget-content { |
border:0; |
} |
.ui-widget-header { |
background:none; |
border:0; |
border-bottom:1px solid #AAA; |
border-radius:0; |
} |
.ui-tabs-selected a { |
border-bottom:1px solid white; |
} |
.ui-tabs-selected a:focus { |
outline:0; |
} |
.ui-tabs .ui-tabs-panel { |
padding:0.2em; |
} |
.ui-tabs .ui-tabs-nav li a { |
padding: 0.5em 0.6em; |
} |
#obs h2 { |
margin:0; |
text-align:center; |
} |
#observations a { |
color:#333; |
border-bottom:1px dotted gainsboro; |
} |
#observations a:hover { |
color:#56B80E; |
border-bottom:1px dotted #56B80E; |
} |
.nom-sci{ |
color:#454341; |
font-weight:bold; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Pop-up observations : liste */ |
.cel-img-principale { |
height:0;/*Pour IE*/ |
} |
.cel-img-principale img{ |
float:right; |
height:75px; |
width:75px; |
padding:1px; |
border:1px solid white; |
} |
#observations .cel-img:hover img{ |
border: 1px dotted #56B80E; |
} |
.cel-img-secondaire, .cel-infos{ |
display: none; |
} |
ol#obs-liste-lignes { |
padding:5px; |
margin:0; |
} |
.champ-nom-sci { |
display:none; |
} |
#obs-liste-lignes li dl {/*Pour IE*/ |
width:350px; |
} |
.obs-conteneur{ |
counter-reset: item; |
} |
.obs-conteneur .nom-sci:before { |
content: counter(item) ". "; |
counter-increment: item; |
display:block; |
float:left; |
} |
.obs-conteneur li { |
display: block; |
margin-bottom:1em; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Diaporama */ |
.cel-legende{ |
text-align:left; |
} |
.cel-legende-vei{ |
float:right; |
} |
.cel-legende p{ |
color: black; |
font-size: 12px; |
line-height: 18px; |
margin: 0; |
} |
.cel-legende a, .cel-legende a:active, .cel-legende a:visited { |
border-bottom:1px dotted gainsboro; |
color:#333; |
text-decoration:none; |
background-image:none; |
} |
.cel-legende a:hover { |
color:#56B80E; |
border-bottom:1px dotted #56B80E; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Plugin Jquery Pagination */ |
.navigation { |
padding:5px; |
float:right; |
display: block; |
} |
.pagination { |
font-size: 80%; |
} |
.pagination a { |
text-decoration: none; |
border: solid 1px #666; |
color: #666; |
background:gainsboro; |
} |
.pagination a:hover { |
color: white; |
background: #56B80E; |
} |
.pagination a, .pagination span { |
display: block; |
float: left; |
padding: 0.3em 0.5em; |
margin-right: 5px; |
margin-bottom: 5px; |
min-width:1em; |
text-align:center; |
} |
.pagination .current { |
background: #4A4B4C; |
color: white; |
border: solid 1px gainsboro; |
} |
.pagination .current.prev, .pagination .current.next{ |
color: #999; |
border-color: #999; |
background: gainsboro; |
} |
/*+-----------------------------------------------------------------------------------------------------------------+*/ |
/* Formulaire de contact */ |
#form-contact input{ |
width:300px; |
} |
#form-contact textarea{ |
width:300px; |
height:200px; |
} |
#form-contact #fc_envoyer{ |
width:50px; |
float:right; |
} |
#form-contact #fc_annuler{ |
width:50px; |
float:left; |
} |
#form-contact label.error { |
color:red; |
font-weight:bold; |
} |
#form-contact .info { |
padding:5px; |
background-color: #4A4B4C; |
border: solid 1px #666; |
color: white; |
white-space: pre-wrap; |
width: 300px; |
} |
/*+------------------------------------------------------------------- |
/* Ajout alex */ |
.info { |
padding:6px 8px; |
font-size:1em; |
background:white; |
width:110px; |
box-shadow:0 0 15px black; |
border-radius:5px; |
line-height:18px; |
} |
.info h4 { |
font-size: 1.2em; |
margin: 0 0 5px; |
color: #555; |
} |
.legend { |
padding :3px; |
color:#999; |
} |
.legend span.couleur-maille { |
width:18px; |
height:18px; |
float:left; |
margin-right:8px; |
opacity: 0.7; |
} |
.legend table { |
border-collapse: separate; |
border: none; |
} |
.legend td { |
border: none; |
} |
.legend td.image-station { |
text-align: center; |
} |
.legend td.label-station { |
text-align: left; |
font-size: 0.9em; |
} |
#tooltip { |
position: absolute; |
z-index: 3000; |
border: none; |
border-radius : 5px; |
background-color: lightblue; |
padding: 5px; |
font-family : sans-serif; |
font-size:1.1em; |
} |
#tooltip h3, #tooltip div { margin: 0; } |
/trunk/widget/modules/carto/squelettes/css/L.Control.Zoomslider.ie.css |
---|
New file |
0,0 → 1,29 |
.leaflet-control-zoomslider a, .leaflet-control-zoomslider-slider { |
background-color: #eee; |
} |
.leaflet-control-zoomslider a:hover { |
background-color: #fff; |
} |
.leaflet-control-zoomslider-slider { |
padding-top: 4px; |
padding-bottom: 4px; |
} |
/* IE6-7 specific hacks */ |
.leaflet-control-zoomslider-slider { |
*width: 23px; |
} |
/* Fix IE6-divs having a too large min height */ |
.leaflet-control-zoomslider-slider-knob { |
*overflow: hidden; |
} |
/* Support for element:after { content: 'text' } */ |
.leaflet-control-zoomslider-in { |
*zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '+'); |
} |
.leaflet-control-zoomslider-out { |
*zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '-'); |
} |
/trunk/widget/modules/carto/squelettes/carto.tpl.html |
---|
New file |
0,0 → 1,192 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
<html xmlns="http://www.w3.org/1999/xhtml"> |
<head> |
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/> |
<meta http-equiv="Content-style-type" content="text/css" /> |
<meta http-equiv="Content-script-type" content="text/javascript" /> |
<meta http-equiv="Content-language" content="fr" /> |
<title>Carte des observations E-flore : Nouvelle version</title> |
<link rel="icon" type="image/png" href="http://resources.tela-botanica.org/tb/img/16x16/favicon.png" /> |
<link rel="shortcut icon" type="image/x-icon" href="http://resources.tela-botanica.org/tb/img/16x16/favicon.ico" /> |
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5/leaflet.css" /> |
<link rel="stylesheet" href="<?=$url_base?>modules/carto/squelettes/css/L.Control.Zoomslider.css" /> |
<link rel="stylesheet" href="<?=$url_base?>modules/carto/squelettes/css/MarkerCluster.Default.css" /> |
<!--[if lte IE 8]> |
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5/leaflet.ie.css" /> |
<link rel="stylesheet" href="<?=$url_base?>modules/carto/squelettes/css/L.Control.Zoomslider.ie.css" /> |
<link rel="stylesheet" href="<?=$url_base?>modules/carto/squelettes/css/MarkerCluster.Default.ie.css" /> |
<![endif]--> |
<link rel="stylesheet" href="http://www.tela-botanica.org/commun/jquery/fancybox/1.3.4/jquery.fancybox-1.3.4.css" type="text/css" media="screen" /> |
<link rel="stylesheet" href="http://www.tela-botanica.org/commun/jquery/jquery-ui/1.8.15/css/smoothness/jquery-ui-1.8.15.custom.css" type="text/css" media="screen" /> |
<link href="<?=$url_base?>modules/carto/squelettes/css/carto.css" rel="stylesheet" type="text/css" media="screen" /> |
<!-- Javascript : bibliothèques --> |
<script src="http://cdn.leafletjs.com/leaflet-0.5/leaflet.js"></script> |
<script type="text/javascript" src="http://www.tela-botanica.org/commun/jquery/1.6.2/jquery-1.6.2.min.js"></script> |
<script type="text/javascript" src="http://www.tela-botanica.org/commun/jquery/tablesorter/2.0.5/jquery.tablesorter.min.js"></script> |
<script type="text/javascript" src="http://www.tela-botanica.org/commun/jquery/jquery-ui/1.8.15/js/jquery-ui-1.8.15.custom.min.js"></script> |
<script type="text/javascript" src="http://www.tela-botanica.org/commun/jquery/pagination/2.2/jquery.pagination.js"></script> |
<script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script> |
<script type="text/javascript"> |
//<![CDATA[ |
var source = '<?= $source ?>'.split(','); |
var logo = '<?=$logo ?>'; |
var titreCarte = '<?= ($titre != null) ? addslashes($titre) : null; ?>'; |
var urlLogo = '<?= ($logo != null) ? "$logo" : null; ?>'; |
var urlSite = '<?= ($url_site != null) ? "$url_site" : null; ?>'; |
var nn = '<?= $nn ?>'; |
var numTaxon = '<?= $num_taxon ?>'; |
var dept = '<?= $departement ?>'; |
var auteur = '<?= $auteur ?>'; |
var referentiel = '<?= $referentiel ?>'; |
var dateDebut = '<?= $date_debut ?>'; |
var dateFin = '<?= $date_fin ?>'; |
var nbJours = '<?=$nb_jours ?>'; |
var urlBase = '<?= $url_serivce_carto ?>/'; |
var urlsLimitesCommunales = <?= $urlLimitesCommunales ?>; |
var communeImageUrl = '<?= $communeImageUrl ?>'; |
var pointImageUrl = '<?= $pointImageUrl ?>'; |
var clusterImageUrl = '<?= $clusterImageUrl ?>'; |
var liensVersSources = '<?= $liensVersSources ?>'.split(','); |
var titreLegende = '<?= $titreLegende ?>'; |
var listeSources = '<?= $listeSources ?>'.split(','); |
var nomListeSources = '<?= $nomListeSources ?>'.split(','); |
const ZOOM_MAXIMUM_MAILLAGE = <?= $zoomMaximumMaillage ?>; |
const SEUIL_MAILLAGE = <?= $seuilMaillage ?>; |
//]]> |
</script> |
<script src="http://maps.google.com/maps/api/js?v=3.5&sensor=true&language=fr®ion=FR" type="text/javascript"></script> |
<script src="<?=$url_base?>modules/carto/squelettes/scripts/L.KML.js" type="text/javascript"></script> |
<script src="<?=$url_base?>modules/carto/squelettes/scripts/carto.js"></script> |
<script src="<?=$url_base?>modules/carto/squelettes/scripts/L.Control.Zoomslider.js" ></script> |
<script src="<?=$url_base?>modules/carto/squelettes/scripts/cluster.js" ></script> |
</head> |
<body> |
<div id="zone-chargement"></div> |
<div id="map"></div> |
<!-- +-------------------------------------------------------------------------------------------+ --> |
<!-- Blocs chargés à la demande : par défaut avec un style display à none --> |
<!-- Squelette du message de chargement des stations et observations --> |
<script id="tpl-chargement-stations" type="text/x-jquery-tmpl"> |
<div id="chargement-stations"> |
<img src="<?=$url_base?>modules/carto/squelettes/images/chargement.gif" alt="Chargement en cours..." /> |
<p>Chargement des stations en cours...</p> |
</div> |
</script> |
<script id="tpl-chargement-observations" type="text/x-jquery-tmpl"> |
<div id="chargement-observations"> |
<img src="<?=$url_base?>modules/carto/squelettes/images/chargement.gif" alt="Chargement en cours..." /> |
<p>Chargement des observations en cours...</p> |
</div> |
</script> |
<?php if($logo != null) : ?> |
<div id="logo"> |
<?php if($url_site != null) : ?> |
<a href="<?= $url_site; ?>" |
title="<?= $url_site; ?>" |
onclick="ouvrirNouvelleFenetre(this, event)"> |
<img height="60px" class="image-logo" src="<?= $logo ?>" alt="logo" /> |
</a> |
<?php else : ?> |
<img class="image-logo" src="<?= $logo ?>" alt="logo" /> |
<?php endif; ?> |
</div> |
<?php endif; ?> |
<?php if($titre !== "0" && $titre != null) : ?> |
<div id="zone-titre" class="element-overlay"> |
<h1 id="carte-titre"> |
<span id="carte-titre-infos"><?= htmlspecialchars($titre); ?></span> |
</h1> |
</div> |
<?php endif; ?> |
<!-- Squelette du contenu d'une info-bulle observation --> |
<script id="tpl-obs" type="text/x-jquery-tmpl"> |
<div id="info-bulle" style="width:{largeur}px;"> |
<div id="obs"> |
<h2 id="obs-station-titre">Station</h2> |
<div class="navigation"> </div> |
<div id="observations"> |
<div id="obs-vue-tableau"> |
<table id="obs-tableau"> |
<thead> |
<tr> |
<th title="Nom scientifique défini par l'utilisateur.">Nom</th> |
<th title="Date de l'observation">Date</th> |
<th title="Lieu d'observation">Lieu</th> |
<th title="Auteur de l'observation">Observateur</th> |
<th title="Nom du projet référent">Projet</th> |
</tr> |
</thead> |
<tbody id="obs-tableau-lignes" class="obs-conteneur"> |
<!-- Insertion des lignes à partir du squelette tpl-obs-tableau --> |
</tbody> |
</table> |
</div> |
</div> |
<div id="obs-pieds-page"> |
<p>Id : <span id="obs-station-id"> </span></p> |
</div> |
</div> |
</div> |
</script> |
<!-- Squelette du contenu du tableau des observation --> |
<script id="tpl-obs-tableau" type="text/x-jquery-tmpl"> |
<tr class="cel-obs-${idObs}"> |
<td> |
<span class="nom-sci"> |
{{if nn != 0}} |
<a href="http://www.tela-botanica.org/nn${nn}" |
target="_blank"> |
${nomSci} |
</a> |
{{else}} |
${nomSci} |
{{/if}} |
</span> |
</td> |
<td class="date">{{if date}}${date}{{else}} {{/if}}</td> |
<td class="lieu">{{if lieu}}${lieu}{{else}} {{/if}}</td> |
<td> |
{{if observateur}} |
{{if observateurId}} |
<a class="contact obs-${idObs} contributeur-${observateurId}" |
href="#form-contact" |
title="Contactez ce contributeur"> |
${observateur} |
</a> |
{{else}} |
${observateur} |
{{/if}} |
{{else}} |
|
{{/if}} |
</td> |
<td><span>${projet}</span></td> |
</tr> |
</script> |
<!-- Squelette de la liste des taxons --> |
<script id="tpl-taxons-liste" type="text/x-jquery-tmpl"> |
<ol id="taxons"> |
{{each(index, taxon) taxons}} |
<li id="taxon-${taxon.nt}"> |
<span class="taxon" title="Numéro taxonomique : ${taxon.nt} - Famille : ${taxon.famille}"> |
${taxon.nom} <span class="nt" title="Numéro taxonomique">${taxon.nt}</span> |
</span> |
</li> |
{{/each}} |
</ol> |
</script> |
<div id="tooltip" style="display:none;"></div> |
</body> |
</html> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/trunk/widget/modules/carto/squelettes |
---|
New file |
Property changes: |
Added: svn:ignore |
+kml |
+ |
+old_carto.tpl.html |
/trunk/widget/modules/carto |
---|
New file |
Property changes: |
Added: svn:ignore |
+config.ini |
/trunk/widget/Widget.php |
---|
New file |
0,0 → 1,161 |
<?php |
// In : utf8 url_encoded (get et post) |
// Out : utf8 |
/** |
* La classe Widget analyser l'url et chage le widget correspondant. |
* Format d'url : |
* /widget/nom_du_widget?parametres1=ma_valeur1¶metre2=ma_valeur2 |
* Les widget sont dans des dossiers en minuscule correspondant au nom de la classe du widget. |
* Exemple : /widget/carto avec la classe Carto.php dans le dossier carto. |
* |
* |
* @author jpm |
* |
*/ |
class Widget { |
/** Les paramètres de configuration extrait du fichier .ini */ |
private static $config; |
/** Le nom du widget demandé. */ |
private $widget = null; |
/** Les chemins où l'autoload doit chercher des classes. */ |
private static $autoload_chemins = array(); |
/** Les paramètres de l'url $_GET nettoyés. */ |
private $parametres = null; |
/** |
* Constructeur. |
* Parse le fichier de configuraion "widget.ini" et parse l'url à la recherche du widget demandé. |
* @param str iniFile Configuration file to use |
*/ |
public function __construct($fichier_ini = 'widget.ini.php') { |
// Chargement de la configuration |
self::$config = parse_ini_file($fichier_ini, TRUE); |
// Paramêtres de config dynamiques |
self::$config['chemins']['baseURLAbsoluDyn'] = 'http://'.$_SERVER['SERVER_NAME'].self::$config['chemins']['baseURL'].'%s'; |
// Gestion de la mémoire maximum allouée aux services |
ini_set('memory_limit', self::$config['parametres']['limiteMemoire']); |
// Réglages de PHP |
setlocale(LC_ALL, self::$config['parametres']['locale']); |
date_default_timezone_set(self::$config['parametres']['fuseauHoraire']); |
// Gestion des erreurs |
error_reporting(self::$config['parametres']['erreurNiveau']); |
if (isset($_SERVER['REQUEST_URI']) && isset($_SERVER['QUERY_STRING'])) { |
$url_morceaux = $this->parserUrl(); |
if (isset($url_morceaux[0])) { |
$this->widget = strlen($url_morceaux[0]) == 0 ? $url_morceaux[1] : $url_morceaux[0]; |
self::$config['chemins']['widgetCourantDossier'] = self::$config['chemins']['widgetsDossier'].strtolower($this->widget).DIRECTORY_SEPARATOR; |
$this->chargerWidgetConfig(); |
} |
// Chargement des chemins pour l'autoload |
$this->chargerCheminAutoload(); |
// Enregistrement de la méthode gérant l'autoload des classes |
spl_autoload_register(array('Widget', 'chargerClasse')); |
// Nettoyage du $_GET (sécurité) |
$this->collecterParametres(); |
} else { |
$e = 'Les widget nécessite les variables serveurs suivantes pour fonctionner : REQUEST_URI et QUERY_STRING.'; |
trigger_error($e, E_USER_ERROR); |
} |
} |
private function parserUrl() { |
if (strlen($_SERVER['QUERY_STRING']) == 0) { |
$len = strlen($_SERVER['REQUEST_URI']); |
} else { |
$len = -(strlen($_SERVER['QUERY_STRING']) + 1); |
} |
$url = substr($_SERVER['REQUEST_URI'], strlen(self::$config['chemins']['baseURL']), $len); |
$url_morceaux = explode('/', $url); |
return $url_morceaux; |
} |
private function collecterParametres() { |
if (isset($_GET) && $_GET != '') { |
$this->nettoyerGet(); |
$this->parametres = $_GET; |
} |
} |
private function nettoyerGet() { |
foreach ($_GET as $cle => $valeur) { |
$verifier = array('NULL', "\n", "\r", "\\", '"', "\x00", "\x1a", ';'); |
$_GET[$cle] = strip_tags(str_replace($verifier, '', $valeur)); |
} |
} |
private function chargerCheminAutoload() { |
$chemins_communs = explode(';', self::$config['chemins']['autoload']); |
$chemins_communs = array_map('trim', $chemins_communs); |
array_unshift($chemins_communs, ''); |
$chemins_widget = array(); |
if (isset(self::$config[$this->widget]['autoload'])) { |
$chemins_widget = explode(';', self::$config[$this->widget]['autoload']); |
foreach ($chemins_widget as $cle => $chemin) { |
$chemins_widget[$cle] = self::$config['chemins']['widgetCourantDossier'].trim($chemin); |
} |
} |
self::$autoload_chemins = array_merge($chemins_communs, $chemins_widget); |
} |
/** |
* La méthode chargerClasse() charge dynamiquement les classes trouvées dans le code. |
* Cette fonction est appelée par php5 quand il trouve une instanciation de classe dans le code. |
* |
*@param string le nom de la classe appelée. |
*@return void le fichier contenant la classe doit être inclu par la fonction. |
*/ |
public static function chargerClasse($classe) { |
if (class_exists($classe)) { |
return null; |
} |
foreach (self::$autoload_chemins as $chemin) { |
$chemin = $chemin.$classe.'.php'; |
if (file_exists($chemin)) { |
require_once $chemin; |
} |
} |
} |
/** |
* Execute le widget. |
*/ |
function executer() { |
if (!is_null($this->widget)) { |
$classe_widget = ucfirst($this->widget); |
$fichier_widget = self::$config['chemins']['widgetCourantDossier'].$classe_widget.'.php'; |
if (file_exists($fichier_widget)) { |
include_once $fichier_widget; |
if (class_exists($classe_widget)) { |
$widget = new $classe_widget(self::$config, $this->parametres); |
$widget->executer(); |
} |
} |
} |
} |
/** |
* Charge le fichier de config spécifique du wiget et fusionne la config avec celle partagés par l'ensemble des widgets. |
*/ |
private function chargerWidgetConfig() { |
$widget_config_ini_fichier = self::$config['chemins']['widgetCourantDossier'].'config.ini'; |
if (file_exists($widget_config_ini_fichier)) { |
$widget_config = parse_ini_file($widget_config_ini_fichier, TRUE); |
self::$config = array_merge(self::$config, $widget_config); |
} |
} |
} |
?> |
/trunk/widget/.htaccess |
---|
New file |
0,0 → 1,13 |
<files *.ini> |
order deny,allow |
deny from all |
</files> |
#AddHandler x-httpd-php5 .php |
AddDefaultCharset UTF-8 |
RewriteEngine On |
# Redirections générale vers le fichier principal de Widget. |
RewriteCond %{REQUEST_FILENAME} !-d |
RewriteCond %{REQUEST_FILENAME} !-f |
RewriteRule ^.*$ index.php/ |
/trunk/widget/bibliotheque/WidgetCommun.php |
---|
New file |
0,0 → 1,431 |
<?php |
abstract class WidgetCommun { |
protected $config = null; |
protected $parametres = null; |
protected $messages = array(); |
protected $debug = array(); |
public function __construct($config, $parametres) { |
$this->config = $config; |
$this->parserFichierIni($config['chemins']['widgetCourantDossier'].'config.ini'); |
$this->parametres = $parametres; |
} |
/** |
* Parse le fichier ini donné en paramètre |
* @param string $fichier_ini nom du fichier ini à parser |
* @return boolean true si le fichier ini a été trouvé. |
*/ |
private function parserFichierIni($fichier_ini) { |
$retour = false; |
if (file_exists($fichier_ini)) { |
$ini = parse_ini_file($fichier_ini, true); |
$this->fusionner($ini); |
$retour = true; |
} |
return $retour; |
} |
/** |
* fusionne un tableau de paramètres avec le tableau de config global |
* @param array $ini le tableau à fusionner |
*/ |
private function fusionner(array $ini) { |
$this->config = array_merge($this->config, $ini); |
} |
protected function traiterNomMethodeExecuter($nom) { |
$methode = 'executer'; |
$methode .= str_replace(' ', '', ucwords(str_replace('-', ' ', strtolower($nom)))); |
return $methode; |
} |
//+----------------------------------------------------------------------------------------------------------------+ |
// GESTION des CLASSES CHARGÉES à la DEMANDE |
protected function getDao() { |
if (! isset($this->dao)) { |
$this->dao = new Dao(); |
} |
return $this->dao; |
} |
//+----------------------------------------------------------------------------------------------------------------+ |
// GESTION DE MÉTHODES COMMUNES ENTRE LES SERVICES |
protected function getUrlImage($id, $format = 'L') { |
$url_tpl = $this->config['chemins']['celImgUrlTpl']; |
$id = sprintf('%09s', $id).$format; |
$url = sprintf($url_tpl, $id); |
return $url; |
} |
protected function encoderMotCle($mot_cle) { |
return md5(mb_strtolower($mot_cle)); |
} |
private function protegerMotsCles($mots_cles, $type) { |
$separateur = ($type == self::TYPE_IMG) ? ',' : ';' ; |
$mots_cles_a_proteger = explode($separateur,rtrim(trim($mots_cles), $separateur)); |
foreach ($mots_cles_a_proteger as $mot) { |
$mots_cles_proteges[] = $this->bdd->quote($mot); |
} |
$mots_cles = implode(',', $mots_cles_proteges); |
return $mots_cles; |
} |
protected function tronquerCourriel($courriel) { |
$courriel = preg_replace('/[^@]+$/i', '...', $courriel); |
return $courriel; |
} |
protected function nettoyerTableau($tableau) { |
foreach ($tableau as $cle => $valeur) { |
if (is_array($valeur)) { |
$valeur = $this->nettoyerTableau($valeur); |
} else { |
$valeur = $this->nettoyerTexte($valeur); |
} |
$tableau[$cle] = $valeur; |
} |
return $tableau; |
} |
protected function nettoyerTexte($txt) { |
$txt = preg_replace('/&(?!([a-z]+|#[0-9]+|#x[0-9][a-f]+);)/i', '&', $txt); |
$txt = preg_replace('/^(?:000null|null)$/i', '', $txt); |
return $txt; |
} |
protected function etreVide($valeur) { |
$vide = false; |
if ($valeur == '' || $valeur == 'null'|| $valeur == '000null' || $valeur == '0') { |
$vide = true; |
} |
return $vide; |
} |
protected function formaterDate($date_heure_mysql, $format = '%A %d %B %Y à %H:%M') { |
$date_formatee = ''; |
if (!$this->etreVide($date_heure_mysql)) { |
$timestamp = $this->convertirDateHeureMysqlEnTimestamp($date_heure_mysql); |
$date_formatee = strftime($format, $timestamp); |
} |
return $date_formatee; |
} |
protected function convertirDateHeureMysqlEnTimestamp($date_heure_mysql){ |
$val = explode(' ', $date_heure_mysql); |
$date = explode('-', $val[0]); |
$heure = explode(':', $val[1]); |
return mktime((int) $heure[0], (int) $heure[1], (int) $heure[2], (int) $date[1], (int) $date[2], (int) $date[0]); |
} |
//+----------------------------------------------------------------------------------------------------------------+ |
// GESTION DE L'IDENTIFICATION et des UTILISATEURS |
protected function getAuthIdentifiant() { |
$id = (isset($_SERVER['PHP_AUTH_USER'])) ? $_SERVER['PHP_AUTH_USER'] : null; |
return $id; |
} |
protected function getAuthMotDePasse() { |
$mdp = (isset($_SERVER['PHP_AUTH_PW'])) ? $_SERVER['PHP_AUTH_PW'] : null; |
return $mdp; |
} |
protected function authentifierAdmin() { |
$message_accueil = "Veuillez vous identifier avec votre compte Tela Botanica."; |
$message_echec = "Accès limité aux administrateurs du CEL.\n". |
"Votre tentative d'identification a échoué.\n". |
"Actualiser la page pour essayer à nouveau si vous êtes bien inscrit comme administrateur."; |
return $this->authentifier($message_accueil, $message_echec, 'Admin'); |
} |
protected function authentifierUtilisateur() { |
$message_accueil = "Veuillez vous identifier avec votre compte Tela Botanica."; |
$message_echec = "Accès limité aux utilisateur du CEL.\n". |
"Inscrivez vous http://www.tela-botanica.org/page:inscription pour le devenir.\n". |
"Votre tentative d'identification a échoué.\n". |
"Actualiser la page pour essayer à nouveau si vous êtes déjà inscrit ou contacter 'accueil@tela-botanica.org'."; |
return $this->authentifier($message_accueil, $message_echec, 'Utilisateur'); |
} |
private function authentifier($message_accueil, $message_echec, $type) { |
$id = $this->getAuthIdentifiant(); |
if (!isset($id)) { |
$this->envoyerAuth($message_accueil, $message_echec); |
} else { |
if ($type == 'Utilisateur' && $this->getAuthMotDePasse() == 'debug') { |
$autorisation = true; |
} else { |
$methodeAutorisation = "etre{$type}Autorise"; |
$autorisation = $this->$methodeAutorisation(); |
} |
if ($autorisation == false) { |
$this->envoyerAuth($message_accueil, $message_echec); |
} |
} |
return true; |
} |
protected function etreUtilisateurAutorise() { |
$identifiant = $this->getAuthIdentifiant(); |
$mdp = md5($this->getAuthMotDePasse()); |
$url = sprintf($this->config['authentification']['serviceUrlTpl'], $identifiant, $mdp); |
$json = $this->getDao()->consulter($url); |
$existe = json_decode($json); |
$autorisation = (isset($existe) && $existe) ? true :false; |
return $autorisation; |
} |
protected function etreAdminAutorise($identifiant) { |
$identifiant = $this->getAuthIdentifiant(); |
$autorisation = ($this->etreUtilisateurAutorise() && $this->etreAdminCel($identifiant)) ? true : false; |
return $autorisation; |
} |
protected function etreAdminCel($courriel) { |
$admins = $this->config['authentification']['administrateurs']; |
$courriels_autorises = explode(',', $admins); |
$autorisation = (in_array($courriel, $courriels_autorises)) ? true : false ; |
return $autorisation; |
} |
/** |
* Prend en paramêtre un tableau de courriels et retourne après avoir intérogé un service we de l'annuaire |
* une tableau avec en clé le courriel et en valeur, un tableau associatif : |
* - nom : le nom de l'utilisateur |
* - prenom : le prénom de l'utilisateur. |
* @param array $courriels un tableau de courriels pour lesquels il faut recherche le prénom et nom. |
*/ |
protected function recupererUtilisateursNomPrenom(Array $courriels) { |
// Récupération des données au format Json |
$service = "utilisateur/prenom-nom-par-courriel/".implode(',', $courriels); |
$url = sprintf($this->config['chemins']['baseURLServicesAnnuaireTpl'], $service); |
$json = $this->getDao()->consulter($url); |
return (array) json_decode($json); |
} |
protected function recupererUtilisateursIdentite(Array $courriels) { |
// Récupération des données au format Json |
$service = "utilisateur/identite-par-courriel/".implode(',', $courriels); |
$url = sprintf($this->config['chemins']['baseURLServicesAnnuaireTpl'], $service); |
$json = $this->getDao()->consulter($url); |
$utilisateurs = json_decode($json); |
foreach ($courriels as $courriel) { |
$info = array('id' => null, 'intitule' => ''); |
if (isset($utilisateurs->$courriel)) { |
$info['intitule'] = $utilisateurs->$courriel->intitule; |
$info['id'] = $utilisateurs->$courriel->id; |
} else { |
$info['intitule'] = $this->tronquerCourriel($courriel); |
} |
$noms[$courriel] = $info; |
} |
return $noms; |
} |
//+----------------------------------------------------------------------------------------------------------------+ |
// GESTION de l'ENVOIE au NAVIGATEUR |
protected function envoyerJsonp($donnees = null, $encodage = 'utf-8') { |
$contenu = $_GET['callback'].'('.json_encode($donnees).');'; |
$this->envoyer($contenu, 'text/html', $encodage); |
} |
protected function envoyer($donnees = null, $mime = 'text/html', $encodage = 'utf-8') { |
// Traitements des messages d'erreurs et données |
if (count($this->messages) != 0) { |
header('HTTP/1.1 500 Internal Server Error'); |
$mime = 'text/html'; |
$encodage = 'utf-8'; |
$sortie = '<html>'. |
'<head><title>Messages</title></head>'. |
'<body><pre>'.implode("\n", $this->messages).'</pre><body>'. |
'</html>'; |
} else { |
$sortie = $donnees; |
if (is_null($donnees)) { |
$sortie = 'OK'; |
} |
} |
// Gestion de l'envoie du déboguage |
$this->envoyerDebogage(); |
// Envoie sur la sortie standard |
$this->envoyerContenu($encodage, $mime, $sortie); |
} |
private function envoyerDebogage() { |
if (!is_array($this->debug)) { |
$this->debug[] = $this->debug; |
} |
if (count($this->debug) != 0) { |
foreach ($this->debug as $cle => $val) { |
if (is_array($val)) { |
$this->debug[$cle] = print_r($val, true); |
} |
} |
header('X-DebugJrest-Data:'.json_encode($this->debug)); |
} |
} |
private function envoyerContenu($encodage, $mime, $contenu) { |
if (!is_null($mime) && !is_null($encodage)) { |
header("Content-Type: $mime; charset=$encodage"); |
} else if (!is_null($mime) && is_null($encodage)) { |
header("Content-Type: $mime"); |
} |
print_r($contenu); |
} |
private function envoyerAuth($message_accueil, $message_echec) { |
header('HTTP/1.0 401 Unauthorized'); |
header('WWW-Authenticate: Basic realm="'.mb_convert_encoding($message_accueil, 'ISO-8859-1', 'UTF-8').'"'); |
header('Content-type: text/plain; charset=UTF-8'); |
print $message_echec; |
exit(0); |
} |
//+----------------------------------------------------------------------------------------------------------------+ |
// GESTION DES SQUELETTES (PHP, TXT...) |
/** |
* Méthode prenant en paramètre un tableau associatif, les clés seront recherchées dans le texte pour être |
* remplacer par la valeur. Dans le texte, les clés devront être entre accolades : {} |
* |
* @param String $txt le texte où chercher les motifs. |
* @param Array $donnees un tableau associatif contenant les motifs à remplacer. |
* |
* @return String le texte avec les motifs remplacer par les valeurs du tableau. |
*/ |
protected static function traiterSqueletteTxt($txt, Array $donnees = array()) { |
$motifs = array(); |
$valeurs = array(); |
foreach ($donnees as $cle => $valeur) { |
if (strpos($cle, '{') === false && strpos($cle, '}') === false) { |
$motifs = '{'.$cle.'}'; |
$valeurs = $valeur; |
} |
} |
$txt = str_replace($motifs, $valeurs, $txt); |
return $txt; |
} |
/** |
* Méthode prenant en paramètre un chemin de fichier squelette et un tableau associatif de données, |
* en extrait les variables, charge le squelette et retourne le résultat des deux combinés. |
* |
* @param String $fichier le chemin du fichier du squelette |
* @param Array $donnees un tableau associatif contenant les variables a injecter dans le squelette. |
* |
* @return boolean false si le squelette n'existe pas, sinon la chaine résultat. |
*/ |
protected static function traiterSquelettePhp($fichier, Array $donnees = array()) { |
$sortie = false; |
if (file_exists($fichier)) { |
// Extraction des variables du tableau de données |
extract($donnees); |
// Démarage de la bufferisation de sortie |
ob_start(); |
// Si les tags courts sont activés |
if ((bool) @ini_get('short_open_tag') === true) { |
// Simple inclusion du squelette |
include $fichier; |
} else { |
// Sinon, remplacement des tags courts par la syntaxe classique avec echo |
$html_et_code_php = self::traiterTagsCourts($fichier); |
// Pour évaluer du php mélangé dans du html il est nécessaire de fermer la balise php ouverte par eval |
$html_et_code_php = '?>'.$html_et_code_php; |
// Interprétation du html et du php dans le buffer |
echo eval($html_et_code_php); |
} |
// Récupèration du contenu du buffer |
$sortie = ob_get_contents(); |
// Suppression du buffer |
@ob_end_clean(); |
} else { |
$msg = "Le fichier du squelette '$fichier' n'existe pas."; |
trigger_error($msg, E_USER_WARNING); |
} |
// Retourne le contenu |
return $sortie; |
} |
/** |
* Fonction chargeant le contenu du squelette et remplaçant les tags court php (<?= ...) par un tag long avec echo. |
* |
* @param String $chemin_squelette le chemin du fichier du squelette |
* |
* @return string le contenu du fichier du squelette php avec les tags courts remplacés. |
*/ |
private static function traiterTagsCourts($chemin_squelette) { |
$contenu = file_get_contents($chemin_squelette); |
// Remplacement de tags courts par un tag long avec echo |
$contenu = str_replace('<?=', '<?php echo ', $contenu); |
// Ajout systématique d'un point virgule avant la fermeture php |
$contenu = preg_replace("/;*\s*\?>/", "; ?>", $contenu); |
return $contenu; |
} |
//+----------------------------------------------------------------------------------------------------------------+ |
// UTILITAIRES |
/** |
* Permet de trier un tableau multi-dimenssionnel en gardant l'ordre des clés. |
* |
* @param Array $array le tableau à trier |
* @param Array $cols tableau indiquant en clé la colonne à trier et en valeur l'ordre avec SORT_ASC ou SORT_DESC |
* @author cagret at gmail dot com |
* @see http://fr.php.net/manual/fr/function.array-multisort.php Post du 21-Jun-2009 12:38 |
*/ |
public static function trierTableauMd($array, $cols) { |
$colarr = array(); |
foreach ($cols as $col => $order) { |
$colarr[$col] = array(); |
foreach ($array as $k => $row) { |
$colarr[$col]['_'.$k] = strtolower(self::supprimerAccents($row[$col])); |
} |
} |
$params = array(); |
foreach ($cols as $col => $order) { |
$params[] =& $colarr[$col]; |
$params = array_merge($params, (array)$order); |
} |
call_user_func_array('array_multisort', $params); |
$ret = array(); |
$keys = array(); |
$first = true; |
foreach ($colarr as $col => $arr) { |
foreach ($arr as $k => $v) { |
if ($first) { |
$keys[$k] = substr($k,1); |
} |
$k = $keys[$k]; |
if (!isset($ret[$k])) { |
$ret[$k] = $array[$k]; |
} |
$ret[$k][$col] = $array[$k][$col]; |
} |
$first = false; |
} |
return $ret; |
} |
private static 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; |
} |
} |
?> |
/trunk/widget/bibliotheque/Dao.php |
---|
New file |
0,0 → 1,157 |
<?php |
// declare(encoding='UTF-8'); |
/** |
* Classe modèle spécifique à l'application, donc d'accés au données, elle ne devrait pas être appelée de l'extérieur. |
* |
* @category php5 |
* @package Widget |
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org> |
* @copyright 2010 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL |
* @version SVN: $Id$ |
*/ |
class Dao { |
const HTTP_URL_REQUETE_SEPARATEUR = '&'; |
const HTTP_URL_REQUETE_CLE_VALEUR_SEPARATEUR = '='; |
private $http_methodes = array('GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS', 'CONNECT', 'TRACE'); |
protected $parametres = null; |
private $url = null; |
private $reponse_entetes = null; |
//+----------------------------------------------------------------------------------------------------------------+ |
// ACCESSEURS |
public function getReponseEntetes($cle) { |
return $this->reponse_entetes; |
} |
public function getParametre($cle) { |
$valeur = (isset($this->parametres[$cle])) ? $this->parametres[$cle] : null; |
return $valeur; |
} |
public function ajouterParametre($cle, $valeur) { |
$this->parametres[$cle] = $valeur; |
} |
public function supprimerParametre($cle) { |
unset($this->parametres[$cle]); |
} |
public function nettoyerParametres() { |
$this->parametres = null; |
} |
//+----------------------------------------------------------------------------------------------------------------+ |
// MÉTHODES |
public function consulter($url) { |
$retour = $this->envoyerRequete($url, 'GET'); |
return $retour; |
} |
public function ajouter($url, Array $donnees) { |
$retour = $this->envoyerRequete($url, 'PUT', $donnees); |
return $retour; |
} |
public function modifier($url, Array $donnees) { |
$retour = $this->envoyerRequete($url, 'POST', $donnees); |
return $retour; |
} |
public function supprimer($url) { |
$retour = $this->envoyerRequete($url, 'DELETE'); |
return $retour; |
} |
public function envoyerRequete($url, $mode, Array $donnees = array()) { |
$this->url = $url; |
$contenu = false; |
if (! in_array($mode, $this->http_methodes)) { |
$e = "Le mode de requête '$mode' n'est pas accepté!"; |
trigger_error($e, E_USER_WARNING); |
} else { |
if ($mode == 'GET') { |
$this->traiterUrlParametres(); |
} |
$contexte = stream_context_create(array( |
'http' => array( |
'method' => $mode, |
'header' => "Content-type: application/x-www-form-urlencoded\r\n", |
'content' => http_build_query($donnees, null, self::HTTP_URL_REQUETE_SEPARATEUR)))); |
$flux = @fopen($this->url, 'r', false, $contexte); |
if (!$flux) { |
$this->reponse_entetes = $http_response_header; |
$e = "L'ouverture de l'url '{$this->url}' par la méthode HTTP '$mode' a échoué!"; |
trigger_error($e, E_USER_WARNING); |
} else { |
// Informations sur les en-têtes et métadonnées du flux |
$this->reponse_entetes = stream_get_meta_data($flux); |
// Contenu actuel de $url |
$contenu = stream_get_contents($flux); |
fclose($flux); |
} |
$this->traiterEntete(); |
} |
$this->reinitialiser(); |
return $contenu; |
} |
private function traiterUrlParametres() { |
$parametres = array(); |
if (count($this->parametres) > 0) { |
foreach ($this->parametres as $cle => $valeur) { |
$cle = rawurlencode($cle); |
$valeur = rawurlencode($valeur); |
$parametres[] = $cle.self::HTTP_URL_REQUETE_CLE_VALEUR_SEPARATEUR.$valeur; |
} |
$url_parametres = implode(self::HTTP_URL_REQUETE_SEPARATEUR, $parametres); |
$this->url = $this->url.'?'.$url_parametres; |
} |
} |
private function traiterEntete() { |
$infos = $this->analyserEntete(); |
$this->traiterEnteteDebogage($infos); |
} |
private function analyserEntete() { |
$entetes = $this->reponse_entetes; |
$infos = array('date' => null, 'uri' => $this->url, 'debogages' => null); |
if (isset($entetes['wrapper_data'])) { |
$entetes = $entetes['wrapper_data']; |
} |
foreach ($entetes as $entete) { |
if (preg_match('/^X_REST_DEBOGAGE_MESSAGES: (.+)$/', $entete, $match)) { |
$infos['debogages'] = json_decode($match[1]); |
} |
if (preg_match('/^Date: .+ ([012][0-9]:[012345][0-9]:[012345][0-9]) .*$/', $entete, $match)) { |
$infos['date'] = $match[1]; |
} |
} |
return $infos; |
} |
private function traiterEnteteDebogage($entetes_analyses) { |
if (isset($entetes['debogages'])) { |
$date = $entetes['date']; |
$uri = $entetes['uri']; |
$debogages = $entetes['debogages']; |
foreach ($debogages as $debogage) { |
$e = "DEBOGAGE : $date - $uri :\n$debogage"; |
trigger_error($e, E_USER_NOTICE); |
} |
} |
} |
private function reinitialiser() { |
$this->nettoyerParametres(); |
} |
} |
?> |
/trunk/widget/index.php |
---|
New file |
0,0 → 1,5 |
<?php |
require 'Widget.php'; |
$widget = new Widget(); |
$widget->executer(); |
?> |
/trunk/widget/widget.ini.defaut.php |
---|
New file |
0,0 → 1,49 |
;<?/* |
[parametres] |
;Memoire maxi pour les services : 128Mo = 134217728 ; 256Mo = 268435456 ; 512Mo = 536870912 ; 1Go = 1073741824 |
limiteMemoire = "512M" |
; Niveau d'erreur PHP |
erreurNiveau = 30719 ; E_ALL = 30719 |
; Séparateur d'url en entrée |
argSeparatorInput = "&" |
; Indication de la locale (setLocale(LC_ALL, ?)) pour les classes appelées par Widget.php |
locale = "fr_FR.UTF-8" |
; Indication du fuseau horraire par défaut date_default_timezone_set(?)pour les classes appelées par Widget.php |
fuseauHoraire = "Europe/Paris" |
[chemins] |
; Chemins à utiliser dans la méthode autoload des widgets |
autoload = "bibliotheque/" |
; Dossier contenant les widgets |
widgetsDossier = "modules/" |
; Dossier contenant le widget demandé construit dynamiquement dans le fichier Widget.php |
widgetCourantDossier = "" |
; Dossier contenant les fichiers des bibliothèques tierces |
bibliothequeDossier = "bibliotheque/" |
; Base de l'url servant à appeler les widgets |
baseURL = "/moissonnage/widget/" |
; URL de base absolue des Widgets du CEL construit dynamiquement dans le fichier WidgetCommun.php |
baseURLAbsoluDyn = "" |
; URL des services web du CEL sous forme de template à utiliser avec sprintf |
baseURLServicesCelTpl = "http://www.tela-botanica.org/service:cel:%s" |
; URL des services web du CEL sous forme de template à utiliser avec sprintf |
baseURLServicesAnnuaireTpl = "http://www.tela-botanica.org/service:annuaire:%s" |
; Squelette d'Url permettant d'afficher une image du CEL (remplace %s par l'id de l'image sans underscore) |
celImgUrlTpl = "http://www.tela-botanica.org/appli:cel-img:%s.jpg" |
; Squelette d'URL pour les services web d'eFlore. |
baseURLServicesEfloreTpl = "http://www.tela-botanica.org/service:eflore:%s/%s/%s" |
; Squelette d'URL pour les services web a tester en local. |
baseURLServicesTpl = "http://localhost/moissonnage/services/0.1%s" |
; Dossier de stockage temporaire des images (ATTENTION : mettre le slash à la fin) |
imagesTempDossier = "/home/telabotap/www/eflore/cel/cache/images/" |
; Squelette d'URL pour les images temporaires sotckées sur le serveur |
imagesTempUrlTpl = "http://www.tela-botanica.org/eflore/cel/cache/images/%s" |
; Url du service fournissant des infos sur les noms à partir d'un num tax |
infosTaxonUrl = "http://www.tela-botanica.org/service:eflore:0.1/bdtfx/noms/%s" |
; Url du service wiki fournissant les pages d'aide |
aideWikiniUrl = 'http://www.tela-botanica.org/wikini/eflore/api/rest/0.5/pages/{page}?txt.format=text/html'; |
[authentification] |
serviceUrlTpl = "http://www.tela-botanica.org/service:annuaire:TestLoginMdp/%s/%s" |
administrateurs = aurelien@tela-botanica.org,david.delon@clapas.net,jpm@tela-botanica.org,marie@tela-botanica.org |
;*/?> |
/trunk/widget |
---|
New file |
Property changes: |
Added: svn:ignore |
+widget.ini.php |
+ |
+.htaccess |
/trunk/scripts/modules/tuilage/tuilage.ini |
---|
New file |
0,0 → 1,14 |
[carte] |
carte.limite_ouest = -180 |
carte.limite_est = 180 |
carte.limite_sud = -85.051129 |
carte.limite_nord = 85.051129 |
rayon_terre = 6378137 |
zoom_minimal = 3 |
zoom_maximal = 13 |
taille_mailles_px = 32 |
[bdd] |
eflore_table_mailles = "mailles_index" |
eflore_champs_table = "zoom,axe,position,debut,fin" |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/trunk/scripts/modules/tuilage/Tuilage.php |
---|
New file |
0,0 → 1,163 |
<?php |
/** |
* Exemple lancement: |
* /opt/lampp/bin/php -d memory_limit=3500M ~/web/moissonnage/scripts/cli.php tuilage -a genererMaillage |
* |
* @author alex |
* |
*/ |
class Tuilage extends Script { |
private $bdd = null; |
private $resolution = 0; |
private $resolutionInitiale = 0; |
private $origine = 0; |
private $longueurMaille; |
public function executer() { |
try { |
$this->initialiserScript(); |
$cmd = $this->getParametre('a'); |
switch ($cmd) { |
case 'genererMaillage' : |
$this->genererTuilage(); |
break; |
default : |
throw new Exception("Erreur : la commande '{$cmd}' n'existe pas!"); |
} |
} catch(Exception $e) { |
$this->traiterErreur($e->getMessage()); |
} |
} |
private function initialiserScript() { |
$fichierIni = $this->getScriptChemin().'tuilage.ini'; |
if (file_exists($fichierIni)) { |
Config::charger($fichierIni); |
} else { |
$m = "Veuillez configurer le projet en créant le fichier '{$this->projetNom}.ini' ". |
"dans le dossier du module de script du projet à partir du fichier '{$this->projetNom}.defaut.ini'."; |
throw new Exception($m); |
} |
$this->longueurMaille = Config::get('taille_mailles_px'); |
$this->resolutionInitiale = 2 * M_PI * Config::get('rayon_terre') / 256; |
$this->origine = 2 * M_PI * Config::get('rayon_terre') / 2.0; |
} |
private function genererTuilage() { |
if (!$this->estTableCreee()) { |
$this->creerStructureTable(); |
print("Table créée"); |
} |
$niveauxZoom = range(Config::get('zoom_minimal'), Config::get('zoom_maximal'), 1); |
foreach ($niveauxZoom as $zoom) { |
print("Génération des mailles au niveau de zoom {$zoom}...\n"); |
$this->resolution = $this->resolutionInitiale / pow(2, $zoom); |
$coordonneesLng = $this->calculerCoordonneesLimitesTuiles($zoom, 'lng'); |
$coordonneesLat = $this->calculerCoordonneesLimitesTuiles($zoom, 'lat'); |
print("mailles calculées\n"); |
$this->ajouterMaillesDansBdd($zoom, $coordonneesLng, $coordonneesLat); |
} |
} |
private function estTableCreee() { |
print("test table"); |
$tables = $this->getBdd()->recupererTous("SHOW TABLES FROM ".Config::get('bdd_nom')); |
$table = Config::get('eflore_table_mailles'); |
for ($index = 0; $index < count($tables) && $tables[$index]['Tables_in_tb_eflore_test'] != $table; $index ++); |
return $index < count($tables); |
} |
private function creerStructureTable() { |
$table = Config::get('eflore_table_mailles'); |
print("Table {$table} non trouvée dans la base de données, création de sa structure...\n"); |
$requete = |
"CREATE TABLE {$table} (". |
"zoom TINYINT UNSIGNED NOT NULL,". |
"axe ENUM('lat','lng') NOT NULL,". |
"position SMALLINT UNSIGNED NOT NULL,". |
"debut DECIMAL(9,6) NOT NULL,". |
"fin DECIMAL(9,6) NOT NULL,". |
"PRIMARY KEY (zoom, axe, position)". |
") ENGINE=MyISAM, CHARACTER SET utf8"; |
$this->getBdd()->requeter($requete); |
$requete = "ALTER TABLE {$table} ADD INDEX (debut), ADD INDEX(fin)"; |
$this->getBdd()->requeter($requete); |
} |
private function calculerCoordonneesLimitesTuiles($zoom, $axe) { |
$variableConfigLimite = $axe == 'lng' ? 'carte.limite_est' : 'carte.limite_nord'; |
$limiteCalcul = Config::get($variableConfigLimite); |
$nombrePixels = pow(2, $zoom+8); |
$tailleTableau = $nombrePixels / $this->longueurMaille; |
$valeurs = array(); |
for ($index = 0; $index <= $tailleTableau; $index ++) { |
$valeur = $this->convertirPixelEnLatLng($index * $this->longueurMaille, $axe); |
$valeurs[] = $this->convertirFloatToString($valeur); |
} |
return $valeurs; |
} |
private function convertirPixelEnLatLng($pixel, $axe) { |
$coord_metrique = $pixel * $this->resolution - $this->origine; |
$coord_lnglat = ($coord_metrique / $this->origine) * 180.0; |
if ($axe == 'lat') { |
$coord_lnglat = 180 / M_PI * (2 * atan(exp($coord_lnglat * M_PI / 180.0)) - M_PI / 2.0); |
} |
return $coord_lnglat; |
} |
private function ajouterMaillesDansBdd($zoom, $coordonneesLng, $coordonneesLat) { |
$table = Config::get('eflore_table_mailles'); |
$nomsChamps = Config::get('eflore_champs_table'); |
$this->getBdd()->requeter("DELETE FROM {$table} WHERE zoom=$zoom"); |
$insertions = array(); |
$j = 10000; |
if (count($coordonneesLng) > $j) { |
for ($i=0; $i < count($coordonneesLng); $i=$i+$j) { |
$insertions = array();print($i." ".$j." "); |
if ($i+$j > count($coordonneesLng)) { |
$k =count($coordonneesLng) - 1; |
} else { |
$k = $i+$j; |
} print_r($k."\n"); |
for ($index = $i; $index < $k; $index ++) { |
$insertions[] = "({$zoom},'lng',{$index},".$coordonneesLng[$index].",".$coordonneesLng[$index+1].")"; |
} |
for ($index = $i; $index < $k; $index ++) { |
$insertions[] = "({$zoom},'lat',{$index},".$coordonneesLat[$index].",".$coordonneesLat[$index+1].")"; |
} |
$requete = "INSERT INTO {$table}({$nomsChamps}) VALUES ".implode(',', $insertions); |
$this->getBdd()->requeter($requete); |
} |
} else { |
for ($index = 0; $index < count($coordonneesLng)-1; $index ++) { |
$insertions[] = "({$zoom},'lng',{$index},".$coordonneesLng[$index].",".$coordonneesLng[$index+1].")"; |
} |
for ($index = 0; $index < count($coordonneesLat)-1; $index ++) { |
$insertions[] = "({$zoom},'lat',{$index},".$coordonneesLat[$index].",".$coordonneesLat[$index+1].")"; |
} |
$requete = "INSERT INTO {$table}({$nomsChamps}) VALUES ".implode(',', $insertions); |
$this->getBdd()->requeter($requete); |
} |
} |
private function getBdd() { |
if (is_null($this->bdd)) { |
$this->bdd = new Bdd(); |
} |
return $this->bdd; |
} |
private function convertirFloatToString($float) { |
return str_replace(',', '.', strval($float)); |
} |
} |
?> |
/trunk/scripts/modules/maillage_projet/sources/baznat.ini |
---|
New file |
0,0 → 1,5 |
[champs] |
tbl.champ_longitude = "longitude" |
tbl.champ_latitude = "latitude" |
tbl.champ_id = "guid" |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/trunk/scripts/modules/maillage_projet/sources/sophy.ini |
---|
New file |
0,0 → 1,5 |
[champs] |
tbl.champ_longitude = "lieu_station_longitude" |
tbl.champ_latitude = "lieu_station_latitude" |
tbl.champ_id = "guid" |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/trunk/scripts/modules/maillage_projet/MaillageProjet.php |
---|
New file |
0,0 → 1,195 |
<?php |
/** |
* Exemple lancement: |
* /opt/lampp/bin/php -d memory_limit=3500M ~/web/moissonnage/scripts/cli.php maillage_projet |
* -a source=nom_source |
* |
* @author alex |
* |
*/ |
class MaillageProjet extends Script { |
private $nomProjet = 'maillage_projet'; |
private $nomSource = ''; |
private $bdd = null; |
private $tableRequetage = ''; |
private $mailles = array(); |
private $points = array(); |
public function executer() { |
try { |
$this->initialiserScript(); |
$cmd = $this->getParametre('a'); |
$parametre = explode('=', $cmd); |
if (count($parametre) != 2 && $parametre[0] != 'source') { |
throw new Exception("Parametre passé incorrect : attendu source=nom_de_la_source\n"); |
} else { |
if (!$this->estSourceDisponible($parametre[1])) { |
$sourcesDispo = Config::get('sources_disponibles'); |
$message = |
"Erreur lors de l'éxécution du script : la soruce demandée n'est pas disponible.\n". |
"Les sources dont le maillage est réalisable sont les suivantes : {$sourcesDispo}.\n"; |
throw new Exception($message); |
} else { |
$this->nomSource = $parametre[1]; |
$this->chargerConfigurationSource($parametre[1]); |
$this->tableRequetage = $parametre[1].Config::get('suffixe_table_interrogation'); |
$this->genererMaillage(); |
} |
} |
} catch(Exception $e) { |
$this->traiterErreur($e->getMessage()); |
} |
} |
private function initialiserScript() { |
$fichierIni = $this->getScriptChemin().'maillage_projet.ini'; |
if (file_exists($fichierIni)) { |
Config::charger($fichierIni); |
} else { |
$m = "Veuillez configurer le projet en créant le fichier '{$this->nomProjet}.ini' ". |
"dans le dossier du module de script du projet à partir du fichier '{$this->nomProjet}.defaut.ini'."; |
throw new Exception($m); |
} |
} |
private function estSourceDisponible($nomSource) { |
$sourcesDispo = explode(',', Config::get('sources_disponibles')); |
return (in_array($nomSource, $sourcesDispo)); |
} |
private function chargerConfigurationSource($nomSource) { |
$fichierIni = $this->getScriptChemin()."sources".DIRECTORY_SEPARATOR."{$nomSource}.ini"; |
if (file_exists($fichierIni)) { |
Config::charger($fichierIni); |
} else { |
$m = "Veuillez configurer les champs specifiques à la source en créant le fichier ". |
"'{$nomSource}.ini' dans le dossier sources de script du projet {$this->nomProjet}."; |
throw new Exception($m); |
} |
} |
private function genererMaillage() { |
if (!$this->estTableCreee()) { |
$this->creerStructureTable(); |
} |
$zoomMinimal = Config::get('zoom_minimal'); |
$niveauxZoom = range($zoomMinimal, Config::get('zoom_maximal'), 1); |
foreach ($niveauxZoom as $zoom) { |
print("Génération des mailles au niveau de zoom {$zoom}...\n"); |
if ($zoom == $zoomMinimal) { |
$this->initialiserMailles(); |
$this->genererMaillesPourZoomMinimal(); |
} else { |
$this->mailles->redecouperMailles(); |
$this->ajouterMaillesDansBdd(); |
} |
} |
} |
private function estTableCreee() { |
$tables = $this->getBdd()->recupererTous("SHOW TABLES FROM ".Config::get('bdd_nom')); |
$tableInsertion = 'mailles_'.$this->nomSource; |
for ($index = 0; $index < count($tables) && $tables[$index]['Tables_in_tb_eflore'] != $tableInsertion; |
$index ++); |
return $index < count($tables); |
} |
private function creerStructureTable() { |
$tableInsertion = 'mailles_'.$this->nomSource; |
print("Table {$tableInsertion} non trouvée dans la base de données, création de sa structure...\n"); |
$requete = |
"CREATE TABLE {$tableInsertion} (". |
"code_maille VARCHAR(25) NOT NULL PRIMARY KEY,". |
"zoom TINYINT UNSIGNED NOT NULL,". |
"position_latitude SMALLINT UNSIGNED NOT NULL,". |
"position_longitude SMALLINT UNSIGNED NOT NULL,". |
"limite_sud DECIMAL(9,6) NOT NULL,". |
"limite_est DECIMAL(9,6) NOT NULL,". |
"limite_nord DECIMAL(9,6) NOT NULL,". |
"limite_ouest DECIMAL(9,6) NOT NULL,". |
"nombre_sites MEDIUMINT UNSIGNED NOT NULL,". |
"nombre_observations MEDIUMINT UNSIGNED NOT NULL". |
") ENGINE=MyISAM, CHARACTER SET utf8"; |
$this->getBdd()->requeter($requete); |
$requete = "ALTER TABLE {$tableInsertion} ADD INDEX bbox(zoom, limite_sud, ". |
"limite_nord, limite_ouest, limite_est)"; |
$this->getBdd()->requeter($requete); |
} |
private function initialiserMailles() { |
$limitesEspaceMaillage = $this->recupererExtremesCoordonnees(); |
$this->recupererIndexMailles($limitesEspaceMaillage, Config::get('zoom_minimal')); |
} |
private function recupererExtremesCoordonnees() { |
$champLongitude = Config::get('tbl.champ_longitude'); |
$champLatitude = Config::get('tbl.champ_latitude'); |
$requete = "SELECT Min({$champLongitude}) AS lng_min, Max({$champLongitude}) AS lng_max, ". |
"Min({$champLatitude}) AS lat_min, Max({$champLatitude}) AS lat_max FROM {$this->tableRequetage}"; |
$limites = $this->getBdd()->recuperer($requete); |
return $limites; |
} |
private function getBdd() { |
if (is_null($this->bdd)) { |
$this->bdd = new Bdd(); |
} |
return $this->bdd; |
} |
private function recupererIndexMailles($limites, $zoom) { |
$bbox = array( |
'sud' => $limites['lat_min'], |
'ouest' => $limites['lng_min'], |
'est' => $limites['lng_max'], |
'nord' => $limites['lat_max'] |
); |
$this->mailles = new Maillage($bbox, $zoom); |
$this->mailles->genererMaillesVides(); |
} |
private function genererMaillesPourZoomMinimal() { |
$this->points = $this->recupererPoints(); |
$this->mailles->ajouterPoints($this->points); |
$this->ajouterMaillesDansBdd(); |
} |
private function recupererPoints() { |
print("Récupération des points dans la base de données...\n"); |
$champLongitude = Config::get('tbl.champ_longitude'); |
$champLatitude = Config::get('tbl.champ_latitude'); |
$id = Config::get('tbl.champ_id'); |
$requete = "SELECT COUNT({$id}) AS observations, {$champLatitude} AS latitude, {$champLongitude} ". |
"AS longitude FROM {$this->tableRequetage} GROUP BY {$champLongitude},{$champLatitude}"; |
$points = $this->getBdd()->recupererTous($requete); |
return $points; |
print("Points chargés\n"); |
} |
private function ajouterMaillesDansBdd() { |
$aInserer = $this->mailles->formaterPourInsertionBdd(); |
$champsTable = Config::get('champs_table_mailles'); |
$tableInsertion = 'mailles_'.$this->nomSource; |
$ordresInsertion = array(); |
$this->getBdd()->requeter("DELETE FROM {$tableInsertion} WHERE zoom={$aInserer[0]['zoom']}"); |
foreach ($aInserer as $ligne) { |
$codeMaille = $this->nomSource.'.'.$ligne['zoom'].'-'.$ligne['indexLat'].'-'.$ligne['indexLng']; |
$sql = "('{$codeMaille}',{$ligne['zoom']},{$ligne['indexLng']},{$ligne['indexLat']},". |
"{$ligne['ouest']},{$ligne['sud']},{$ligne['est']},{$ligne['nord']},". |
"{$ligne['points']},{$ligne['observations']})"; |
$ordresInsertion[] = $sql; |
} |
$requete = "INSERT INTO {$tableInsertion} ({$champsTable}) VALUES ".implode(',', $ordresInsertion); |
$this->getBdd()->requeter($requete); |
} |
} |
?> |
/trunk/scripts/modules/maillage_projet/maillage_projet.ini |
---|
New file |
0,0 → 1,10 |
[database] |
table_index_mailles = "mailles_index" |
suffixe_table_interrogation = "_tapir" |
sources_disponibles = "sophy,baznat" |
champs_table_mailles = "code_maille,zoom,position_longitude,position_latitude,limite_ouest,limite_sud,limite_est,limite_nord,nombre_sites,nombre_observations" |
origine = 20037508.342789244 |
zoom_minimal = 3 |
zoom_maximal = 13 |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/trunk/scripts/configurations/config.defaut.ini |
---|
New file |
0,0 → 1,42 |
; Encodage : UTF-8 |
; +------------------------------------------------------------------------------------------------------+ |
; Info sur l'application |
info.nom = Scripts de tests |
; Abréviation de l'application |
info.abr = SCRIPTS |
; Version du Framework nécessaire au fonctionnement de cette application |
info.framework.version = 0.3 |
; Encodage de l'application |
encodage_appli = "UTF-8" |
; Chemin de l'application (pour l'utiliser dans ce fichier) |
chemin_scripts = "php:Framework::getCheminAppli()" |
; +------------------------------------------------------------------------------------------------------+ |
; Débogage |
; Indique si oui ou non on veut afficher le débogage. |
debogage = true |
; Indique si oui ou non on veut lancer le chronométrage |
chronometrage = false |
+------------------------------------------------------------------------------------------------------+ |
; Paramètrage de la base de données. |
; bdd_abstraction : abstraction de la base de données. |
; bdd_protocole : Protocole de la base de données. |
; bdd_serveur : Nom du serveur de bases de données. |
; bdd_utilisateur : Nom de l'utilisateur de la base de données. |
; bdd_mot_de_passe : Mot de passe de l'utilisateur de la base de données. |
; bdd_nom : Nom de la base de données principale. |
; bdd_encodage : Encodage de la base de données principale. Normalement le même que l'application mais au format base de |
; données : voir ici : http://dev.mysql.com/doc/refman/5.0/en/charset-charsets.html |
; et là: http://www.postgresql.org/docs/8.1/static/multibyte.html pour les correspondances |
bdd_abstraction = pdo |
bdd_protocole = mysql |
bdd_serveur = localhost |
bdd_utilisateur = "" |
bdd_mot_de_passe = "" |
bdd_nom = "tb_eflore_test" |
bdd_encodage = "utf8" |
; Dossier de base contenant les données d'eFlore (Fichiers TSV et SQL) |
dossierDonneesEflore = "/home/telabotap/www/eflore/donnees/" |
Property changes: |
Added: svn:mime-type |
+text/plain |
\ No newline at end of property |
/trunk/scripts/configurations |
---|
New file |
Property changes: |
Added: svn:ignore |
+config.ini |
/trunk/scripts/framework.defaut.php |
---|
New file |
0,0 → 1,6 |
<?php |
// Inclusion du Framework |
// Renomer ce fichier en "framework.php" |
// Indiquer ci-dessous le chemin absolu vers le fichier autoload.inc.php de la bonne version du Framework |
require_once '/home/www/commun/framework/0.3/Framework.php'; |
?> |
/trunk/scripts/bibliotheque/Maillage.php |
---|
New file |
0,0 → 1,228 |
<?php |
class Maillage { |
private $bbox; |
private $zoom; |
private $indexLongitude; |
private $indexLatitude; |
private $mailles; |
private $origine; |
private $bdd = null; |
public function __construct($bbox, $zoom) { |
$this->bbox = $bbox; |
$this->zoom = $zoom; |
$this->indexLongitude = array(); |
$this->indexLatitude = array(); |
$this->mailles = array(); |
$this->origine = Config::get('origine'); |
} |
public function __destruct() { |
while (count($this->indexLatitude) > 0) { |
array_pop($this->indexLatitude); |
} |
while (count($this->indexLongitude) > 0) { |
array_pop($this->indexLongitude); |
} |
while (count($this->mailles) > 0) { |
array_pop($this->mailles); |
} |
unset($this); |
} |
public function genererMaillesVides() { |
$this->recupererIndexMaillesDansBbox(); |
foreach ($this->indexLatitude as $indexLat => $intervalleLat) { |
$ligne = array(); |
foreach ($this->indexLongitude as $indexLng => $intervalleLng) { |
$ligne[] = new Maille($intervalleLat[0], $intervalleLng[0], $intervalleLat[1], |
$intervalleLng[1], $indexLat, $indexLng); |
} |
$this->mailles[] = $ligne; |
} |
} |
private function recupererIndexMaillesDansBbox() { |
$tableIndex = Config::get('table_index_mailles'); |
$requete = |
"SELECT axe, position, debut, fin FROM {$tableIndex} WHERE zoom={$this->zoom} AND (". |
"(axe='lat' AND debut<{$this->bbox['nord']} AND fin>{$this->bbox['sud']}) ". |
"OR (axe='lng' AND debut<{$this->bbox['est']} AND fin>{$this->bbox['ouest']})". |
") ORDER BY axe, position"; |
$indexMailles = $this->getBdd()->recupererTous($requete); |
foreach ($indexMailles as $index) { |
if ($index['axe'] == 'lng') { |
$this->indexLongitude[$index['position']] = array($index['debut'], $index['fin']); |
} else { |
$this->indexLatitude[$index['position']] = array($index['debut'], $index['fin']); |
} |
} |
} |
private function getBdd() { |
if (is_null($this->bdd)) { |
$this->bdd = new Bdd(); |
} |
return $this->bdd; |
} |
public function ajouterPoints($points) { |
foreach ($points as $point) { |
$longitude = $point['longitude']; |
$latitude = $point['latitude']; |
list($indexLongitude, $indexLatitude) = $this->rechercherIndexMaille($longitude, $latitude); |
$this->mailles[$indexLatitude][$indexLongitude]->ajouterPoint($point); |
} |
} |
private function rechercherIndexMaille($longitude, $latitude) { |
$indexLatitude = 0; |
$indexLongitude = 0; |
while ($indexLatitude < count($this->indexLatitude) - 1 |
&& $this->mailles[$indexLatitude][0]->getLatitudeNord() < $latitude) { |
$indexLatitude ++; |
} |
while ($indexLongitude < count($this->indexLongitude) - 1 |
&& $this->mailles[$indexLatitude][$indexLongitude]->getLongitudeEst() < $longitude) { |
$indexLongitude ++; |
} |
return array($indexLongitude, $indexLatitude); |
} |
public function formaterPourInsertionBdd() { |
$mailles_resume = array(); |
foreach ($this->mailles as $ligne) { |
foreach ($ligne as $maille) { |
if ($maille->getNombrePoints() > 0) { |
$mailles_resume[] = array( |
'zoom' => $this->zoom, |
'sud' => $maille->getLatitudeSud(), |
'ouest' => $maille->getLongitudeOuest(), |
'nord' => $maille->getLatitudeNord(), |
'est' => $maille->getLongitudeEst(), |
'indexLat' => $maille->getIndexLatitude(), |
'indexLng' => $maille->getIndexLongitude(), |
'points' => $maille->getNombrePoints(), |
'observations' => $maille->getNombreObservations() |
); |
} |
} |
} |
return $mailles_resume; |
} |
private function formaterPourQuadtree() { |
$mailles_resume = array(); |
foreach ($this->mailles as $ligne) { |
foreach ($ligne as $maille) { |
if ($maille->getNombrePoints() > 0) { |
$mailles_resume[] = array( |
'zoom' => $this->zoom, |
'sud' => $maille->getLatitudeSud(), |
'ouest' => $maille->getLongitudeOuest(), |
'nord' => $maille->getLatitudeNord(), |
'est' => $maille->getLongitudeEst(), |
'indexLat' => $maille->getIndexLatitude(), |
'indexLng' => $maille->getIndexLongitude(), |
'points' => $maille->getPoints() |
); |
} |
} |
} |
return $mailles_resume; |
} |
public function redecouperMailles() { |
$mailles = $this->formaterPourQuadtree(); |
$this->viderMailles(); |
while (count($mailles)>0) { |
$nouvellesMailles = $this->genererMaillesParQuadtree($mailles[count($mailles)-1]); |
foreach ($nouvellesMailles as $maille) { |
$this->ajouterMaille($maille); |
} |
array_pop($mailles); |
} |
$this->zoom += 1; |
} |
private function viderMailles() { |
while (count($this->indexLatitude) > 0) { |
array_pop($this->indexLatitude); |
} |
while (count($this->indexLongitude) > 0) { |
array_pop($this->indexLongitude); |
} |
while (count($this->mailles) > 0) { |
array_pop($this->mailles); |
} |
} |
private function genererMaillesParQuadtree(& $maille) { |
$ouest = $maille['ouest']; |
$est = $maille['est']; |
$sud = $maille['sud']; |
$nord = $maille['nord']; |
$indexLat = $maille['indexLat']; |
$indexLng = $maille['indexLng']; |
$milieuLongitude = $this->convertirFloatToString(($ouest + $est)/2); |
$milieuLatitude = $this->calculerMilieuLatitudes($sud, $nord); |
// sens des mailles : NordOuest, NordEst, SudOuest, SudEst |
$mailles = array(); |
$mailles[] = new Maille($milieuLatitude, $ouest, $nord, $milieuLongitude, $indexLat*2, $indexLng*2); |
$mailles[] = new Maille($milieuLatitude, $milieuLongitude, $nord, $est, $indexLat*2, $indexLng*2+1); |
$mailles[] = new Maille($sud, $ouest, $milieuLatitude, $milieuLongitude, $indexLat*2+1, $indexLng*2); |
$mailles[] = new Maille($sud, $milieuLongitude, $milieuLatitude, $est, $indexLat*2+1, $indexLng*2+1); |
$this->deplacerPoints($maille, $mailles); |
return $mailles; |
} |
private function calculerMilieuLatitudes($latitudeSud, $latitudeNord) { |
$ySud = log(tan((90 + $latitudeSud) * M_PI / 360.0 )) / (M_PI / 180.0) * ($this->origine/180.0); |
$yNord = log(tan((90 + $latitudeNord) * M_PI / 360.0 )) / (M_PI / 180.0) * ($this->origine/180.0); |
$yMilieu = ($ySud+$yNord) / 2; |
$latitude = ($yMilieu / $this->origine) * 180.0; |
$latitude = 180 / M_PI * (2 * atan(exp($latitude * M_PI / 180.0)) - M_PI / 2.0); |
return $this->convertirFloatToString($latitude); |
} |
private function deplacerPoints(& $maille, & $sousMailles) { |
$nombrePoints = count($maille['points']); |
for ($index = 0; $index < $nombrePoints; $index ++) { |
$position = ($maille['points'][$index]['latitude']>=$sousMailles[0]->getLatitudeSud()) ? 0 : 2; |
$position += ($maille['points'][$index]['longitude']<$sousMailles[$position]->getLongitudeEst()) ? 0 : 1; |
$sousMailles[$position]->ajouterPoint($maille['points'][$index]); |
} |
} |
private function ajouterMaille($maille) { |
$indexLat = $maille->getIndexLatitude(); |
$indexLng = $maille->getIndexLongitude(); |
if (!isset($this->indexLongitude[$indexLng])) { |
$this->indexLongitude[$indexLng] = array($maille->getLongitudeOuest(), $maille->getLongitudeEst()); |
$this->mailles[$indexLng] = array(); |
} |
if (!isset($this->indexLongitude[$indexLat])) { |
$this->indexLatitude[$indexLat] = array($maille->getLatitudeSud(), $maille->getLatitudeNord()); |
} |
$this->mailles[$indexLng][$indexLat] = $maille; |
} |
private function convertirFloatToString($float) { |
return str_replace(',', '.', strval($float)); |
} |
} |
?> |
/trunk/scripts/bibliotheque/Maille.php |
---|
New file |
0,0 → 1,76 |
<?php |
class Maille { |
private $latitudeSud; |
private $longitudeOuest; |
private $latitudeNord; |
private $longitudeEst; |
private $indexLatitude; |
private $indexLongitude; |
private $points = array(); |
private $observations = array(); |
public function __construct($sud, $ouest, $nord, $est, $indexLat, $indexLng) { |
$this->latitudeSud = $sud; |
$this->longitudeOuest = $ouest; |
$this->latitudeNord = $nord; |
$this->longitudeEst = $est; |
$this->indexLatitude = $indexLat; |
$this->indexLongitude = $indexLng; |
} |
public function ajouterPoint($point) { |
$this->points[] = $point; |
$this->observations[] = $point['observations']; |
} |
public function getLatitudeNord() { |
return $this->latitudeNord; |
} |
public function getLongitudeOuest() { |
return $this->longitudeOuest; |
} |
public function getLatitudeSud() { |
return $this->latitudeSud; |
} |
public function getLongitudeEst() { |
return $this->longitudeEst; |
} |
public function getIndexLatitude() { |
return $this->indexLatitude; |
} |
public function getIndexLongitude() { |
return $this->indexLongitude; |
} |
public function getPoints() { |
return $this->points; |
} |
public function getNombrePoints() { |
return count($this->points); |
} |
public function getNombreObservations() { |
return array_sum($this->observations); |
} |
public function getPoint($index = 0) { |
return (!isset($this->points[$index])) ? NULL : $this->points[$index]; |
} |
public function totalNonNul() { |
return count($this->points) > 0; |
} |
} |
?> |
/trunk/scripts/cli.php |
---|
New file |
0,0 → 1,37 |
<?php |
// Encodage : UTF-8 |
// +-------------------------------------------------------------------------------------------------------------------+ |
/** |
* Initialise le chargement et l'exécution des scripts |
* |
* Lancer ce fichier en ligne de commande avec : |
* <code>/opt/lampp/bin/php cli.php mon_script -a test</code> |
* |
//Auteur original : |
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org> |
* @author Delphine CAUQUIL <delphine@tela-botanica.org> |
* @copyright Tela-Botanica 1999-2008 |
* @licence GPL v3 & CeCILL v2 |
* @version $Id$ |
*/ |
// +-------------------------------------------------------------------------------------------------------------------+ |
// Le fichier Framework.php du Framework de Tela Botanica doit être appelée avant tout autre chose dans l'application. |
// Sinon, rien ne sera chargé. |
// Chemin du fichier chargeant le framework requis |
$framework = dirname(__FILE__).DIRECTORY_SEPARATOR.'framework.php'; |
if (!file_exists($framework)) { |
$e = "Veuillez paramétrer l'emplacement et la version du Framework dans le fichier $framework"; |
trigger_error($e, E_USER_ERROR); |
} else { |
// Inclusion du Framework |
require_once $framework; |
// Ajout d'information concernant cette application |
Framework::setCheminAppli(__FILE__);// Obligatoire |
Framework::setInfoAppli(Config::get('info')); |
// Initialisation et lancement du script appelé en ligne de commande |
Cli::executer(); |
} |
?> |
/trunk/scripts |
---|
New file |
Property changes: |
Added: svn:ignore |
+framework.php |
/trunk |
---|
Property changes: |
Added: svn:ignore |
+.project |
+france_02.svg |
+.buildpath |