* @author Jean-Pascal MILCENT * @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 $Id$ * @copyright 2010 Tela-Botanica */ class Recherche extends Ref { /** * Méthode principale appelée avec une requête de type GET. * Elle sert d'aiguilleur pour appeller la méthode correspondant au type de recherche passé en paramêtre. */ public function getElement($param = array()) { // Initialisation des variables $info = array(); // Nous recherchons le type de requête demandé $type = $param[0]; $methode = 'getElement'.$type; if (method_exists($this, $methode)) { array_shift($param); $info = $this->$methode($param); } else { $this->messages[] = "Le type de recherche demandé '$type' n'est pas disponible."; } // Envoie sur la sortie standard $this->envoyer($info); } /* Méthode pour récupérer le nombre de taxons répondant à la requête * Appelée avec les paramètres d'url suivant : * /Recherche/Nombre/_ * ou les _ représentent dans l'ordre : référentiel, mots, paramétres avancés * Si un des paramètres est absent, il prendre la valeur * */ public function getElementNombre($param) { // Initialisation des variables $info = array(); // Pré traitement des paramètres $p = $this->pretraiterParametresUrl($param); $referentiel = substr($p['ref'], 2, -2); // Construction de la requête // Il est important de compter le nombre de taxons pour l'affichage $requete = (($this->distinct) ? 'SELECT DISTINCT' : 'SELECT').' COUNT(num_nom) AS nbre FROM '.$referentiel. $this->construireWhere($p, $referentiel).' '; // Récupération des résultats try { $donnees = $this->bdd->query($requete)->fetch(PDO::FETCH_ASSOC); if ($donnees === false) { $this->messages[] = "La requête a retourné aucun résultat : $requete"; } else { $info = $donnees['nbre']; } } catch (PDOException $e) { $this->messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage()).$requete; } return $info; } /* Méthode pour récupérer une liste de taxons * Appelée avec les paramêtres d'url suivant : * /Recherche/ParDefaut/_ * ou les _ représentent dans l'ordre : référentiel, mots, paramétres avancés * Si un des paramètres est absent, il prendre la valeur * */ public function getElementParDefaut($param) { // Initialisation des variables $info = array(); // Pré traitement des paramètres $p = $this->pretraiterParametresUrl($param); $referentiel = substr($p['ref'], 2, -2); // Construction de la requête $requete = (($this->distinct) ? 'SELECT DISTINCT' : 'SELECT').' num_nom, nom_sci, auteur, annee, '. ' biblio_origine, nom_addendum, num_nom_retenu, presence, exclure_taxref'. ' FROM '.$referentiel.$this->construireWhere($p, $referentiel). ' ORDER BY '.((!is_null($this->orderby)) ? $this->orderby : 'nom_sci ASC').' '. " LIMIT $this->start, $this->limit "; // Récupération des résultats try { $donnees = $this->bdd->query($requete)->fetchAll(PDO::FETCH_ASSOC); if ($donnees === false) { $this->messages[] = "La requête a retourné aucun résultat : $requete"; } else { $info = $donnees; } } catch (PDOException $e) { $this->messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage()).$requete; } return $info; } /* Méthode pour récupérer le nombre de taxons répondant à une requête sur la synonymie * Appelée avec les paramètres d'url suivant : * /Recherche/Nombre/_ * ou les _ représentent dans l'ordre : référentiel, mots, paramétres avancés * Si un des paramètres est absent, il prendre la valeur * */ public function getElementNombreTaxon($param) { // Initialisation des variables $info = array(); // Pré traitement des paramètres $p = $this->pretraiterParametresUrl($param); $referentiel = substr($p['ref'], 2, -2); // Construction de la requête // Il est important de compter le nombre de taxons pour l'affichage $requete = 'SELECT count(DISTINCT num_nom_retenu) as nbr FROM '.$referentiel.$this->construireWhere($p, $referentiel).';'; // Récupération des résultats try { $donnees = $this->bdd->query($requete)->fetch(PDO::FETCH_ASSOC); if ($donnees === false) { $this->messages[] = "La requête a retourné aucun résultat."; } else { $info = $donnees['nbr']; } } catch (PDOException $e) { $this->messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage()); } return $info; } /* Méthode pour récupérer une liste de taxons * Appelée avec les paramêtres d'url suivant : * /Recherche/ParDefaut/_ * ou les _ représentent dans l'ordre : référentiel, mots, paramétres avancés * Si un des paramètres est absent, il prendre la valeur * */ public function getElementParTaxon($param) { // Initialisation des variables $info = ''; // Pré traitement des paramètres $p = $this->pretraiterParametresUrl($param); $referentiel = substr($p['ref'], 2, -2); $liste_nom = $this->getNomRetenu($param); if ($liste_nom != '') { // Construction de la requête // si recherche des synonymes $requete = (($this->distinct) ? 'SELECT DISTINCT' : 'SELECT').' num_nom, nom_sci, auteur, annee, '. 'biblio_origine, nom_addendum, num_nom_retenu, num_basionyme, synonyme_mal_applique, presence, exclure_taxref '. ' FROM '.$referentiel.' WHERE num_nom_retenu IN ('.$liste_nom.') '. 'ORDER BY nom_sci ASC '; try { $donnees = $this->bdd->query($requete)->fetchAll(PDO::FETCH_ASSOC); $info = $donnees; } catch (PDOException $e) { $this->messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage()); } } return $info; } /* Méthode pour récupérer une liste de taxons * Appelée avec les paramêtres d'url suivant : * /Recherche/ParDefaut/_ * ou les _ représentent dans l'ordre : référentiel, mots, paramétres avancés * Si un des paramètres est absent, il prendre la valeur * */ public function getElementNombreSynonymeParTaxon($param) { // Initialisation des variables $info = ''; // Pré traitement des paramètres $p = $this->pretraiterParametresUrl($param); $referentiel = substr($p['ref'], 2, -2); $liste_nom = $this->getNomRetenu($param); if ($liste_nom != '') { // Construction de la requête // si recherche des synonymes $requete = (($this->distinct) ? 'SELECT DISTINCT' : 'SELECT').' COUNT(num_nom) as nbr, num_nom_retenu '. 'FROM '.$referentiel.' WHERE num_nom_retenu IN ('.$liste_nom.') GROUP BY num_nom_retenu '. 'ORDER BY nom_sci ASC '; try { $donnees = $this->bdd->query($requete)->fetchAll(PDO::FETCH_ASSOC); foreach($donnees as $ligne) { $info[$ligne['num_nom_retenu']] = $ligne['nbr']; } } catch (PDOException $e) { $this->messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage()); } } return $info; } /** * Récupérer le nombre de taxons d'une classifiation (infra ou supra) * Appelée avec les paramètres d'url suivant : * /Recherche/NombreClassif/_ * ou les _ représentent dans l'ordre : référentiel, mots, paramétres avancés * Si un des paramètres est absent, il prendre la valeur * */ public function getElementNombreClassif($param) { // Initialisation des variables $info = array(); // Pré traitement des paramètres $p = $this->pretraiterParametresUrl($param); $referentiel = substr($p['ref'], 2, -2); $requete = ''; if (isset($p['classif'])) { if (!isset($p['nn'])) { $p['rg'] = 180; } if ($p['classif'] == 'infra') { $requete = 'SELECT COUNT(num_nom) as nbr '. 'FROM '.$referentiel.' '. 'WHERE num_tax_sup IN '. '(SELECT num_nom '. 'FROM '.$referentiel.$this->construireWhere($p, $referentiel).') '; } else { $requete = 'SELECT count(distinct num_tax_sup) as nbr '. 'FROM '.$referentiel.$this->construireWhere($p, $referentiel).' '; } } else { // Construction de la requête // Il est important de compter le nombre de taxons pour l'affichage $requete = 'SELECT count(DISTINCT num_nom_retenu) as nbr FROM '.$referentiel.$this->construireWhere($p, $referentiel).';'; } // Récupération des résultats try { $donnees = $this->bdd->query($requete)->fetch(PDO::FETCH_ASSOC); if ($donnees === false) { $this->messages[] = "La requête a retourné aucun résultat."; } else { $info = $donnees['nbr']; } } catch (PDOException $e) { $this->messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage()); } return $info; } /** * Récupérer le nombre de taxons d'une classifiation (infra ou supra) * Appelée avec les paramètres d'url suivant : * /Recherche/NombreClassif/_ * ou les _ représentent dans l'ordre : référentiel, mots, paramétres avancés * Si un des paramètres est absent, il prendre la valeur * */ public function getElementNombreClassifParTaxon($param) { // Initialisation des variables $info = array(); // Pré traitement des paramètres $p = $this->pretraiterParametresUrl($param); $referentiel = substr($p['ref'], 2, -2); $requete = ''; if (isset($p['classif'])) { if (!isset($p['nn'])) { $p['rg'] = 180; } if ($p['classif'] == 'infra') { $requete = 'SELECT COUNT(num_nom) as nbr, num_tax_sup '. 'FROM '.$referentiel.' '. 'WHERE num_tax_sup IN '. '(SELECT num_nom '. 'FROM '.$referentiel.$this->construireWhere($p, $referentiel).') GROUP BY num_tax_sup'; } else { $requete = 'SELECT count(distinct num_tax_sup) as nbr, num_tax_sup '. 'FROM '.$referentiel.$this->construireWhere($p, $referentiel).' GROUP BY num_tax_sup'; } } else { // Construction de la requête // Il est important de compter le nombre de taxons pour l'affichage $requete = 'SELECT count(DISTINCT num_nom_retenu) as nbr, num_tax_sup FROM '.$referentiel.$this->construireWhere($p, $referentiel).' GROUP BY num_tax_sup;'; } // Récupération des résultats try { $donnees = $this->bdd->query($requete)->fetchAll(PDO::FETCH_ASSOC); if ($donnees === false) { $this->messages[] = "La requête a retourné aucun résultat."; } else { foreach($donnees as $ligne) { $info[$ligne['num_tax_sup']] = $ligne['nbr']; } } } catch (PDOException $e) { $this->messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage()); } return $info; } /** * Récupérer la classification d'un taxon donné (ses enfants ou parents) * Appelée avec les paramêtres d'url suivant : * /Recherche/Hierarchie/_ * ou les _ représentent dans l'ordre : référentiel, mots, paramétres avancés (dont classif est le sens de la requête infra ou supra) * Si un des paramètres est absent, il prendre la valeur * */ public function getElementClassification($param) { $resultats = array(); try { $p = $this->pretraiterParametresUrl($param); $referentiel = substr($p['ref'], 2, -2); $classif = $p['classif']; //Si on ne recherche pas sur un numéro taxonomique, on veut ne trouver que les familles if (!isset($p['nn'])) { $p['rg'] = 180; } // Récupérer les informations du nom sélectionné $requete = (($this->distinct) ? 'SELECT DISTINCT' : 'SELECT'). ' num_nom, nom_sci, auteur, annee, biblio_origine, nom_addendum,'. ' num_nom_retenu, presence, exclure_taxref, num_tax_sup'. ' FROM '.$referentiel.$this->construireWhere($p, $referentiel). ' ORDER BY '.((!is_null($this->orderby)) ? $this->orderby : 'nom_sci ASC'); $donnees = $this->bdd->query($requete)->fetchAll(PDO::FETCH_ASSOC); if ($donnees === false) { $this->messages[] = "La requête a retourné aucun résultat : $requete"; } else { if ($classif == 'infra') { $resultats = $this->trouverInfra($referentiel, $donnees); } else { $resultats = $this->trouverSupra($referentiel, $donnees); } } } catch (PDOException $e) { $this->messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage()).$requete; } return $resultats; } /** * Parcourir les données passées en paramètre pour trouver les taxons inférieurs * @param $referentiel String le référentiel pour la requête * @param $donnees Array un tableau de résultats contenant des lignes taxons * @return un tableau de résultats contenant les taxons inférieurs * */ public function trouverInfra($referentiel, $donnees) { $resultats = array(); foreach ($donnees as $taxon) { $donneesInfras = array(); $requete = 'SELECT DISTINCT '. ' num_nom, nom_sci, auteur, annee, biblio_origine, nom_addendum,'. ' num_nom_retenu, presence, exclure_taxref'. ' FROM '.$referentiel. ' WHERE num_tax_sup = '.$taxon['num_nom'].' '. ' ORDER BY '.((!is_null($this->orderby)) ? $this->orderby : 'nom_sci ASC').' '. "LIMIT $this->start, $this->limit "; $donneesInfras = $this->bdd->query($requete)->fetchAll(PDO::FETCH_ASSOC); if ($donneesInfras !== false) { $resultats = array_merge($resultats, $donneesInfras); } } return $resultats; } /** * Parcourir les données passées en paramètre pour trouver les taxons supérieurs * @param $referentiel String le référentiel pour la requête * @param $donnees Array un tableau de résultats contenant des lignes taxons * @return un tableau de résultats contenant les taxons supérieurs * */ public function trouverSupra($referentiel, $donnees) { $resultats = array(); $numNomSup = array(); foreach ($donnees as $taxon) { $numNomSup[] = $taxon['num_tax_sup']; } // Récupérer les taxons supérieurs : $requete = 'SELECT DISTINCT '. ' num_nom, nom_sci, auteur, annee, biblio_origine, nom_addendum,'. ' num_nom_retenu, presence, exclure_taxref, num_tax_sup'. ' FROM '.$referentiel. ' WHERE num_nom IN ('.implode(',', $numNomSup).') '. ' ORDER BY '.((!is_null($this->orderby)) ? $this->orderby : 'nom_sci ASC').' '. "LIMIT $this->start, $this->limit "; $donneesSupras = $this->bdd->query($requete)->fetchAll(PDO::FETCH_ASSOC); if ($donneesSupras !== false) { $resultats = $donneesSupras; } return $resultats; } /* Méthode pour récupérer une liste de noms retenus */ public function getNomRetenu($param) { // Initialisation des variables $info = array(); // Pré traitement des paramètres $p = $this->pretraiterParametresUrl($param); $referentiel = substr($p['ref'], 2, -2); // Construction de la requête // si recherche des synonymes $requete_nom_retenu = 'SELECT DISTINCT num_nom_retenu FROM '.$referentiel.$this->construireWhere($p, $referentiel) ." ORDER BY nom_sci ASC LIMIT $this->start, $this->limit ".';'; try { $info = ''; $donnees_nom_retenu = $this->bdd->query($requete_nom_retenu)->fetchAll(PDO::FETCH_ASSOC); if ($donnees_nom_retenu === false) { $this->messages[] = "La requête n'a retourné aucun résultat."; } else { $liste_nom = ''; foreach ($donnees_nom_retenu as $donnees_nom) { if ($donnees_nom['num_nom_retenu'] != '') { $liste_nom .= (!empty($liste_nom) ? ', ' : '').'"'.$donnees_nom['num_nom_retenu'].'"'; } } $info = $liste_nom; } } catch (PDOException $e) { $this->messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage()); } return $info; } private function pretraiterParametresUrl($param) { // Tableau des paramètres qui peuvent être passés dans l'url $params_passes = array('ref' => 'str', 'mots' => 'str', 'sg' => 'str_exact', 'gen' => 'str_exact', 'sp' => 'str_exact', 'ssp' => 'str_exact', 'au' => 'str', 'an' => 'str', 'nn' => 'int', 'bib' => 'str', 'nr' => 'bool', 'tax' => 'bool', 'pre' => 'bool', 'taxref' => 'bool', 'classif' => '', 'rg' => 'int'); $p = $this->traiterParametresUrl(array_keys($params_passes), $param, false); //$this->debug[] = $param; foreach ($params_passes as $param_passe => $type) { if (isset($p[$param_passe])) { // Suppression des éventuels espaces en début et fin de chaine $valeur = trim($p[$param_passe]); // Type de paramètre chaine if ($type == 'str') { // Suppression des slash $valeur = stripslashes($valeur); // Utilisation d'une recherche de chaîne if (preg_match('/^"(.*)"$/', $valeur, $match)) { $valeur = '%'.$match[1].'%'; } elseif ($valeur == "#") { }else{ // Recherche de mots non liés $mots = explode(' ', $valeur); $valeur = '%'.implode ('%', $mots).'%'; } // Mise en place des quotes pour l'interrogation dans la bdd $valeur = $this->bdd->quote($valeur); } // Type de paramètre chaine exacte if ($type == 'str_exact') { // Suppression des slash $valeur = stripslashes($valeur); // Utilisation d'une recherche de chaîne exacte if (preg_match('/^"(.*)"$/', $valeur, $match)) { $valeur = $match[1]; } else { // Recherche de mots non liés $mots = explode(' ', $valeur); $valeur = implode (' ', $mots); } // Mise en place des quotes pour l'interrogation dans la bdd $valeur = $this->bdd->quote($valeur); } // Type de paramètre booléen if ($type == 'bool') { if (preg_match('/^[0]$/', $valeur)) { $valeur = false; } else if (preg_match('/^[1]$/', $valeur)) { $valeur = true; } else { $this->messages[] = "Le paramètre '$param_passe' attend une valeur de type 0 ou 1 et non '$valeur'."; $valeur = null; } } // Type de paramètre entier if ($type == 'int') { if (!preg_match('/^(?:[0-9]+,\s*)*[0-9]+$/', $valeur)) { $this->messages[] = "Le paramètre '$param_passe' attend une ou plusieurs valeurs de type entiers ". "séparés par des virgules et non '$valeur'."; $valeur = null; } } $p[$param_passe] = $valeur; } } return $p; } private function construireWhere($p, $referentiel) { // Initialisation de variables $where = ' WHERE '; // Construire where en fonction des paramêtres if (isset($p['mots'])) { if (stripos($p['mots'], "#") == 1) { $where .= " 1 "; } else { $where .= 'AND ('. " num_nom LIKE {$p['mots']} ". " OR num_nom_retenu LIKE {$p['mots']} ". " OR num_tax_sup LIKE {$p['mots']} ". " OR rang LIKE {$p['mots']} ". " OR nom_sci LIKE {$p['mots']} ". " OR nom_supra_generique LIKE {$p['mots']} ". " OR genre LIKE {$p['mots']} ". " OR epithete_infra_generique LIKE {$p['mots']} ". " OR epithete_sp LIKE {$p['mots']} ". " OR type_epithete LIKE {$p['mots']} ". " OR epithete_infra_sp LIKE {$p['mots']} ". " OR cultivar_groupe LIKE {$p['mots']} ". " OR cultivar LIKE {$p['mots']} ". " OR nom_commercial LIKE {$p['mots']} ". " OR auteur LIKE {$p['mots']} ". " OR annee LIKE {$p['mots']} ". " OR biblio_origine LIKE {$p['mots']} ". " OR notes LIKE {$p['mots']} ". " OR nom_addendum LIKE {$p['mots']} ". " OR homonyme LIKE {$p['mots']} ". " OR synonyme_proparte LIKE {$p['mots']} ". " OR synonyme_douteux LIKE {$p['mots']} ". " OR synonyme_mal_applique LIKE {$p['mots']} ". " OR synonyme_orthographique LIKE {$p['mots']} ". " OR hybride_parent_01 LIKE {$p['mots']} ". " OR hybride_parent_01_notes LIKE {$p['mots']} ". " OR hybride_parent_02 LIKE {$p['mots']} ". " OR hybride_parent_02_notes LIKE {$p['mots']} ". " OR nom_francais LIKE {$p['mots']} ". " OR presence LIKE {$p['mots']} ". " OR statut_origine LIKE {$p['mots']} ". " OR statut_introduction LIKE {$p['mots']} ". " OR statut_culture LIKE {$p['mots']} ". " OR num_basionyme LIKE {$p['mots']}) "; } } if (isset($p['sg'])) { $where .= "AND nom_supra_generique LIKE {$p['sg']} "; } if (isset($p['gen'])) { $where .= "AND genre LIKE ({$p['gen']}) "; } if (isset($p['sp'])) { $where .= "AND epithete_sp LIKE {$p['sp']} "; } if (isset($p['ssp'])) { $where .= "AND epithete_infra_sp LIKE {$p['ssp']} "; } if (isset($p['au'])) { $where .= "AND auteur LIKE {$p['au']} "; } if (isset($p['an'])) { $where .= "AND annee LIKE ({$p['an']}) "; } if (isset($p['nn'])) { $where .= "AND num_nom IN ({$p['nn']}) "; } if (isset($p['bib'])) { $where .= "AND biblio_origine LIKE ({$p['bib']}) "; } if (isset($p['nr']) && $p['nr'] == true) { $where .= "AND num_nom_retenu = num_nom "; } if (isset($p['pre']) && $p['pre'] == true) { $where .= "AND presence NOT IN ('A', '') "; } elseif(isset($p['pre']) && $p['pre'] != true) { $where .= "AND presence IN ('A', '') "; } if (isset($p['taxref'])) { $where .= "AND exclure_taxref ="; $where .= ($p['taxref'] == true) ? " 0 " : " 1 "; } if (isset($p['rg'])) { $where .= "AND rang = $p[rg] "; } $where = str_replace('WHERE AND', ' WHERE ', $where); // Retour du Where associé if (count($p) == 1) { $where = ""; } return $where; } } ?>