* @author Jennifer Dhé * @license GPL v3 * @license CECILL v2 * @version 1.0 * @copyright 1999-${year} Tela Botanica (accueil@tela-botanica.org) */ class ZoneGeo extends Commun { protected $service = 'zone-geo'; /** * Permet de stocker la requete formulée : /zone-geo | /zone-geo/#id | /zone-geo/#id/champ | /zone-geo/#id/relations * Est remplit au cours de l'analyse des ressources (traiterRessources()), par défaut, a la valeur du service. * Est utilisée principalement pr déterminer le format du tableau à retourner. */ protected $format_reponse = 'zone-geo'; /** Variables constituant les parametres de la requete SQL (champ, condition, group by, limit) remplie * selon ressources et paramètres */ protected $requete_champ = ' * '; protected $requete_condition = ''; protected $limite_requete = array( 'depart' => 0, 'limite' => 100 ); /** Stockage des ressources et paramétres */ protected $table_ressources = array(); protected $table_param = array(); /** * Precise la contenance plus ou moins précise du tableau à retourner : * - min = les données présentes dans la table * - max = les données de la table + les informations complémentaires (pour les identifiants et les codes) * - oss = la liste des nom_sci (uniquement pour noms et taxons) */ protected $retour_format = 'max'; /** Valeur du paramètre de requete recherche : * - stricte : le masque est passé tel quel à l'opérateur LIKE. * - etendue : ajout automatique du signe % à la place des espaces et en fin de masque avec utilisation de LIKE. * - floue : recherche tolérante vis-à-vis d'approximations ou d'erreurs (fautes d'orthographe par exemple) */ protected $recherche; /** Permet de stocker le tableau de résultat (non encodé en json) */ protected $table_retour = array(); /** Stocke le nombre total de résultats de la requete principale. Est calculée lors de l'assemblage de la requete */ protected $total_resultat; // +-----------------------------------------------------------------------------------------------------+ public function traiterParametres() { if (isset($this->parametres) && !empty($this->parametres)) { $this->table_param = $this->parametres; // masque : filtre la liste en fonction d'un masque de recherche portant sur le code, le nom ou la region. // masque.code : filtre uniquement sur le code. masque.nom : filtre uniquement sur le nom. // masque.region : filtre uniquement sur la region. if (isset($this->parametres['recherche']) && $this->parametres['recherche'] != '') { $this->recherche = $this->parametres['recherche']; } foreach ($this->parametres as $param => $valeur) { switch ($param) { case 'masque' : $this->ajouterLeFiltreMasque('masque', $valeur); break; case 'masque.code' : $this->ajouterLeFiltreMasque('codet', $valeur); break; case 'masque.nom' : $this->ajouterLeFiltreMasque('nom', $valeur); break; case 'masque.statut' : $this->ajouterLeFiltreMasque('codet_statut', $valeur); break; case 'retour.format' : $this->retour_format = $valeur; break; case 'navigation.depart' : $this->limite_requete['depart'] = $valeur; break; case 'navigation.limite' : $this->limite_requete['limite'] = $valeur; break; case 'recherche' : break; default : $p = 'Erreur dans les paramètres de recherche de votre requête : '. '
Le paramètre " '.$param.' " n\'existe pas.'; $this->renvoyerErreur(RestServeur::HTTP_CODE_MAUVAISE_REQUETE, $p); break; } } } } public function ajouterLeFiltreMasque($nom_champ, $valeur) { if ($nom_champ == 'codet') { $this->requete_condition[] .= $nom_champ.' = '.$this->getBdd()->proteger($valeur); } else { if ($this->recherche == 'floue') { if ($nom_champ == 'masque') { $this->requete_condition[] = ' ( codet = '.$this->getBdd()->proteger($valeur) .' OR (SOUNDEX(nom_francais) = SOUNDEX(\''.$valeur.'\')' .' OR SOUNDEX(REVERSE(nom_francais)) = SOUNDEX(REVERSE(\''.$valeur.'\')) OR ' .'SOUNDEX(nom_anglais) = SOUNDEX(\''.$valeur.'\')' .' OR SOUNDEX(REVERSE(nom_anglais)) = SOUNDEX(REVERSE(\''.$valeur.'\'))) ' .' OR ( SOUNDEX(codet_statut) = SOUNDEX(\''.$valeur.'\')' .' OR SOUNDEX(REVERSE(codet_statut)) = SOUNDEX(REVERSE(\''.$valeur.'\')) ' .')) '; } elseif ($nom_champ == 'nom') { $this->requete_condition[] = '(SOUNDEX(nom_francais) = SOUNDEX(\''.$valeur.'\')' .' OR SOUNDEX(REVERSE(nom_francais)) = SOUNDEX(REVERSE(\''.$valeur.'\'))) OR (SOUNDEX(nom_anglais) = SOUNDEX(\''.$valeur.'\')' .' OR SOUNDEX(REVERSE(nom_anglais)) = SOUNDEX(REVERSE(\''.$valeur.'\'))) '; } else { $this->requete_condition[] = '(SOUNDEX('.$nom_champ.') = SOUNDEX(\''.$valeur.'\')' .' OR SOUNDEX(REVERSE('.$nom_champ.')) = SOUNDEX(REVERSE(\''.$valeur.'\'))) '; } } else { if ($this->recherche == 'etendue') { $valeur = str_replace(' ','%', $valeur); $valeur .= '%'; } if ($nom_champ == 'masque') { $this->requete_condition[] = '(codet = '.$this->getBdd()->proteger($valeur) .' OR nom_francais LIKE '.$this->getBdd()->proteger($valeur) .' OR nom_anglais LIKE '.$this->getBdd()->proteger($valeur) .' OR codet_statut LIKE '.$this->getBdd()->proteger($valeur).')'; } elseif ($nom_champ == 'nom') { $this->requete_condition[] = '(nom_francais LIKE '.$this->getBdd()->proteger($valeur).' OR ' .'nom_anglais LIKE '.$this->getBdd()->proteger($valeur).') '; } else { $this->requete_condition[] = $nom_champ.' LIKE '.$this->getBdd()->proteger($valeur); } } } } // +-----------------------------------------------------------------------------------------------------+ public function traiterRessources() { if (isset($this->ressources) && !empty($this->ressources)) { $this->table_ressources = $this->ressources; if (isset($this->table_ressources[0]) && !empty($this->table_ressources[0])) { //requete = /zone-geo/#id $this->traiterRessourceId(); if (isset($this->table_ressources[1]) && !empty($this->table_ressources[1])) { //requete = /zone-geo/#id/#champ ou /zone-geo/#id/relations $this->traiterRessourceChampOuRelations(); } } } } public function traiterRessourceId() { //requete : /zone-geo/#id (ex : /zone-geo/7) if ($this->table_ressources[0]) { $this->requete_condition[] = ' codet = '.$this->getBdd()->proteger($this->table_ressources[0]); $this->format_reponse .= '/id'; } else { $r = 'Erreur dans les ressources de votre requête :
La ressource " '.$this->table_ressources[0]. ' " n\'existe pas.'; $this->renvoyerErreur(RestServeur::HTTP_CODE_MAUVAISE_REQUETE, $r); } } public function traiterRessourceChampOuRelations() { if ($this->table_ressources[1] == 'relations') { $r = 'Erreur dans les ressources de votre requête :
La ressource " '.$this->table_ressources[1]. ' " n\'existe pas.'; $this->renvoyerErreur(RestServeur::HTTP_CODE_MAUVAISE_REQUETE, $r); } else { $this->format_reponse .= '/champ'; } } // +-------------------------------------------------------------------------------------------------------------------+ public function assemblerLaRequete() { //assemblage de la requete : $requete = ' SELECT '.$this->requete_champ. ' FROM '.$this->table .$this->formerRequeteCondition() .$this->formerRequeteLimite(); return $requete; } //ajout d'une limite seulement pour les listes (pas plus de 100 resultats retournés pr les requetes // suivantes : /zone-geo et /zone-geo/#id/relations) public function formerRequeteLimite() { if ($this->format_reponse != 'zone-geo') { $this->requete_limite = ''; } elseif (($depart = $this->limite_requete['depart']) > ($this->total_resultat = $this->recupererTotalResultat())) { //cas ou la requete presente un navigation.depart supérieur au nb total de resultats. $this->limite_requete['depart'] = (($nb - $this->limite_requete['limite']) < 0) ? 0 : ($nb - $this->limite_requete['limite']); $this->requete_limite = ' LIMIT '.$this->limite_requete['depart'].', '.$this->limite_requete['limite']; } else { $this->requete_limite = ' LIMIT '.$this->limite_requete['depart'].', '.$this->limite_requete['limite']; } return $this->requete_limite; } public function formerRequeteCondition() { $condition = ''; if ($this->requete_condition != null) { $condition = ' WHERE '.implode(' AND ', $this->requete_condition); } return $condition; } public function recupererTotalResultat() { //on récupère le nombre total de résultats de la requete (ex : le nombre d'id contenu dans la liste /zone-geo) $requete = 'SELECT count(*) as nombre FROM ' .$this->table .$this->formerRequeteCondition(); $res = $this->getBdd()->recuperer($requete); if ($res) { $total = $res['nombre']; } else { $t = 'Fonction recupererTotalResultat() :
Données introuvables dans la base'; $this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $t); } return $total; } // +-------------------------------------------------------------------------------------------------------------------+ // determine en fct du service appelé (/zone-geo | /zone-geo/#id | /zone-geo/#id/champ | // /zone-geo/#id/relations) le format du tableau à retourner. Encode en json public function retournerResultatFormate($resultat) { $this->recupererTableConfig('correspondance_champs'); switch ($this->format_reponse) { case 'zone-geo' : $reponse = $this->formaterZoneGeo($resultat); break; case 'zone-geo/id' : $reponse = $this->formaterZoneGeoId($resultat[0]); break; case 'zone-geo/id/champ' : $reponse = $this->formaterZoneGeoIdChamp($resultat[0]); break; default : break; } return $reponse; } public function formaterZoneGeo($resultat) { //on remplit la table $table_retour_json['entete'] $this->table_retour['depart'] = $this->limite_requete['depart']; $this->table_retour['limite'] = $this->limite_requete['limite']; $this->table_retour['total'] = $this->total_resultat; $url = $this->formulerUrl($this->total_resultat, '/zone-geo'); if (isset($url['precedent']) && $url['precedent'] != '') { $this->table_retour['href.precedent'] = $url['precedent']; } if (isset($url['suivant']) && $url['suivant'] != '') { $this->table_retour['href.suivant'] = $url['suivant']; } $table_retour_json['entete'] = $this->table_retour; //on remplit la table $table_retour_json['resultat'] $this->table_retour = array(); if (isset($this->table_param['masque_nom'])) $resultat = $this->trierRechercheFloue($this->table_param['masque_nom'], $resultat, 'nom_francais'); foreach ($resultat as $tab) { foreach ($tab as $key => $valeur) { $valeur = rtrim($valeur); if ($valeur != '') { switch ($key) { case 'codet' : $num = $valeur; $this->table_retour['code'] = $valeur; break; case 'nom_francais' : $this->table_retour['nom'] = $valeur; break; case 'nom_anglais' : if ($tab['nom_francais'] == '') $this->table_retour['nom'] = $valeur; break; case 'codet_statut' : $this->table_retour['statut'] = $valeur; break; default : break; } } } if ($this->retour_format == 'max') { $this->table_retour['href'] = $this->ajouterHref('zone-geo', $num); } $resultat_json[$num] = $this->table_retour; $this->table_retour = array(); } $table_retour_json['resultat'] = $resultat_json; return $table_retour_json; } public function formaterZoneGeoId($resultat) { foreach ($resultat as $key => $valeur) { if ($valeur != '') { $this->afficherDonnees($key, $valeur); } } unset($this->table_retour['href']); return $this->table_retour; } public function formaterZoneGeoIdChamp($resultat) { //on recupère tous les resultats possibles $reponse = $this->formaterZoneGeoId($resultat); $this->table_retour = array(); //on recupère les résultats demandés à partir du tableau de résultat complet $this->table_retour['id'] = $reponse['code']; $champs = explode(' ', $this->table_ressources[1]); foreach ($champs as $champ) { if ($champ == 'nom') $champ = 'nom.fr'; if ($this->verifierValiditeChamp($champ)) { if (strrpos($champ, '.*') !== false) { $this->afficherPointEtoile($champ, $reponse); } else { if (isset($reponse[$champ])) { $this->table_retour[$champ] = $reponse[$champ]; } else { $this->table_retour[$champ] = null; } } } } return $this->table_retour; } public function verifierValiditeChamp($champ) { preg_match('/^([^.]+)(\.([^.]+))?$/', $champ, $match); $champs_possibles = $this->correspondance_champs; $champs_possibles[] = 'nom.*'; if (in_array($match[1], $champs_possibles)) { $validite = true; } elseif (in_array($match[0], $champs_possibles)) { $validite = true; } else { $champs_possibles = implode('
  • ', $champs_possibles); $c = 'Erreur dans votre requête :
    Le champ "'.$champ_possibles.'" n\'existe pas. '. 'Les champs disponibles sont :
  • '.$champs_possibles.'
  • '; $this->renvoyerErreur(RestServeur::HTTP_CODE_MAUVAISE_REQUETE, $c); } return $validite; } public function afficherPointEtoile($champ, $reponse) { preg_match('/^([^.]+\.)\*$/', $champ, $match); foreach ($reponse as $chp => $valeur) { if (strrpos($chp, $match[1]) !== false) { if ($valeur != '') { $this->table_retour[$chp] = $valeur; } else { $this->table_retour[$chp] = null; } } } } public function afficherDonnees($champ, $valeur) { if ($this->retour_format == 'max') { if ($champ == 'codet_statut') { $this->table_retour[$this->correspondance_champs[$champ]] = $valeur; $this->table_retour[$this->correspondance_champs[$champ].'.href'] = $this->ajouterHref('ontologies', 'masque.nom=Codet '.$valeur, '?'); } else { $this->table_retour[$this->correspondance_champs[$champ]] = $valeur; } } else { $this->table_retour[$this->correspondance_champs[$champ]] = $valeur; } } // +-------------------------------------------------------------------------------------------------------------------+ /** Permet de retourner l'url http://tela-botanica.org/service:eflore:0.1/[projet]/[version_projet]/[service]/[ressource]:[valeur] * @param $service : correspond au nom de la ressource à laquelle on souhaite acceder * @param $val : correspond au paramètre de la ressource (ex : * @param $projet : est remplit dans les cas suivants : * - si le projet dans lequel se trouve l'information est différent de celui du service appelé * - si on souhaite rappeler le meme projet avec la meme ressource mais un parametre de ressource différent */ public function ajouterHref($service, $val, $separation = '/') { $val = $this->encoderUrl($val); if ($this->version_projet == '+') { $url = Config::get('url_service_base').Config::get('nom_projet').'/'.$service.$separation.$val; } else { $url = Config::get('url_service_base').Config::get('nom_projet').'/'.$this->version_projet.'/'.$service.$separation.$val; } return $url; } public function encoderUrl($url) { $url = str_replace(' ', '%20', $url); $url = str_replace('?', urlencode('?'), $url); return $url; } } ?>