* @license GPL v3 * @license CECILL v2 * @version 1.0 * @copyright 1999-${year} Tela Botanica (accueil@tela-botanica.org) */ class MetaDonnees extends Commun { protected $requete_champ = '*'; protected $requete_condition = null; protected $retour_format = 'max'; protected $table_retour = array(); protected $format_reponse = 'metaDonnees'; protected $table_ressources; static $cache_ontologies = array(); public function consulter($ressources, $parametres) { $this->ressources = $ressources; $this->parametres = $parametres; $this->service = 'meta-donnees'; $resultats = ''; // on traite en premier la version dans le cas ou un langage est demandé pr une version $this->traiterVersionProjet(); $this->traiterParametres($parametres); $this->traiterRessources($ressources); if ($this->corps_http == '' && $this->entete_http == '') { $requete_meta = $this->assemblerLaRequete(); $resultat_meta = $this->getBdd()->recupererTous($requete_meta); $resultats = $this->formerResultat($resultat_meta, $requete_meta); } return $resultats; } public function formerResultat($resultat_meta, $requete_meta) { if ($resultat_meta == '') { $e = 'La requête formée comporte une erreur!'; $this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE,$e); Debug::printr($requete); } elseif ($resultat_meta) { $resultat_formate = $this->retournerResultatFormate($resultat_meta); } else { $m = "Données introuvables dans la base $this->table"; $this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $m); Debug::printr($requete_meta); } return $resultat_formate; } //--------------------FONCTIONS TRAITEMENT DES PARAMETRES--------------------------------------------------------------- public function traiterParametres($parametres) { if (isset($parametres) && !empty($parametres)) { foreach ($parametres as $param => $val) { switch ($param) { case 'version.projet' : $this->ajouterFiltreVersion($val); break; case 'retour.langue' : $this->rechercherLangueDispo($val); break; case 'retour.format' : $this->retour_format = $val; break; default : $e = '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, $e); break; } } } } /** Détermine quelles métadonnées doivent etre retournées : * - "*" : (/#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 * - non renseignée : (/#projet/meta-donnees) Renvoi les meta-données de la dernière version du projet * Cette info est stockée dans par la classe RestServeur dans la variable $ressources ($ressources[0]) */ public function ajouterFiltreVersion($val) { if (preg_match('/(?:[0-9]+(?:_|[.])[0-9]+|[*]| )/', $val)) { $this->version_projet = ($val == ' ') ? '+' : $val; } switch ($this->version_projet) { case '+' : $this->requete_condition[] = 'version = (SELECT MAX(version) FROM '.Config::get('bdd_table_meta').')'; break; case '*' : break; default : if (is_numeric($this->version_projet)) { $versions_dispo = $this->rechercherVersionsDispos(); if (in_array($val, $versions_dispo)) { $this->requete_condition[] = 'version = '.$this->getBdd()->proteger($val); } else { $e = 'La version demandée n\'existe pas actuellement.
Les versions disponibles sont : ' .implode(', ', $versions_dispo); $this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $e); } } break; } } /** * Vérifie que le numéro de la version passée en paramètre correspond à une version existante. * Si oui remplit la condition de la requete SQL */ public function rechercherVersionsDispos() { $val = str_replace('_', '.', $this->version_projet); $req_version = 'SELECT version FROM '.Config::get('bdd_table_meta'); $res_version = $this->getBdd()->recupererTous($req_version); foreach ($res_version as $version) { $versions_dispo[] = $version['version']; } return $versions_dispo; } /** Vérifie que les meta-donnees existe dans la langue passée en paramètre, Si oui remplit la condition de la requete SQL */ public function rechercherLangueDispo($val) { //on recherche les langues_meta disponibles pour la version demandée : (d'ou ajout de la condition) $req_langue = 'SELECT langue_meta FROM ' .Config::get('bdd_table_meta') .$this->formerRequeteCondition(); $res_langue = $this->getBdd()->recupererTous($req_langue); foreach ($res_langue as $langue) { $langue_dispo[] = $langue['langue_meta']; } if (in_array($val, $langue_dispo)) { $this->requete_condition[] = 'langue_meta = '.$this->getBdd()->proteger($val); } else { $e = 'La langue demandée n\'existe pas actuellement.
Les langues disponibles sont : ' .implode($langue_dispo); $this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $e); } } //----------------------FONCTIONS TRAITEMENT DES RESSOURCES------------------------------------------------------------- public function traiterRessources($ressources) { // /meta-donnees (liste des meta-données. Toutes les info de la table sont affichées) ou /meta-donnees/#champ if (isset($ressources) && !empty($ressources)) { $this->table_ressources = $ressources; if (isset($ressources) && !empty($ressources)) { $this->format_reponse = 'metaDonnees/champ'; } } } //------------------------------Fonction d'assemblage de la requete------------------------------------------------------ public function assemblerLaRequete() { $req = 'SELECT '.$this->requete_champ.' FROM '.Config::get('bdd_table_meta').$this->formerRequeteCondition(); return $req; } public function formerRequeteCondition() { $condition = ''; if ($this->requete_condition != null) { $condition = ' WHERE '.implode(' AND ', $this->requete_condition); } return $condition; } //--------------------------------------Fonction de formatage des resultats --------------------------------------------- public function retournerResultatFormate($resultat) { switch ($this->format_reponse) { case 'metaDonnees/champ' : $reponse = $this->formaterMetaDonneesChamp($resultat); break; case 'metaDonnees' : $reponse = $this->formaterMetaDonnees($resultat); break; default : break; } return $reponse; } //--------------------------------------Fonction de formatage des resultats de /metaDonnees/---------------------------- public function formaterMetaDonnees($resultat) { foreach ($resultat as $version) { foreach ($version as $key => $val) { if ($val != '') { $this->afficherDonnees($key, $val); } } if ($this->retour_format == 'max' && $this->version_projet == '*') { $this->table_retour['href'] = Config::get('url_service_base').Config::get('nom_projet') .'/'.$version['version'].'/'.$this->serviceNom; } $table[] = $this->table_retour; $this->table_retour = array(); } return $table; } public function afficherDonnees($key, $valeur) { if ($valeur != '') { $tab = array(); if ($this->retour_format == 'min') { if (in_array($key, array('editeur','createurs', 'contributeurs','couverture_spatiale','couverture_temporelle'))) { //Pour les données comprenant plusieurs infos (...=...,...=...;...) $tab = $this->recupererTableauResultat($valeur); $this->afficherConcatenationValeur($key, $tab); } else { $this->table_retour[$key] = trim($valeur); } } else { if (in_array($key, array('editeur','createurs', 'contributeurs','couverture_spatiale','couverture_temporelle','langue','langue_meta'))) { $tab = $this->recupererTableauResultat($valeur); $this->afficherConcatenationValeur($key, $tab); $this->afficherDonneesMax($key,$valeur,$tab); } else { $this->table_retour[$key] = trim($valeur); } } } } /** * Recupère à partir de la valeur du champ les différentes informations séparées par ';' (stocke ds un tableau) * pour éditeurs, créateurs, contributeurs,... * (ex : nom=Tela Botanica,guid=urn:lsid:tela-botanica.org,courriel=accueil@tela-botanica.org,... */ public function recupererTableauResultat($val) { $tab = array(); $num_entite = 0; // découpe chaque participant $tab_entites = explode(';', $val); foreach ($tab_entites as $entite) { $tab[$num_entite] = array(); if ($entite != '') { // découpe les informations du participant $entite_detail = explode(',', $entite); foreach ($entite_detail as $detail) { if ($detail != '') { if (preg_match('/^([^=]+)=([^=]*)$/', $detail, $match)) { $tab[$num_entite][$match[1]] = $match[2]; } else { $tab[$num_entite][] = $detail; } } } } $num_entite++; } return $tab; } /** Retourne : * - le nom de l'editeur * - les coordonnées de l'éditeur sous la forme [latitude]N,[longitude]S [datum] * - la couverture temporelle sous la forme xxxx à xxxx * - la concaténation des noms pour les contributeurs et les créateurs (machin chouette, truc bidule...) * - la liste des liste des couvertures spatiales (le nom et pas le code) (France, allemagne..) */ public function afficherConcatenationValeur($champ, $tab) { if (strrpos($champ, '.coordonnees') !== false) { if (isset($tab[0]['latitude']) && isset($tab[0]['longitude']) && isset($tab[0]['datum'])) { $this->table_retour[$champ] = $tab[0]['latitude'].' N, '.$tab[0]['longitude'].' S ['.$tab[0]['datum'].']'; } } else { $concat = ''; foreach ($tab as $entite) { foreach ($entite as $key => $val) { if ($champ == 'couverture_spatiale') { $concat .= ', '.$this->ajouterSignification($champ, $val); } else { if (strrpos($key, '.prenom') !== false) { $concat .= ', '.$val; } elseif (strrpos($key, 'nom') !== false) { $concat .= ' '.$val; break; } } } } $res = trim($concat, ','); $res = trim($res); if ($champ == 'couverture_temporelle') $res = str_replace(' ', ' à ',$res); $this->table_retour[$champ] = $res; } } public function afficherDonneesMax($champ,$valeur,$tab) { switch ($champ) { case 'couverture_temporelle' : $this->afficherInfosPrecises($champ, 'start,end', $valeur, $tab); break; case 'langue' : $this->afficherInfosPrecises($champ,'signification,code,href', $valeur); break; case 'langue_meta' : $this->afficherInfosPrecises($champ,'signification,code,href', $valeur); break; case 'couverture_spatiale' : $this->afficherInfosPrecises($champ, 'details', $valeur, $tab); break; case 'createurs' : $this->afficherInfosPrecises($champ, 'details', $valeur, $tab); break; case 'contributeurs' : $this->afficherInfosPrecises($champ, 'details', $valeur, $tab); break; case 'editeur' : $this->afficherEditeur($champ, $tab); break; default : $this->table_retour[$champ] = $valeur; break; } } public function afficherEditeur($key, $tab) { // infos générales sur l'éditeur foreach ($tab[0] as $k => $val) { if ((strrpos($k, 'contact.') === false) && (strrpos($k, '.wgs84') === false)) { $this->table_retour[$key.'.'.$k] = $val; } } //on récupère dans un premier temps les tableaux des coordonnées. $table_coordonnees = $this->recupererTableCoordonnees($tab); //on affiche les informations sur les coordonnees : concaténation + détails if ($table_coordonnees[0] != array()) { $this->afficherConcatenationValeur($key.'.coordonnees', $table_coordonnees); if (isset($table_coordonnees[0]['datum'])) { $this->afficherInfosPrecises($key.'.coordonnees.datum', 'signification,code,href',$table_coordonnees[0]['datum'], $table_coordonnees); } } $table_contact = $this->recupererTableContact($tab); //on affiche le premier contact en dehors de la table de détail: if ($table_contact[0] != array()) { $this->table_retour[$key.'.contact'] = ''; foreach ($table_contact as $info => $valeur) { $this->table_retour[$key.'.contact'] .= $valeur['contact.prenom']." ".$valeur['contact.nom']; } //on affiche les détails des autres contacts : $this->afficherTableDetails($key.'.contact', $table_contact); } } public function afficherInfosPrecises($champ, $pts, $val, $tab = null) { //permet d'afficher les informations précises telles que les .details, .start, .end... $pts = explode(',', $pts); foreach ($pts as $pt) { switch ($pt) { case 'start' : if (isset($this->table_retour[$champ.'.start'])) { $this->table_retour[$champ.'.start'] = $tab['start']; } break; case 'end' : if (isset($this->table_retour[$champ.'.end'])) { $this->table_retour[$champ.'.end'] = $tab['end']; } break; case 'code' : $this->table_retour[$champ.'.code'] = $val; break; case 'href' : $this->table_retour[$champ.'.href'] = $this->ajouterHrefAutreProjet($champ, '', $val); break; case 'signification' : $this->table_retour[$champ] = $this->ajouterSignification($champ, $val); break; case 'details' : if ($champ == 'couverture_spatiale') { $this->afficherCouvertureSpatiale($champ, $tab); } else { $this->afficherTableDetails($champ, $tab); } break; default : $this->table_retour[$champ.'.'.$pt] = $tab[$pt]; } } } public function afficherCouvertureSpatiale($key, $tab) { $res = $this->table_retour; $this->table_retour = array(); foreach ($tab as $iso) { foreach ($iso as $val) { $this->afficherInfosPrecises($key, 'signification,code,href',$val); $res[$key.'.detail'][] = $this->table_retour; $this->table_retour = array(); } } $this->table_retour = $res; } public function afficherTableDetails($champ, $tab) { $res = $this->table_retour; $this->table_retour = array(); foreach ($tab as $num_entite => $entite) { // $t et $type valent p ou o $t = ''; $type = '.'; foreach ($entite as $key => $infos) { list($type, $info) = explode('.', trim($key)); if ($type == 'contact') $type = 'p'; if ($type != $t) { // cherche et ajoute la signification du type $this->afficherInfosPrecises('type', 'signification,code,href', trim($type)); foreach ($this->table_retour as $k => $val) { $res[$champ.'.details'][$num_entite][$type.'.'.$k] = $val; } $table_retour = array(); $this->table_retour = array(); // rempli par afficherInfosPrecises $t = $type; } $res[$champ.'.details'][$num_entite][$key] = $infos; } } $this->table_retour = $res; } public function ajouterSignification($champ, $val, $nom = 'nom') { $url = $this->ajouterHrefAutreProjet($champ, '', $val); if (in_array($champ, array('langue', 'langue_meta', 'couverture_spatiale'))) { $url .= '/'.$nom; } if(array_key_exists($url, self::$cache_ontologies)) { return self::$cache_ontologies[$url]; } $signification = $this->consulterHref($url); if (isset($signification->$nom)) { $res = $signification->$nom; } else { $nom = 'nom.fr'; $res = $signification->$nom; } self::$cache_ontologies[$url] = $res; return $res ; } public function recupererTableContact(&$tab) { $res = array(); foreach ($tab[0] as $key => $val) { if (strrpos($key, 'contact.') !== false) { while (array_key_exists($key, $res)) { $key = ' '.$key; } $res[$key] = $val; unset($tab[0][$key]); //suppression des premiers contacts qui seront affichés après } } $resultat[0] = $res; return $resultat; } public function recupererTableCoordonnees(&$tab) { $res = array(); foreach ($tab[0] as $key => $val) { if (strrpos($key, 'latitude') !== false || strrpos($key, 'longitude') !== false) { list ($coord, $datum) = explode('.', $key); $res[$coord] = $val; $res['datum'] = $datum; } } $resultat[0] = $res; return $resultat; } //-------------------------------------Fonction de formatage des resultats de /metaDonnees/#champs+champs---------------- public function formaterMetaDonneesChamp($resultat) { $this->recupererNomChamp(Config::get('bdd_table_meta')); //On récupère dans un premier temps toutes les données existantes puis on pioche les champs recherchés $table_Meta = $this->formaterMetaDonnees($resultat); foreach ($table_Meta as $version) { //on affiche les informations par defaut : la version, la langue_meta et le guid : $this->afficherVersionLangueMetaGuid($version); $tab_ress = explode(' ', $this->table_ressources[0]); foreach ($tab_ress as $champ) {//on recupere le radical pour comparaison avec les nom des champs de la bdd : $this->afficherChampRecherche($champ, $version); } $table[] = $this->table_retour; $this->table_retour = array(); } return $table; } public function afficherChampRecherche(&$champ, &$version) { preg_match('/^([^.]+)(?:[.][^.]+)?$/', $champ, $match); if (preg_match('/(.+)[.][*]$/', $champ, $match_2)) { $this->afficherPointEtoile($match_2, $version, $champ); } elseif (array_key_exists($champ, $version)) { $this->table_retour[$champ] = $version[$champ]; } elseif (in_array($match[1], $this->champs_table)) { //si le champ est vide dans cette version on retourne null (comparaison avec les champs existants) $this->table_retour[$champ] = null; } else { $champs = implode('
  • ', array_keys($version)); $e = 'Erreur dans votre requête :
    Le champ "'.$champ.'" n\'existe pas'. '. Les champs disponibles sont :
  • '.$champs.'
  • '; $this->renvoyerErreur(RestServeur::HTTP_CODE_MAUVAISE_REQUETE, $e); } } public function afficherPointEtoile($match, $version, $ressource) { $existe = false; foreach ($version as $key => $valeur) { if (strrpos($key, $match[1].'.') !== false) { $this->table_retour[$key] = $valeur; $existe = true; } } if (!$existe) { $champs = implode('
  • ', array_keys($version)); $e = 'Erreur dans votre requête :
    Le champ " '.$ressource.' " n\'existe pas dans la version ' .$version['version'].'. Les champs disponibles sont :
  • '.$champs.'
  • '; $this->renvoyerErreur(RestServeur::HTTP_CODE_MAUVAISE_REQUETE, $e); } } public function afficherVersionLangueMetaGuid(&$version) { $this->table_retour['version'] = $version['version']; $this->table_retour['langue_meta'] = $version['langue_meta']; $this->table_retour['guid'] = $version['guid']; } }