* @author Raphaël Droz * @author Jean-Pascal MILCENT * @author Aurelien PERONNET * @license GPL v3 * @license CECILL v2 * @copyright 1999-2014 Tela Botanica */ class GestionChampsEtendus extends Cel { private $mode = null; private $table_champs_etendus = null; private $champ_id = null; public function GestionChampsEtendus($config, $mode) { parent::__construct($config); $this->mode = $mode; if ($this->mode == 'obs') { $this->mode = 'obs'; $this->table_champs_etendus = 'cel_obs_etendues'; $this->champ_id = 'id_observation'; } else if ($this->mode == 'image') { $this->mode = 'image'; $this->table_champs_etendus = 'cel_images_etendues'; $this->champ_id = 'id_image'; } else { throw new Exception('Mode inconnu, les modes autorisés sont "obs" et "image"'); } } /** * Renvoie true ou false suivant que l'element indiqué possède une valeur * pour la clé indiquée * * @param int $id_element_lie * @param string $cle * @param string $valeur * @return bool */ public function existe($id_element_lie, $cle) { $id = Cel::db()->proteger($id_element_lie); $cle = Cel::db()->proteger($cle); $requete = 'SELECT COUNT(*) >= 1 AS existe '. "FROM {$this->table_champs_etendus} ". "WHERE {$this->champ_id} = $id ". " AND cle = $cle ". ' -- '.__FILE__.':'.__LINE__;; $resultat = Cel::db()->requeter($requete); return ($resultat[0]['existe'] == '1'); } /** * Renvoie tous les champs étendus associé à l'élément passé en paramètre * * @param int $id_element_lie * @return array tableau associatif des champs de la table etendu */ public function consulter($id_element_lie) { $id = Cel::db()->proteger($id_element_lie); $requete = 'SELECT * '. "FROM {$this->table_champs_etendus} ". "WHERE {$this->champ_id} = $id ". ' -- '.__FILE__.':'.__LINE__; $resultat = Cel::db()->requeter($requete); return $resultat; } /** * Renvoie tous les champs étendus associés aux éléments passés en paramètre. * Retour sous forme de tableau associatif de tableau d'objets ChampEtendu. * Les objets ChampEtendu sont regroupés par id d'élement. * * @param array $ids_element_lies tableau d'id des éléments liés (obs ou image). * @return array tableau associatif de tableau d'objets ChampEtendu. */ public function consulterParLots(Array $ids_element_lies) { $champs_etendus_par_element = array(); if (!empty($ids_element_lies)) { $ids_element_lies = array_map(array(Cel::db(), 'proteger'),$ids_element_lies); $ids = implode(',', $ids_element_lies); $requete = "SELECT * FROM {$this->table_champs_etendus} WHERE {$this->champ_id} IN ($ids) "; $resultats = Cel::db()->requeter($requete); foreach ($resultats as &$ligne) { $id_element = $ligne[$this->champ_id]; if (!isset($champs_etendus_par_element[$id_element])) { $champs_etendus_par_element[$id_element] = array(); } $champ_etendu = new ChampEtendu(); $champ_etendu->id = $id_element; $champ_etendu->cle = $ligne['cle']; $champ_etendu->valeur = $ligne['valeur']; $champs_etendus_par_element[$id_element][] = $champ_etendu; } } return $champs_etendus_par_element; } /** * Ajoute un champ étendu. * Si la clé existe déjà, seule valeur du champ est mise à jour * * @param ChampEtendu $champ_etendu * @return bool true si l'ajout a eu lieu */ public function ajouter(ChampEtendu $champ_etendu) { $id = Cel::db()->proteger($champ_etendu->id); $cle = Cel::db()->proteger($champ_etendu->cle); $valeur = Cel::db()->proteger($champ_etendu->valeur); $requete = "INSERT INTO {$this->table_champs_etendus} ". "( {$this->champ_id}, cle, valeur) ". "VALUES ($id, $cle, $valeur) ". "ON DUPLICATE KEY UPDATE valeur = VALUES(valeur) ". ' -- '.__FILE__.':'.__LINE__; // la partie on duplicate key est spécifique mysql mais il sera facile de s'en passer le jour // où l'on change de sgbd $ajout = Cel::db()->executer($requete); return ($ajout !== false); } /** * Ajoute plusieurs champs étendus à la fois. * Si la clé existe déjà, seule la valeur du champ est mise à jour * * @param array $champs_etendus tableau d'objets ChampEtendu * @return bool true si l'ajout a eu lieu */ public function ajouterParLots(Array $champs_etendus) { if (! $champs_etendus) return TRUE; // le tableau ... vide à été inséré $lignes = array(); foreach ($champs_etendus as $champ_etendu) { $id = Cel::db()->proteger($champ_etendu->id); $cle = Cel::db()->proteger($champ_etendu->cle); $valeur = Cel::db()->proteger($champ_etendu->valeur); $lignes[] = "($id, $cle, $valeur)"; } // la partie on duplicate key est spécifique mysql mais il sera facile de s'en passer le jour // où l'on change de sgbd $ajout = Cel::db()->executer(sprintf( "INSERT INTO %s (%s, cle, valeur) VALUES %s ON DUPLICATE KEY UPDATE valeur = VALUES(valeur) -- %s:%d", $this->table_champs_etendus, $this->champ_id, implode(',', $lignes), __FILE__, __LINE__)); return ($ajout !== false); } /** * Modifie un champ étendu associé à l'élément passé en paramètre * * @param ChampEtendu $champ_etendu * @return bool true si la modification a eu lieu */ public function modifier(ChampEtendu $champ_etendu) { $id = Cel::db()->proteger($champ_etendu->id); $cle = Cel::db()->proteger($champ_etendu->cle); $valeur = Cel::db()->proteger($champ_etendu->valeur); $requete = "UPDATE {$this->table_champs_etendus} ". "SET valeur = $valeur ". "WHERE cle = $cle". " AND {$this->champ_id} = $id ". ' -- '.__FILE__.':'.__LINE__; $modif = Cel::db()->executer($requete); return ($modif !== false); } /** * Supprime le champ champ étendu associé à l'élément et au nom de clé passés en paramètre * * @param int $id_element_lie * @param string $cle * @return bool */ public function supprimer($id_element_lie, $cle) { $id = Cel::db()->proteger($id_element_lie); $cle = Cel::db()->proteger($cle); $requete = "DELETE FROM {$this->table_champs_etendus} ". "WHERE cle = $cle ". "AND {$this->champ_id} = $id ". ' -- '.__FILE__.':'.__LINE__; $suppr = Cel::db()->executer($requete); return ($suppr !== false); } /** * Supprime tous les champs champ étendu associés à l'élément passés en paramètre * * @param int $id_element_lie * @return bool */ public function vider($id_element_lie) { $id = Cel::db()->proteger($id_element_lie); $requete = "DELETE FROM {$this->table_champs_etendus} ". "WHERE {$this->champ_id} = $id ". ' -- '.__FILE__.':'.__LINE__; $suppr = Cel::db()->executer($requete); return ($suppr !== false); } /** * Supprime tous les champs champ étendu associés aux éléments passés en paramètre * * @param array $ids_elements_lies * @return bool */ public function viderParLots($ids_elements_lies) { $ids = $this->protegerTableau($ids_elements_lies); $requete = "DELETE FROM {$this->table_champs_etendus} ". "WHERE {$this->champ_id} IN (".implode(',',$ids).") ". ' -- '.__FILE__.':'.__LINE__; $suppr = Cel::db()->executer($requete); return ($suppr !== false); } /** * Revnoie tous les intitules aux éléments passés en paramètre * * @param array $ids_elements_lies * @return bool */ public function consulterClesParLots($ids_elements_lies) { $cles_fmt = array(); if(!empty($ids_elements_lies)) { $ids = $this->protegerTableau($ids_elements_lies); $requete = 'SELECT cle '. "FROM {$this->table_champs_etendus} ". "WHERE {$this->champ_id} IN (".implode(',',$ids).") ". ' -- '.__FILE__.':'.__LINE__; $cles = Cel::db()->requeter($requete); $i = 0; foreach($cles as &$cle) { $cles_fmt[$cle['cle']] = $i++; } } return array_values(array_flip($cles_fmt)); } /** * Renvoie la liste des groupes de champs étendus */ public function consulterGroupesChampsEtendusPredefinis() { $groupes = array(); $requete = "SELECT cc.cle as cle_groupe, cc.label as nom_groupe, ccc.cle as cle_champ, ccc.label as label_champ, ccc.invisible, ccc.prive ". "FROM `cel_catalogue_champs_etendus` cc ". "INNER JOIN cel_catalogue_champs_etendus_liaison cl ON cc.cle = cl.groupe ". "INNER JOIN cel_catalogue_champs_etendus ccc ON ccc.cle = cl.champ ". ' -- '.__FILE__.':'.__LINE__; $groupes_champs = Cel::db()->executerRequete($requete); $cle_groupe = ''; $infos_groupe = null; foreach ($groupes_champs as $groupe_champ) { // les champs sont ordonnés par groupe, ce qui permet de les assembler // séquentiellement en créeant un nouveau groupe lorsque la clé // de groupe du champ actuel est différénte de la précédente if ($cle_groupe != $groupe_champ['cle_groupe']) { if($infos_groupe != null) { $groupes[] = $infos_groupe; } $infos_groupe = array(); $cle_groupe = $groupe_champ['cle_groupe']; } if (empty($infos_groupe)) { $infos_groupe = array( 'cle' => $groupe_champ['cle_groupe'], 'nom' => $groupe_champ['nom_groupe'], 'champs' => array() ); } $infos_groupe['champs'][] = array( 'cle' => $groupe_champ['cle_champ'], 'label' => $groupe_champ['label_champ'], 'options' => array( 'invisible' => $groupe_champ['invisible'], 'prive' => $groupe_champ['prive']) ); } // Ajout du dernier groupe, qui serait ignoré sinon, étant donné que l'ajout // au tableau se fait au début de la boucle //TODO: voir si on ne peut pas simplifier ça if (!empty($infos_groupe)) { $groupes[] = $infos_groupe; } return $groupes; } /** * Renvoie le catalogue des champs étendus */ public function consulterCatalogueChampsEtendusPredefinis($ordonner_par_cle = false) { $requete = 'SELECT cle, label, invisible, prive '. 'FROM cel_catalogue_champs_etendus AS cc '. ' -- '.__FILE__.':'.__LINE__; $catalogue = Cel::db()->executerRequete($requete); $infos_champs = array(); foreach ($catalogue as $champ) { $champ_fmt = array( 'cle' => $champ['cle'], 'label' => $champ['label'], 'options' => array( 'invisible' => $champ['invisible'], 'prive' => $champ['prive']) ); if ($ordonner_par_cle) { $infos_champs[$champ_fmt['cle']] = $champ_fmt; } else { $infos_champs[] = $champ_fmt; } } return $infos_champs; } /** * Transforme un label en clé. * Supprime tous les accents et caractères spéciaux. * Accole les mots pour créer un chatmot. * * @param string le label. * @return string la clé correspondante */ public function transformerLabelEnCle($label) { //TODO: cette fonction est elle encore pertinente // maintenant que la notion de label est supprimée ? $cle = strtolower(trim($label)); // Suppression des mots inutiles $mots_a_remplacer = array(' le ', ' la ', ' les ', ' des ', ' de ', " l'", " d'", ' à ', ' au '); $cle = str_replace($mots_a_remplacer, ' ', $cle); // Remplacement parenthèses et crochets et leurs contenus $cle = preg_replace('/\([^)]+\)/', '', $cle); $cle = preg_replace('/\[[^\]]+\]/', '', $cle); // Remplacement des accents (voir : http://www.weirdog.com/blog/php/supprimer-les-accents-des-caracteres-accentues.html ) $cle = htmlentities($cle, ENT_NOQUOTES, 'utf-8'); $cle = preg_replace('/&([A-za-z])(?:acute|cedil|circ|grave|orn|ring|slash|th|tilde|uml);/', '\1', $cle); $cle = preg_replace('/&([A-za-z]{2})(?:lig);/', '\1', $cle); // pour les ligatures e.g. 'œ' $cle = preg_replace('/&[^;]+;/', '', $cle); // supprime les autres caractères // Suppression définitive de tout ce qui n'est pas ASCII $cle = preg_replace('/[^a-zA-Z0-9 ]/', ' ', $cle); $cle = preg_replace('/\s+/', ' ', $cle); // Accollement des mots $cle = ucwords($cle); $cle = str_replace(' ', '', $cle); $cle{0} = strtolower($cle{0}); return $cle; } }