Rev 702 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php/*** Classe Commun.php est une classe abstraite qui contient les méthodes de base communes à tous les* sous-services des projets.** Encodage en entrée : utf8* Encodage en sortie : utf8* @package eflore-projets* @author Jennifer DHÉ <jennifer.dhe@tela-botanica.org>* @author Delphine CAUQUIL <delphine@tela-botanica.org>* @author Jean-Pascal MILCENT <jpm@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 1.0* @copyright 1999-2011 Tela Botanica (accueil@tela-botanica.org)*/abstract class Commun {/** Objet Bdd. */private $Bdd = null;/** Objet Rest Client. */private $RestClient = null;/** Contients les paramètres. Doit remplacer table_param. */protected $parametres = array();/** Contients les ressources. Doit remplacer table_ressources. */protected $ressources = array();/** Le nom du service courrant. */protected $serviceNom = null;//Classe commune à tous les services web d'un projet. Contient par exemple les fonctions permettant de//renvoyer la réponse http...protected $entete_http; // Entete de la réponse correspondant au code de réponse de la requete http */protected $corps_http; // Tableau de résultat à retourner au format json ou la description de l'erreur si elle existe */protected $service; // Nom du service appelé/** Stocke la version du projet demandée dans la requete* - "*" : (/#projet/* /meta-donnees) Renvoi les meta-données de toutes les versions du projet* - "numero de la version" : (/#projet/2.00/meta-donnees) Renvoi les meta-données de la version 2.00 du projet */protected $version_projet = '+';protected $table_version; //Stocke les noms des tables de toutes les versions du projet disponibles/** tableau contenant tous les champs d'une table (est rempli par la fonction Commun::recupererNomChamp($table)) */protected $champs_table = array();private static $tri_multi_dimension = array();private static $tri_type = '';public function consulter($ressources, $parametres) {$this->ressources = $ressources;$this->parametres = $parametres;$this->chargerNomDuService();$this->traiterParametres();$this->traiterVersionProjet();$resultats = '';foreach ($this->table_version as $version) {$this->table = $version; //on stocke le nom de la table correspondant à la version du projet en cours$this->recupererNomChamp($this->table); //on récupère les noms des champs disponibles (Ds Commun.php)$this->traiterRessources(); //dans CommunNomsTaxons.php$requete = $this->assemblerLaRequete();$resultat = $this->getBdd()->recupererTous($requete);$versionResultat = $this->traiterResultat($resultat, $version, $requete);if (count($this->table_version) > 1) {$resultats[$version] = $versionResultat;} else {$resultats = $versionResultat;}}return $resultats;}private function chargerNomDuService() {$this->serviceNom = get_class($this);}public function traiterResultat($resultat, $version, $requete) {$versionResultat = null;if ($resultat == '') {//cas ou la requete comporte des erreurs$message = 'La requête SQL formée comporte une erreur!';$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;throw new Exception($message, $code);} elseif ($resultat) {$versionResultat = $this->retournerResultatFormate($resultat, $version);} else {$message = 'Les données recherchées sont introuvables.';$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;throw new Exception($message, $code);}return $versionResultat;}//+------------------------------------------------------------------------------------------------------+// Méthodes concernant les paramètres/*** Permet de récupérer une liste des noms des champs de la table passée en paramètre* @param $table : Nom de la table dont on souhaite connaitre les champs*/public function recupererNomChamp($table) {$requete = 'SHOW FIELDS FROM '.$table;$resultat = $this->getBdd()->recupererTous($requete);if ($resultat == '') {$e = 'La requête SQL formée comporte une erreur!';$this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $e);} elseif ($resultat) {foreach ($resultat as $info) {$this->champs_table[] = $info['Field'];}} else {$m = "La table recherchée n'existe pas";$this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $m);}}/*** Fonction permettant de creer la table dont le nom est passé en paramètre (champs_api, champs_bdtfx,* correspondance_champs...). Les données de chaque table sont présentes dans le fichier de configuration config.ini* @param String $table : Peut contenir plusieurs nom de table dont on souhaite récupérer les données : table,table,table.* Ex : recupererTableConfig('champs_api,champs_bdtfx')*/public function recupererTableConfig($table) {$tables = explode(',', $table);foreach ($tables as $tab) {$tableau = explode(',', Config::get($tab));$tableau = array_map('trim', $tableau);foreach ($tableau as $champ) {list($code, $rang) = explode('=', $champ);$tab_tampon[$code] = $rang;}$this->$tab = $tab_tampon;$tab_tampon = array();}}public function renvoyerErreur($entete, $message) {throw new Exception($message, $entete);}/*** Permet de remplir la variable version_projet et de retirer cette donnée du tableau des ressources* @param $ressources*/public function traiterVersionProjet() {if (isset($this->parametres['version.projet'])) {if (preg_match('/^[0-9]+(?:[._][0-9]+|)$/', $this->parametres['version.projet'])) {$this->version_projet = $this->parametres['version.projet'];$this->version_projet = 'v'.str_replace('.', '_', $this->version_projet);} else {$this->version_projet = $this->parametres['version.projet'];}}//si la liste des noms est demandée pr toutes les versions, on affiche seulement la dernière version :if ($this->version_projet == '*' && $this->ressources == array()) {$message = "L'affichage de plusieurs versions ne fonctionne que pour les ressources de type /ressources/#id";$code = RestServeur::HTTP_CODE_MAUVAISE_REQUETE;throw new Exception($message, $code);}//on recupère les versions du projet disponible dans la table des meta-donnees (utilisation service MetaDonnees)$table_num_version = $this->recupererVersionDisponible();//on recupere la liste des noms des tables de la bdd correspondant aux differentes versions du projet en fct de la ou les versions demandées$this->recupererListeNomTablePrChaqueVersion($table_num_version);}/*** Recupération des versions disponibles par appel du service metaDonnees* Verification de l'existance du service recherché dans la requete (si précisé : hors *)* @return array : tableau contenant le numéro de chaque version disponible*/public function recupererVersionDisponible() {$versions_dispo = '';$req_version = 'SELECT version FROM '.Config::get('bdd_table_meta');$res_version = $this->getBdd()->recupererTous($req_version);if ($res_version == '') { //cas ou la requete comporte des erreurs$e = "La requête SQL de versionnage formée comporte une erreur : $req_version";$this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $e);} elseif ($res_version) {foreach ($res_version as $version) {$versions_dispo[] = $version['version'];}} else {$m = 'Versions introuvables dans la table des méta-données';$this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $m);}return $versions_dispo;}public function recupererListeNomTablePrChaqueVersion($table_num_version) {switch ($this->serviceNom) {case 'Ontologies' :$prefixe_table = 'bdd_table_ontologies';break;default:$prefixe_table = 'bdd_table';}switch ($this->version_projet) {case '+' :$derniere_version = $table_num_version[count($table_num_version) - 1];$this->table_version[] = Config::get($prefixe_table).'_v'.str_replace('.', '_', $derniere_version);break;case '*' :foreach ($table_num_version as $num_version) {$this->table_version[] = Config::get($prefixe_table).'_v'.str_replace('.', '_', $num_version);}break;default :$this->table_version[] = Config::get($prefixe_table).'_'.$this->version_projet;break;}}/*** Est appelée pour former l'url complete des resultats precedants ou suivants.* @param int : Permet de connaitre le nombre de noms obtenus par la requete* @return string Retourne l'url complete des resultats precedents ou suivant sous la forme d'un tableau*/public function formulerUrl($nb_resultat, $id = null) {$url = array();$debut_url = Config::get('url_service').$id.'?';//on recré l'url sans les parametres de navigation qui seront rajouter ci-apres. On les enlève dc de la table des parametresforeach($this->parametres as $cle => $val) {$param_url[str_replace('_', '.', $cle)] = $val;}$this->recupererLesLimitesSuivantes($nb_resultat, $param_url);if (isset($param_url['navigation.depart']) && isset($param_url['navigation.limite'])) {$url['suivant'] = $debut_url.http_build_query($param_url);}$this->recupererLesLimitesPrecedentes($param_url);if (isset($param_url['navigation.depart']) && isset($param_url['navigation.limite'])) {$url['precedent'] = $debut_url.http_build_query($param_url);}return $url;}public function supprimerNavigation(&$param_url) {unset($param_url['navigation.depart']);unset($param_url['navigation.limite']);}/*** Description :* Permet de former les limites de la requete retournant les résultats suivants.* Cette url sera afficher dans l'entete de la reponse retournée en format JSON (retour.format=defaut).* @param int : $nb_resultat : Permet de connaitre le nombre de résultats obtenus par la requete* @return string : la fin de l'url decrivant les limites des resultats suivants. Si aucun résultats ne suient,* une chaine de caractère vide est retournée*/public function recupererLesLimitesSuivantes($nb_resultat, &$param_url_suiv) {$this->supprimerNavigation($param_url);$depart = $this->limite_requete['depart'];$limite = $this->limite_requete['limite'];$depart_suivant = $depart + $limite;$limite_suivant = $limite;if ($nb_resultat > $depart_suivant) {$param_url_suiv['navigation.depart'] = $depart_suivant;$param_url_suiv['navigation.limite'] = $limite_suivant;} else {$param_url_suiv['navigation.depart'] = null;$param_url_suiv['navigation.limite'] = null;}}/*** Description :* Permet de former les limites de la requete retournant les résultats precedents.* Cette url sera afficher dans l'entete de la taxons/105reponse retournée en format JSON (retour.format=defaut)* @return string : la fin de l'url decrivant les limites des resultats precedents.* Si aucun résultats ne precedent, une chaine de caractère vide est retournée*/public function recupererLesLimitesPrecedentes(&$param_url) {$this->supprimerNavigation($param_url);$depart = $this->limite_requete['depart'];$limite = $this->limite_requete['limite'];if ($depart == 0) {$url_precedente = '';} else {if (($depart - $limite) < 0) {$depart_precedent = 0;} else {$depart_precedent = $depart - $limite;}$param_url['navigation.depart'] = $depart_precedent;$param_url['navigation.limite'] = $limite;}}public function ajouterHref($service, $val) {// http://tela-botanica.org/service:eflore:0.1/[projet]/[version_projet]/[service]/[ressource]:[valeur]if ($this->version_projet == '+') {$url = Config::get('url_service_base').Config::get('nom_projet').'/'.$service.'/'.$val;} else {$url = Config::get('url_service_base').Config::get('nom_projet').'/'.$service.'/'.$val.'?version.projet='.ltrim($this->version_projet, 'v');}return $url;}public function ajouterHrefAutreProjet($service, $ressource, $valeur, $projet = null, $param = null) {//on enleve les GA et Co, les meta ou les "_"$this->transliterer($service, $valeur);//on définit les nom des projets, des services et des ressources de l'url (dans les méta-donnees)$tab = array('langue' => array('service' => 'langues', 'projet' => 'iso-639-1', 'ressource' => ''),'couverture_spatiale' => array('service' => 'zone-geo', 'projet' => 'iso-3166-1', 'ressource' => ''),'type' => array('service' => 'ontologies', 'projet' => 'eflore', 'ressource' => 'contactType:'),'datum' => array('service' => 'ontologies', 'projet' => 'eflore', 'ressource' => 'datum:'));if (array_key_exists($service, $tab)) {extract($tab[$service]);} else {if (strpos(Config::get('nom_projet'), 'bd') === 0 && $projet == null) {$projet = 'bdnt';$service = 'ontologies';$ressource = '';}}$param = ($param) ? "?".$param : "";$url = Config::get('url_service_base').$projet.'/'.$service.'/'.$ressource.$valeur.$param;return $url;}/**Permet de consulter une url et retourne le résultat ou une erreur* @param $url */public function consulterHref($url) {$res = $this->getRestClient()->consulter($url);$entete = $this->getRestClient()->getReponseEntetes();//Si le service meta-donnees fonctionne correctement, l'entete comprend la clé wrapper_dataif (isset($entete['wrapper_data'])) {$res = json_decode($res);return $res;} else {$u = 'L\'url <a href="'.$url.'">'.$url.'</a> lancée via RestClient renvoie une erreur';$this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $u);}}public function transliterer(&$service, &$val) {if (preg_match('/^.+:(.+)$/', $val, $match)) {$val = $match[1];}$service = str_replace(array('_Ga','_Co','_meta'), '', $service);if ($service == 'rang') {$ressource = 'rangTaxo';} elseif (preg_match('/^(statut)(?:_|-)([^_-]+)$/', $service, $match)) {$service = $match[1].ucfirst($match[2]);} elseif (strrpos($service, 'datum') !== false) {$service = 'datum';}}// prend en valeur la valeur de la recherche, les résultats approchés, le paramétre recherche// retourne le tableau trié en fonction de la ressemble entre le résultat approché et la valeur recherchéepublic function trierRechercheFloue($nom_demande, $tab_approchee, $nom) {$trie = '';$resultat = array();foreach ($tab_approchee as $id => $tab) {$nom_demande_ss = strtolower(Chaine::supprimerAccents($nom_demande));$nom_flou_ss = strtolower(Chaine::supprimerAccents($tab[$nom]));$stat = array();// Prime pour la ressemblance globale :$score = 500 - levenshtein($nom_flou_ss, $nom_demande_ss);// On affine$score = $score + (similar_text($nom_demande_ss, $nom_flou_ss) * 3);$stat['score'] = $score;foreach ($tab as $key => $valeur) {$stat[$key] = $valeur;}$resultat[] = $stat;}// Vérification que nous avons bien trouvé un nom approchéif (count($resultat) > 0) {$trie = Tableau::trierMD($resultat, array('score' => SORT_DESC));}return $trie;}protected function recupererTableauConfig($param) {$tableau = array();$tableauPartiel = explode(',', Config::get($param));$tableauPartiel = array_map('trim', $tableauPartiel);foreach ($tableauPartiel as $champ) {if (strpos($champ, '=') === false) {$tableau[] = $champ;} else {list($cle, $val) = explode('=', $champ);$tableau[$cle] = $val;}}return $tableau;}//+------------------------------------------------------------------------------------------------------+// Méthodes d'accès aux objets du Framework/*** Méthode de connection à la base de données sur demande.* Tous les services web n'ont pas besoin de s'y connecter.*/protected function getBdd() {if (! isset($this->Bdd)) {$this->Bdd = new Bdd();}return $this->Bdd;}/*** Méthode permettant de faire appel à un client REST en fonction des besoins du service.*/protected function getRestClient() {if (! isset($this->RestClient)) {$this->RestClient = new RestClient();}return $this->RestClient;}}?>