Rev 2061 | Rev 2086 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php/*** @package jrest* @author Aurélien Peronnet <aurelien@tela-botania.org>* @copyright 2010, 2013 Tela-Botanica* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL** Librairie de liaison d'images et d'observation à des mots clés en utilisant la méthode* path enumeration*/class GestionMotsClesChemin {private $config;private $mode;private $table_liaison;private $table_mots_cles;//TODO: trigger pour les tables liaisonspublic function GestionMotsClesChemin($config, $mode = 'obs') {$this->config = $config;//TODO: switch suivant mode$this->mode = $mode;list($this->table_liaison, $this->table_mots_cles) = self::getTablesMotsClesEtLiaisons($mode);}public function obtenirArbre($id_utilisateur, $chemin = "/") {$requete = "SELECT * FROM ".$this->table_mots_cles." "."WHERE id_utilisateur = ".Cel::db()->proteger($id_utilisateur)." AND "."chemin LIKE ".Cel::db()->proteger($chemin."%")." "."ORDER BY chemin";$arbre = Cel::db()->requeter($requete.' -- '.__FILE__.':'.__LINE__);usort($arbre, array('GestionMotsClesChemin', 'comparerProfNoeuds'));return $arbre;}public function obtenirIdsMotsClesParIdParent($id_utilisateur, $id_mot_cle) {$requete = "SELECT id_mot_cle FROM ".$this->table_mots_cles." "."WHERE chemin LIKE CONCAT("."(SELECT chemin FROM ".$this->table_mots_cles." "."WHERE id_mot_cle = ".Cel::db()->proteger($id_mot_cle)."), "."'%')";$ids_enfants = Cel::db()->executerRequete($requete.' -- '.__FILE__.':'.__LINE__);return $ids_enfants;}public function insererParCheminSiInexistant($mot_cle, $chemin_parent, $id_utilisateur) {$chemin_mot_cle = self::getCheminHarmonise($chemin_parent, $mot_cle);$requete_mot_cle_existe = "SELECT id_mot_cle FROM ".$this->table_mots_cles." "."WHERE chemin = ".Cel::db()->proteger($chemin_mot_cle)." AND "."id_utilisateur = ".Cel::db()->proteger($id_utilisateur);$infos_mot_cle = Cel::db()->executerRequete($requete_mot_cle_existe.' -- '.__FILE__.':'.__LINE__);if(!empty($infos_mot_cle)) {$id_mot_cle = $infos_mot_cle[0]['id_mot_cle'];} else {$id_mot_cle = $this->insererParChemin($mot_cle, $chemin_parent, $id_utilisateur);}return $id_mot_cle;}public function insererParChemin($mot_cle, $chemin_parent, $id_utilisateur) {$chemin_mot_cle = self::getCheminHarmonise($chemin_parent, $mot_cle);$requete = "INSERT INTO ".$this->table_mots_cles." (chemin, id_utilisateur, mot_cle) "."VALUES (".Cel::db()->proteger($chemin_mot_cle).", ".Cel::db()->proteger($id_utilisateur).", ".Cel::db()->proteger($mot_cle)." ".") ";$insertion = Cel::db()->executer($requete.' -- '.__FILE__.':'.__LINE__);$resultat = false;if($insertion !== false) {$resultat = Cel::db()->obtenirDernierId();}return $resultat;}public function insererParIdParent($mot_cle, $id_parent, $id_utilisateur) {$mot_cle_simp = self::simplifier($mot_cle);if($id_parent != "") {$sous_requete_chemin = "(SELECT chemin FROM ".$this->table_mots_cles." ctp "."WHERE ctp.id_mot_cle = ".Cel::db()->proteger($id_parent).")";} else {$sous_requete_chemin = Cel::db()->proteger("/");}$requete = "INSERT INTO ".$this->table_mots_cles."(chemin, id_utilisateur, mot_cle) "."VALUES ("."CONCAT(".$sous_requete_chemin.",".Cel::db()->proteger($mot_cle_simp).",'/'), ".Cel::db()->proteger($id_utilisateur).", ".Cel::db()->proteger($mot_cle)." ".")";$insertion = Cel::db()->executer($requete.' -- '.__FILE__.':'.__LINE__);if($insertion !== false) {$resultat = Cel::db()->obtenirDernierId();}return $resultat;}public function lierParId($id_mot_cle, $id_element_lie) {$requete = "INSERT INTO ".$this->table_liaison." (id_element_lie, id_mot_cle) "."VALUES (".Cel::db()->proteger($id_element_lie).", ".Cel::db()->proteger($id_mot_cle)." ".") "."ON DUPLICATE KEY UPDATE id_element_lie = id_element_lie ";$liaison = Cel::db()->executer($requete.' -- '.__FILE__.':'.__LINE__);return $liaison;}public function lierParChemin($chemin, $id_element_lie, $id_utilisateur) {$sous_requete_chemin = '(SELECT id_mot_cle FROM '.$this->table_mots_cles.' '.'WHERE chemin = '.Cel::db()->proteger(self::harmoniserChemin($chemin)).' '.'AND id_utilisateur = '.Cel::db()->proteger($id_utilisateur).' '.')';$requete = "INSERT INTO ".$this->table_liaison." (id_element_lie, id_mot_cle) "."VALUES (".Cel::db()->proteger($id_element_lie).", ".$sous_requete_chemin." ".") "."ON DUPLICATE KEY UPDATE id_element_lie = id_element_lie ";$liaison = Cel::db()->executer($requete.' -- '.__FILE__.':'.__LINE__);return $liaison;}public function lierParTableaux($ids_mots_cles, $ids_elements_lies, $id_utilisateur) {foreach($ids_mots_cles as $id_mot_cle) {foreach($ids_elements_lies as $id_element_lie) {$combinaisons[] = '('.Cel::db()->proteger($id_element_lie).', '.Cel::db()->proteger($id_mot_cle).')';}}$requete = "INSERT INTO ".$this->table_liaison." (id_element_lie, id_mot_cle) "."VALUES ".implode(',', $combinaisons).' '."ON DUPLICATE KEY UPDATE id_element_lie = id_element_lie ";$liaison = Cel::db()->executer($requete.' -- '.__FILE__.':'.__LINE__);return $liaison;}public function supprimerLiaisonsMotsCles($ids_mots_cles, $ids_elements_lies, $id_utilisateur) {$requete = 'DELETE FROM '.$this->table_liaison.' WHERE ';$combinaisons = array();foreach($ids_mots_cles as $id_mot_cle) {foreach($ids_elements_lies as $id_element_lie) {$combinaisons[] = '('.'id_element_lie = '.Cel::db()->proteger($id_element_lie).' AND '.'id_mot_cle = '.Cel::db()->proteger($id_mot_cle).')';}}$requete .= implode(' OR ', $combinaisons);$suppression = Cel::db()->executer($requete.' -- '.__FILE__.':'.__LINE__);return $suppression;}public function supprimerToutesLiaisonsPourIdsElementsLies($ids_elements_lies) {foreach($ids_elements_lies as &$id_element_lie) {$id_element_lie = Cel::db()->proteger($id_element_lie);}$requete = 'DELETE FROM '.$this->table_liaison.' '.'WHERE id_element_lie IN ('.implode(',', $ids_elements_lies).')';$suppression = Cel::db()->executer($requete.' -- '.__FILE__.':'.__LINE__);$suppression = ($suppression !== false);return $suppression;}public function supprimerToutesLiaisonsIdsMotsCles($ids_mots_cles, $id_utilisateur) {if(!empty($ids_mots_cles)) {$ids_mots_cles_p = array();foreach($ids_mots_cles as $id_mot_cle) {$id_mot_cle = Cel::db()->proteger($id_mot_cle);}$requete = 'DELETE FROM '.$this->table_liaison.' '.'WHERE id_mot_cle IN ('.implode(',', $ids_mots_cles).') ';$suppression = Cel::db()->executerRequeteSimple($requete.' -- '.__FILE__.':'.__LINE__);$suppression = ($suppression !== false);} else {$suppression = true;}return $suppression;}public function supprimerLiaisonPourMotCleEtIdElementLie($mot_cle, $id_element_lie, $id_utilisateur) {// supprime toutes les laisons pour un utilisateur et un mot clé (au sens textuel) donnés$requete = "DELETE FROM ".$this->table_liaison." "."WHERE id_element_lie = ".Cel::db()->proteger($id_element_lie)." "."AND id_mot_cle IN ("."SELECT id_mot_cle FROM ".$this->table_mots_cles." "."WHERE mot_cle = ".Cel::db()->proteger($mot_cle)." "."AND id_utilisateur = ".Cel::db()->proteger($id_utilisateur)." ".")";$suppression_liaison = Cel::db()->executerRequeteSimple($requete.' -- '.__FILE__.':'.__LINE__);$suppression_liaison = ($suppression_liaison !== false);return $suppression_liaison;}public function renommerMotCle($id_mot_cle, $nouveau_nom) {$nouveau_nom = self::simplifier($nouveau_nom);$requete_ancien_chemin = 'SELECT chemin, id_utilisateur FROM '.$this->table_mots_cles.' '.'WHERE id_mot_cle = '.Cel::db()->proteger($id_mot_cle);$res_ancien_chemin = Cel::db()->requeter($requete_ancien_chemin.' -- '.__FILE__.':'.__LINE__);$ancien_chemin = $res_ancien_chemin[0]['chemin'];$id_utilisateur = $res_ancien_chemin[0]['id_utilisateur'];$tab_chemin = explode('/', $ancien_chemin);// le dernier élément du tableau est vide (à cause du / terminal)// c'est également le cas pour le premier (à cause du / qui commence le chemin)$tab_chemin[count($tab_chemin) - 2] = $nouveau_nom;$nouveau_chemin = implode('/', $tab_chemin);$requete = 'UPDATE '.$this->table_mots_cles.' '.'SET mot_cle = '.Cel::db()->proteger($nouveau_nom).' '.'WHERE id_mot_cle = '.Cel::db()->proteger($id_mot_cle).' ';$renommage = Cel::db()->executer($requete.' -- '.__FILE__.':'.__LINE__);$this->renommerChemin($ancien_chemin, $nouveau_chemin, $id_utilisateur);$ids_elements_lies = $this->obtenirIdElementsLiesPourIds(array($id_mot_cle));foreach($ids_elements_lies as $id_element_lie) {self::regenererIndexTexteMotCle($id_element_lie['id_element_lie'], $this->mode);}return $renommage;}public function deplacerMotCle($id_mot_cle, $id_pere, $id_utilisateur) {$chemin_pere = "";// si aucun id_père n'a été mentionné, c'est un déplacement vers// la racine de l'arbre (qui n'existe pas)if($id_pere != "") {$selection_chemin_pere = 'SELECT chemin FROM '.$this->table_mots_cles.' '.'WHERE id_mot_cle = '.Cel::db()->proteger($id_pere);$chemin_pere = Cel::db()->requeter($selection_chemin_pere.' -- '.__FILE__.':'.__LINE__);if(!empty($chemin_pere)) {$chemin_pere = $chemin_pere[0]['chemin'];}}$selection_infos_mot_cle = 'SELECT chemin, mot_cle FROM '.$this->table_mots_cles.' '.'WHERE id_mot_cle = '.Cel::db()->proteger($id_mot_cle);$infos_mot_cle = Cel::db()->requeter($selection_infos_mot_cle.' -- '.__FILE__.':'.__LINE__);$ancien_chemin = $infos_mot_cle[0]['chemin'];$nouveau_chemin = $chemin_pere.'/'.$infos_mot_cle[0]['mot_cle'];return $this->renommerChemin($ancien_chemin, $nouveau_chemin, $id_utilisateur);}public function renommerChemin($ancien_chemin, $nouveau_chemin, $id_utilisateur) {$ancien_chemin = self::harmoniserChemin($ancien_chemin);$nouveau_chemin = self::harmoniserChemin($nouveau_chemin);$ancien_chemin_p = Cel::db()->proteger($ancien_chemin);$nouveau_chemin_p = Cel::db()->proteger($nouveau_chemin);$condition_chemin = Cel::db()->proteger($ancien_chemin.'%');$requete = "UPDATE ".$this->table_mots_cles." "."SET chemin = REPLACE(chemin,".$ancien_chemin_p.", ".$nouveau_chemin_p.") "."WHERE chemin LIKE ".$condition_chemin." AND "."id_utilisateur = ".$id_utilisateur." ";return Cel::db()->executer($requete.' -- '.__FILE__.':'.__LINE__);}public function supprimerChemin($chemin, $id_utilisateur) {// TODO : triggers pour les tables liées ?$requete = "DELETE FROM ".$this->$table_mots_cles." "."WHERE chemin LIKE ".Cel::db()->proteger($chemin."%")." AND "."id_utilisateur = ".Cel::db()->proteger($id_utilisateur)." ";return Cel::db()->executer($requete.' -- '.__FILE__.':'.__LINE__);}public function supprimerMotCleParId($id_mot_cle, $id_utilisateur) {//TODO: simplifier cette fonction// suppression des associations du mots clé aux images ou obs, mais aussi des associations de ses enfants// (car ceux-ci seront supprimés aussi dans le processus)// même s'il n'a pas d'enfants, le tableau contient au moins l'id du mot clé lui même$ids_mot_cle_et_enfants = $this->obtenirIdsMotsClesParIdParent($id_utilisateur, $id_mot_cle);$print = array();// obtention des ids des éléments liés au mot clé ainsi qu'à ces enfants (afin de pouvoir// régénérer les index texte de mots clés sur les éléments liés)$ids_a_delier = array();foreach($ids_mot_cle_et_enfants as $id) {$ids_a_delier[] = $id['id_mot_cle'];}$ids_elements_lies = $this->obtenirIdElementsLiesPourIds($ids_a_delier);$suppression_liaison = $this->supprimerToutesLiaisonsIdsMotsCles($ids_a_delier, $id_utilisateur);foreach($ids_elements_lies as $id_element_lie) {self::regenererIndexTexteMotCle($id_element_lie['id_element_lie'], $this->mode);}// suppression du mot clé proprement dit ainsi que de ses enfants$suppression = $this->supprimerMotCleEtEnfantsParId($id_mot_cle, $id_utilisateur);return $suppression && $suppression_liaison;}public function supprimerMotCleEtEnfantsParId($id_mot_cle, $id_utilisateur) {$selection_chemin = 'SELECT chemin FROM '.$this->table_mots_cles.' '.'WHERE id_mot_cle = '.Cel::db()->proteger($id_mot_cle);$chemin = Cel::db()->requeter($selection_chemin.' -- '.__FILE__.':'.__LINE__);$suppression = true;// vérification pour empecher la suppression accidentelle de tout l'arbre,// cas qui ne devrait jamais arriver normalementif(!empty($chemin) && $chemin != "/") {$chemin = $chemin[0]['chemin'];$requete = "DELETE FROM ".$this->table_mots_cles." WHERE chemin LIKE ".Cel::db()->proteger($chemin.'%')." "."AND id_utilisateur =".Cel::db()->proteger($id_utilisateur);$suppression = Cel::db()->executer($requete.' -- '.__FILE__.':'.__LINE__);}return ($suppression !== false);}public function obtenirIdsMotClesPourMotsCles($mots_cles, $id_utilisateur) {$mots_cles_p = array();foreach($mots_cles as $mot_cle) {$mots_cles_p[] = Cel::db()->proteger($mot_cle);}$requete = "SELECT id_mot_cle, mot_cle FROM ".$this->table_mots_cles." "."WHERE mot_cle IN (".implode(',', $mots_cles_p).") "."AND id_utilisateur = ".Cel::db()->proteger($id_utilisateur);return Cel::db()->executer($requete.' -- '.__FILE__.':'.__LINE__);}public function obtenirIdElementsLiesPourChemins($chemins, $id_utilisateur) {foreach($chemins as &$chemin) {$chemin = Cel::db()->proteger(self::harmoniserChemin($chemin));}$requete = 'SELECT id_element_lie FROM '.$this->table_liaison.' cl '.'INNER JOIN '.$this->table_mots_cles.' cm '.'ON cm.id_mot_cle = cl.id_mot_cle AND chemin IN ('.implode(',', $chemin).') '.' AND cm.id_utilisateur = '.Cel::db()->proteger($id_utilisateur);$ids_pour_chemin = Cel::db()->executer($requete.' -- '.__FILE__.':'.__LINE__);return $ids_pour_chemin;}public function obtenirIdElementsLiesPourIds($ids_mots_cles) {$ids_elements_lies = array();if(!empty($ids_mots_cles)) {foreach($ids_mots_cles as $id_mot_cle) {$id_mot_cle = Cel::db()->proteger($id_mot_cle);}$requete = 'SELECT id_element_lie FROM '.$this->table_liaison.' '.'WHERE id_mot_cle IN ('.implode(',', $ids_mots_cles).')';$ids_elements_lies = Cel::db()->executerRequete($requete.' -- '.__FILE__.':'.__LINE__);}return $ids_elements_lies;}/******* Fonctions statiques utilitaires* (Dans l'idéal toute la classe pourrait être statique car elle n'a* pas d'état (mais il faudrait passer $mode à toutes les fonctions)**/public static function getTablesMotsClesEtLiaisons($mode) {if($mode == 'obs') {$table_liaison = 'cel_mots_cles_obs_liaison';$table_mots_cles = 'cel_arbre_mots_cles_obs';} else {$table_liaison = 'cel_mots_cles_images_liaison';$table_mots_cles = 'cel_arbre_mots_cles_images';}return array($table_liaison, $table_mots_cles);}public static function regenererIndexTexteMotCle($id_element_lie, $mode) {$sous_requete_concat = '('.sprintf(GestionMotsClesChemin::obtenirTemplateRequeteMotsClesTexte($mode),Cel::db()->proteger($id_element_lie)).')';list($table, $champ_id) = self::getNomTablesEtChampsElementsLies($mode);$requete = 'UPDATE '.$table.' SET mots_cles_texte = '.$sous_requete_concat.' '.'WHERE '.$champ_id.' = '.Cel::db()->proteger($id_element_lie).' ';return Cel::db()->executer($requete, __FILE__ , __LINE__);}private static function getNomTablesEtChampsElementsLies($mode) {$tables = array();if($mode == 'obs') {$tables = array('cel_obs','id_observation');} else {$tables = array('cel_images','id_image');}return $tables;}public static function obtenirTemplateRequeteMotsClesTexte($mode) {list($table_liaison, $table_mots_cles) = self::getTablesMotsClesEtLiaisons($mode);// renvoie un template de requete pour selectionner la concatenation// de mots clé pour un element donné (utilisable avec sprintf)return 'SELECT GROUP_CONCAT(mot_cle) '.'FROM '.$table_mots_cles.' cm '.'INNER JOIN '.$table_liaison.' cml '.'ON cml.id_mot_cle = cm.id_mot_cle '.'AND cml.id_element_lie = %s ';}public static function obtenirTemplateRequeteMotsClesIds($mode) {list($table_liaison, $table_mots_cles) = self::getTablesMotsClesEtLiaisons($mode);// renvoie un template de recherche sur les ids de mots clés utilisables avec sprintfreturn "SELECT id_element_lie "."FROM ".$table_liaison." "."WHERE id_mot_cle IN (%s) ";}// Fonctions utilitairesstatic public function comparerProfNoeuds($a, $b) {// la profondeur d'un noeud est déterminée par le nombre de slashs// qu'il contient (étant donné que ceux ci sont interdits dans le texte du mot clé$nb_slashs_a = substr_count($a['chemin'], '/');$nb_slashs_b = substr_count($a['chemin'], '/');$cmp = 0;if($nb_slashs_a == $nb_slashs_b) {$cmp = strcmp($a['chemin'], $b['chemin']);} else {$cmp = ($a['chemin'] > $b['chemin']) ? +1 : -1;}return $cmp;}static public function getCheminHarmonise($chemin_parent, $mot_cle) {return self::harmoniserChemin($chemin_parent.'/'.self::simplifier($mot_cle).'/');}static public function harmoniserChemin($chemin) {$chemin = self::startsWith($chemin,'/') ? $chemin : '/'.$chemin;$chemin = self::endsWith($chemin,'/') ? $chemin : $chemin.'/';return str_replace('//', '/', $chemin);}// fonction de slugification du mot cléstatic public function simplifier($text){// ni slashes ou antislashes ou virgules (ce qui fausserait l'arbre ou bien les mots// clés texte dans les tables obs ou image)return trim(str_replace(array('\\','/', ','), '', $text));}// gardée pour compatibilité ancienne version (mais devrait être supprimée// dans le futurstatic function nettoyerMotsClesAvantSuppression($chaine) {$valeur = str_replace('null', '', $chaine);$valeur = trim($valeur, ';;');return $valeur;}static public function startsWith($haystack, $needle) {return $needle === "" || strpos($haystack, $needle) === 0;}static public function endsWith($haystack, $needle) {return $needle === "" || substr($haystack, -strlen($needle)) === $needle;}/*** Fonction utilisée pour importer les anciens mots clés saisis dans les widget dans un compte identifié* Dans ce cas là, le widget remplit la case id_utilisateur par le mail indiqué lors de la saisie* @param string $mail_utilisateur* @param string $id_utilisateur*/public static function migrerMotsClesMailVersId($mail_utilisateur, $infos_utilisateur) {return self::migrerLiaisonEtMotsCles($mail_utilisateur, $infos_utilisateur, 'obs') &&self::migrerLiaisonEtMotsCles($mail_utilisateur, $infos_utilisateur, 'images');}private static function migrerLiaisonEtMotsCles($mail_utilisateur, $infos_utilisateur, $mode) {list($table_liaisons, $table_mots_cles) = self::getTablesMotsClesEtLiaisons($mode);// ATTENTION : cette fonction suppose que l'utilisateur n'ai pas déjà de mots clés dans le CEL// avec l'identifiant $id_utilisateur ce qui est normalement le cas// ça devrait normalement marcher correctement même s'il en a déjà mais ça n'a pas été testé$requete_migration_mc = 'UPDATE '.$table_mots_cles.' SET '.'id_utilisateur = '.Cel::db()->proteger($infos_utilisateur['id_utilisateur']).' '.'WHERE id_utilisateur = '.Cel::db()->proteger($mail_utilisateur).' ';$migration_mc = Cel::db()->executerRequeteSimple($requete_migration_mc);$requete_migration_mc_liaisons = 'UPDATE '.$table_liaisons.' SET '.'id_utilisateur = '.Cel::db()->proteger($infos_utilisateur['id_utilisateur']).' '.'WHERE id_utilisateur = '.Cel::db()->proteger($mail_utilisateur).' ';$migration_mc_liaisons = Cel::db()->executerRequeteSimple($requete_migration_mc_liaisons);return $migration_mc !== false &&$migration_mc_liaisons !== false;}}?>