Rev 31 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?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-WFSprivate 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 defautif (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 virguleif (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 validesif ($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-WFSprivate 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();}}?>