* @author Jean-Pascal MILCENT * @author Aurelien PERONNET * @license GPL v3 * @license CECILL v2 * @copyright 1999-2014 Tela Botanica */ class GestionMotsClesChemin { private $config; private $mode; private $table_liaison; private $table_mots_cles; //TODO: trigger pour les tables liaisons public 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 = '/') { $idUtilisateurP = Cel::db()->proteger($id_utilisateur); $cheminP = Cel::db()->proteger($chemin.'%'); $requete = 'SELECT * '. "FROM {$this->table_mots_cles} ". "WHERE id_utilisateur = $idUtilisateurP ". "AND chemin LIKE $cheminP ". 'ORDER BY chemin '. ' -- '.__FILE__.':'.__LINE__; $arbre = Cel::db()->requeter($requete); foreach ($arbre as &$noeud) { $noeud['chemin'] = strtolower($noeud['chemin']); } usort($arbre, array('GestionMotsClesChemin', 'comparerProfNoeuds')); return $arbre; } public function obtenirIdsMotsClesParIdParent($id_utilisateur, $id_mot_cle) { $idMotCleP = Cel::db()->proteger($id_mot_cle); $idUtilisateurP = Cel::db()->proteger($id_utilisateur); $sousRequete = "SELECT chemin FROM {$this->table_mots_cles} WHERE id_mot_cle = $idMotCleP "; $requete = 'SELECT id_mot_cle '. "FROM {$this->table_mots_cles} ". "WHERE chemin LIKE CONCAT(($sousRequete), '%') ". "AND id_utilisateur = $idUtilisateurP ". ' -- '.__FILE__.':'.__LINE__; return Cel::db()->requeter($requete); } /** * Retourne la liste des mots clés pour l'élément lié fourni. Ne tient pas compte de l'utilisateur * car seul le propriétaire d'un élément lié peut y lier des mots clés */ public function obtenirIdsMotsClesParIdElementLie($id_element_lie) { $idElementLieP = Cel::db()->proteger($id_element_lie); $requete = "SELECT id_mot_cle FROM {$this->table_liaison} ". "WHERE id_element_lie = $idElementLieP ". ' -- '.__FILE__.':'.__LINE__; return Cel::db()->requeter($requete); } public function insererParCheminSiInexistant($mot_cle, $chemin_parent, $id_utilisateur) { $mot_cle = self::simplifier($mot_cle); $cheminMotCle = self::getCheminHarmonise($chemin_parent, $mot_cle); $cheminMotCleP = Cel::db()->proteger($cheminMotCle); $idUtilisateurP = Cel::db()->proteger($id_utilisateur); $requete = 'SELECT id_mot_cle '. "FROM {$this->table_mots_cles} ". "WHERE chemin = $cheminMotCleP ". "AND id_utilisateur = $idUtilisateurP ". ' -- '.__FILE__.':'.__LINE__; $infosMotCle = Cel::db()->requeter($requete); if (!empty($infosMotCle)) { $idMotCle = $infosMotCle[0]['id_mot_cle']; } else { $idMotCle = $this->insererParChemin($mot_cle, $chemin_parent, $id_utilisateur); } return $idMotCle; } public function insererParChemin($mot_cle, $chemin_parent, $id_utilisateur) { $mot_cle = self::simplifier($mot_cle); $cheminMotCle = self::getCheminHarmonise($chemin_parent, $mot_cle); $cheminMotCleP = Cel::db()->proteger($cheminMotCle); $idUtilisateurP = Cel::db()->proteger($id_utilisateur); $motCleP = Cel::db()->proteger($mot_cle); $requete = "INSERT INTO {$this->table_mots_cles} ". '(chemin, id_utilisateur, mot_cle) '. "VALUES ($cheminMotCleP, $idUtilisateurP, $motCleP ) ". ' -- '.__FILE__.':'.__LINE__; $insertion = Cel::db()->executer($requete); $resultat = false; if ($insertion !== false) { $resultat = Cel::db()->obtenirDernierId(); } return $resultat; } public function insererParIdParent($mot_cle, $id_parent, $id_utilisateur) { $motCleSimple = self::simplifier($mot_cle); $motCleSimpleP = Cel::db()->proteger(strtolower(self::supprimerAccents($mot_cle))); $idParentP = Cel::db()->proteger($id_parent); $racineP = Cel::db()->proteger('/'); $idUtilisateurP = Cel::db()->proteger($id_utilisateur); $motCleP = Cel::db()->proteger($mot_cle); $sousRequete = $racineP; if ($id_parent != '') { $sousRequete = '(SELECT chemin '. "FROM {$this->table_mots_cles} AS ctp ". "WHERE ctp.id_mot_cle = $idParentP) "; } $requete = "INSERT INTO {$this->table_mots_cles} (chemin, id_utilisateur, mot_cle) ". "VALUES (CONCAT($sousRequete, $motCleSimpleP, '/'), $idUtilisateurP, $motCleP ) ". ' -- '.__FILE__.':'.__LINE__; $insertion = Cel::db()->executer($requete); if ($insertion !== false) { $resultat = Cel::db()->obtenirDernierId(); } return $resultat; } public function lierParId($id_mot_cle, $id_element_lie) { $idElementLieP = Cel::db()->proteger($id_element_lie); $idMotCleP = Cel::db()->proteger($id_mot_cle); $requete = "INSERT INTO {$this->table_liaison} (id_element_lie, id_mot_cle) ". "VALUES ($idElementLieP, $idMotCleP) ". 'ON DUPLICATE KEY UPDATE `id_element_lie`=VALUES(`id_element_lie`), `id_mot_cle`=VALUES(`id_mot_cle`) '. ' -- '.__FILE__.':'.__LINE__; return Cel::db()->executer($requete); } public function lierParChemin($chemin, $id_element_lie, $id_utilisateur) { $cheminP = Cel::db()->proteger(self::harmoniserChemin($chemin)); $idElementLieP = Cel::db()->proteger($id_element_lie); $idUtilisateurP = Cel::db()->proteger($id_utilisateur); $sousRequete = '(SELECT id_mot_cle '. "FROM {$this->table_mots_cles} ". "WHERE chemin = $cheminP ". "AND id_utilisateur = $idUtilisateurP ". ')'; $requete = "INSERT INTO {$this->table_liaison} (id_element_lie, id_mot_cle) ". "VALUES ($idElementLieP, $sousRequete) ". 'ON DUPLICATE KEY UPDATE `id_element_lie`=VALUES(`id_element_lie`), `id_mot_cle`=VALUES(`id_mot_cle`) '. ' -- '.__FILE__.':'.__LINE__; return Cel::db()->executer($requete); } public function lierParTableaux($ids_mots_cles, $ids_elements_lies) { $combinaisons = array(); foreach ($ids_mots_cles as $id_mot_cle) { $idMotCleP = Cel::db()->proteger($id_mot_cle); foreach ($ids_elements_lies as $id_element_lie) { $idElementLieP = Cel::db()->proteger($id_element_lie); $combinaisons[] = "($idElementLieP, $idMotCleP)"; } } $valeursGroupees = implode(', ', $combinaisons); $requete = "INSERT INTO {$this->table_liaison} (id_element_lie, id_mot_cle) ". "VALUES $valeursGroupees ". "ON DUPLICATE KEY UPDATE `id_element_lie`=VALUES(`id_element_lie`), `id_mot_cle`=VALUES(`id_mot_cle`) ". ' -- '.__FILE__.':'.__LINE__; return Cel::db()->executer($requete); } /** * Modifie les liaisons aux mots clés pour chaque element lié, en supprimant et ajoutant seulement les * mots clés qui ont changé, sans toucher à ceux qui sont conservés. Ça évite de tout supprimer avant, * et ainsi de perdre la date de liaison des mots clés conservés. * Si $supprimer est true, les mots clefs existant mais non spécifiés dans le POST seront supprimés, * sinon ils seront laissés en l'état. */ public function modifierLiaisonParTableaux($ids_mots_cles, $ids_elements_lies, $supprimer) { $reussi = true; foreach ($ids_elements_lies as $id_element_lie) { $idElementLieP = Cel::db()->proteger($id_element_lie); // trouver les mots clés actuels $ids_mots_cles_actuels = $this->obtenirIdsMotsClesParIdElementLie($id_element_lie); if (! is_array($ids_mots_cles_actuels)) { $ids_mots_cles_actuels = array(); } // remise en forme foreach ($ids_mots_cles_actuels as $k => $v) { if (isset($v['id_mot_cle'])) { // je vois mal comment ça pourrait ne pas être set $ids_mots_cles_actuels[$k] = $v['id_mot_cle']; } } // changements $ids_mots_cles_ajoutes = array_diff($ids_mots_cles, $ids_mots_cles_actuels); if ($supprimer === true) { $ids_mots_cles_supprimes = array_diff($ids_mots_cles_actuels, $ids_mots_cles); } // insérer if (count($ids_mots_cles_ajoutes) > 0) { $combinaisons = array(); foreach ($ids_mots_cles_ajoutes as $id_mot_cle) { $idMotCleP = Cel::db()->proteger($id_mot_cle); $combinaisons[] = "($idElementLieP, $idMotCleP)"; } $valeursGroupees = implode(', ', $combinaisons); $requete = "INSERT INTO {$this->table_liaison} (id_element_lie, id_mot_cle) ". "VALUES $valeursGroupees ". "ON DUPLICATE KEY UPDATE `id_element_lie`=VALUES(`id_element_lie`), `id_mot_cle`=VALUES(`id_mot_cle`) ". // normalement pas nécessaire ' -- '.__FILE__.':'.__LINE__; $resultat = Cel::db()->executer($requete); $reussi = ($reussi && $resultat); } // supprimer if ($supprimer === true && count($ids_mots_cles_supprimes) > 0) { $clauses = array(); foreach ($ids_mots_cles_supprimes as $id_mot_cle) { $idMotCleP = Cel::db()->proteger($id_mot_cle); $clauses[] = "(id_element_lie = $idElementLieP AND id_mot_cle = $idMotCleP)"; } $clause = implode(' OR ', $clauses); $requete = "DELETE FROM {$this->table_liaison} WHERE $clause" . ' -- '.__FILE__.':'.__LINE__; $resultat = Cel::db()->executer($requete); $reussi = ($reussi && $resultat); } } return $reussi; } public function supprimerLiaisonsMotsCles($ids_mots_cles, $ids_elements_lies, $id_utilisateur) { $combinaisons = array(); foreach ($ids_mots_cles as $id_mot_cle) { $idMotCleP = Cel::db()->proteger($id_mot_cle); foreach ($ids_elements_lies as $id_element_lie) { $idElementLieP = Cel::db()->proteger($id_element_lie); $combinaisons[] = "(id_element_lie = $idElementLieP AND id_mot_cle = $idMotCleP)"; } } $clauseWhere = implode(' OR ', $combinaisons); $requete = "DELETE FROM {$this->table_liaison} ". "WHERE $clauseWhere ". ' -- '.__FILE__.':'.__LINE__; return Cel::db()->executer($requete); } public function supprimerToutesLiaisonsPourIdsElementsLies($ids_elements_lies) { $idsElementsLiesP = Cel::db()->proteger($ids_elements_lies); $listeIds = implode(',', $idsElementsLiesP); $requete = "DELETE FROM {$this->table_liaison} ". "WHERE id_element_lie IN ($listeIds) ". ' -- '.__FILE__.':'.__LINE__; $suppression = Cel::db()->executer($requete); $suppression = ($suppression !== false) ? true : false; return $suppression; } public function supprimerToutesLiaisonsIdsMotsCles($ids_mots_cles, $id_utilisateur) { $suppression = true; if (!empty($ids_mots_cles)) { $idsMotsClesP = Cel::db()->proteger($ids_mots_cles); $listeIds = implode(',', $idsMotsClesP); $requete = "DELETE FROM {$this->table_liaison} ". "WHERE id_mot_cle IN ($listeIds) ". ' -- '.__FILE__.':'.__LINE__; $suppression = Cel::db()->executer($requete); $suppression = ($suppression !== false) ? true : false; } return $suppression; } /** * Supprime toutes les laisons pour un utilisateur et un mot clé (au sens textuel) donnés. * */ public function supprimerLiaisonPourMotCleEtIdElementLie($mot_cle, $id_element_lie, $id_utilisateur) { $mot_cle = self::simplifier($mot_cle); $idElementLieP = Cel::db()->proteger($id_element_lie); $motCleP = Cel::db()->proteger($mot_cle); $idUtilisateurP = Cel::db()->proteger($id_utilisateur); $sousRequete = "SELECT id_mot_cle FROM {$this->table_mots_cles} ". "WHERE mot_cle = $motCleP ". "AND id_utilisateur = $idUtilisateurP "; $requete = "DELETE FROM {$this->table_liaison} ". "WHERE id_element_lie = $idElementLieP ". "AND id_mot_cle IN ($sousRequete) ". ' -- '.__FILE__.':'.__LINE__; $suppression_liaison = Cel::db()->executer($requete); $suppression_liaison = ($suppression_liaison !== false); return $suppression_liaison; } public function renommerMotCle($id_mot_cle, $nouveau_nom) { $nouveauNomSimple = self::simplifier($nouveau_nom); $nouveauNomSimpleP = Cel::db()->proteger($nouveauNomSimple); $idMotCleP = Cel::db()->proteger($id_mot_cle); $requete = 'SELECT chemin, id_utilisateur '. "FROM {$this->table_mots_cles} ". "WHERE id_mot_cle = $idMotCleP ". ' -- '.__FILE__.':'.__LINE__; $ancienCheminInfos = Cel::db()->requeter($requete); $ancienChemin = $ancienCheminInfos[0]['chemin']; $id_utilisateur = $ancienCheminInfos[0]['id_utilisateur']; $cheminDecompo = explode('/', $ancienChemin); // 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) $cheminDecompo[count($cheminDecompo) - 2] = $nouveauNomSimple; $nouveauChemin = implode('/', $cheminDecompo); $requete = "UPDATE {$this->table_mots_cles} ". "SET mot_cle = $nouveauNomSimpleP ". "WHERE id_mot_cle = $idMotCleP ". ' -- '.__FILE__.':'.__LINE__; $renommage = Cel::db()->executer($requete); $this->renommerChemin($ancienChemin, $nouveauChemin, $id_utilisateur); $idsElementsLies = $this->obtenirIdElementsLiesPourIds(array($id_mot_cle)); foreach ($idsElementsLies as $idElementLie) { self::regenererIndexTexteMotCle($idElementLie['id_element_lie'], $this->mode); } return $renommage; } /** * Si aucun id_père n'est mentionné, c'est un déplacement vers la racine de l'arbre (qui n'existe pas). */ public function deplacerMotCle($id_mot_cle, $id_pere, $id_utilisateur) { $idMotCleP = Cel::db()->proteger($id_mot_cle); $idPereP = Cel::db()->proteger($id_pere); $cheminPere = ''; if ($id_pere != '') { $requete = 'SELECT chemin '. "FROM {$this->table_mots_cles} ". "WHERE id_mot_cle = $idPereP ". ' -- '.__FILE__.':'.__LINE__; $cheminPereInfos = Cel::db()->requeter($requete); if (!empty($cheminPereInfos)) { $cheminPere = $cheminPereInfos[0]['chemin']; } } $requete = 'SELECT chemin, mot_cle '. "FROM {$this->table_mots_cles} ". "WHERE id_mot_cle = $idMotCleP ". ' -- '.__FILE__.':'.__LINE__; $infosMotCle = Cel::db()->requeter($requete); $ancienChemin = $infosMotCle[0]['chemin']; $ancienMotCle = $infosMotCle[0]['mot_cle']; $nouveauChemin = $cheminPere.'/'.$ancienMotCle; return $this->renommerChemin($ancienChemin, $nouveauChemin, $id_utilisateur); } public function renommerChemin($ancien_chemin, $nouveau_chemin, $id_utilisateur) { $ancienCheminHarmonise = self::harmoniserChemin($ancien_chemin); $nouveauCheminHarmonise = self::harmoniserChemin($nouveau_chemin); $idUtilisateurP = Cel::db()->proteger($id_utilisateur); $ancienCheminP = Cel::db()->proteger($ancienCheminHarmonise); $nouveauCheminP = Cel::db()->proteger($nouveauCheminHarmonise); $conditionCheminP = Cel::db()->proteger($ancienCheminHarmonise.'%'); $requete = "UPDATE {$this->table_mots_cles} ". "SET chemin = REPLACE(chemin, $ancienCheminP, $nouveauCheminP) ". "WHERE chemin LIKE $conditionCheminP ". "AND id_utilisateur = $idUtilisateurP ". ' -- '.__FILE__.':'.__LINE__; return Cel::db()->executer($requete); } public function supprimerChemin($chemin, $id_utilisateur) { $idUtilisateurP = Cel::db()->proteger($id_utilisateur); $cheminP = Cel::db()->proteger($chemin.'%'); // TODO : triggers pour les tables liées ? $requete = "DELETE FROM {$this->$table_mots_cles} ". "WHERE chemin LIKE $cheminP ". "AND id_utilisateur = $idUtilisateurP ". ' -- '.__FILE__.':'.__LINE__; return Cel::db()->executer($requete); } /** * 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 */ public function supprimerMotCleParId($id_mot_cle, $id_utilisateur) { //TODO: simplifier cette fonction $ids_mot_cle_et_enfants = $this->obtenirIdsMotsClesParIdParent($id_utilisateur, $id_mot_cle); // 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) { $idMotCleP = Cel::db()->proteger($id_mot_cle); $requete = 'SELECT chemin '. "FROM {$this->table_mots_cles} ". "WHERE id_mot_cle = $idMotCleP ". ' -- '.__FILE__.':'.__LINE__; $chemin = Cel::db()->requeter($requete); $suppression = true; // vérification pour empecher la suppression accidentelle de tout l'arbre, // cas qui ne devrait jamais arriver normalement if (!empty($chemin) && $chemin != '/') { $chemin = $chemin[0]['chemin']; $cheminP = Cel::db()->proteger($chemin.'%'); $idUtilisateurP = Cel::db()->proteger($id_utilisateur); $requete = "DELETE FROM {$this->table_mots_cles} ". "WHERE chemin LIKE $cheminP ". "AND id_utilisateur = $idUtilisateurP ". ' -- '.__FILE__.':'.__LINE__;; $suppression = Cel::db()->executer($requete); } return ($suppression !== false); } public function obtenirIdsMotClesPourMotsCles($mots_cles, $id_utilisateur) { $motsClesP = array(); foreach ($mots_cles as $mot_cle) { $motsClesP[] = Cel::db()->proteger(self::simplifier($mot_cle)); } $listeMotsClesP = implode(',', $motsClesP); $idUtilisateurP = Cel::db()->proteger($id_utilisateur); $requete = 'SELECT id_mot_cle, mot_cle '. "FROM {$this->table_mots_cles} ". "WHERE mot_cle IN ($listeMotsClesP) ". "AND id_utilisateur = $idUtilisateurP ". ' -- '.__FILE__.':'.__LINE__; $resultat = Cel::db()->executerRequete($requete); return $resultat; } public function obtenirIdElementsLiesPourChemins($chemins, $id_utilisateur) { foreach ($chemins as &$chemin) { $chemin = Cel::db()->proteger(self::harmoniserChemin($chemin)); } $listeChemins = implode(',', $chemin); $idUtilisateurP = Cel::db()->proteger($id_utilisateur); $requete = 'SELECT id_element_lie '. "FROM {$this->table_liaison} AS cl INNER JOIN {$this->table_mots_cles} AS cm ". "ON (". "cm.id_mot_cle = cl.id_mot_cle ". "AND chemin IN ($listeChemins) ". "AND cm.id_utilisateur = $idUtilisateurP ". ") ". ' -- '.__FILE__.':'.__LINE__; $idsPourChemin = Cel::db()->executer($requete); return $idsPourChemin; } public function obtenirIdElementsLiesPourIds($ids_mots_cles) { $idsElementsLies = array(); if (!empty($ids_mots_cles)) { $idsMotsClesP = Cel::db()->proteger($ids_mots_cles); $listeIdsMotsCles = implode(',', $idsMotsClesP); $requete = 'SELECT id_element_lie '. "FROM {$this->table_liaison} ". "WHERE id_mot_cle IN ($listeIdsMotsCles) ". ' -- '.__FILE__.':'.__LINE__; $idsElementsLies = Cel::db()->requeter($requete); } return $idsElementsLies; } /** * * 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); } /** * Régénère le champ "mots_cles_texte" l'entité liée (image ou obs) * et met à jour sa date de modification */ public static function regenererIndexTexteMotCle($id_element_lie, $mode) { $idElementLieP = Cel::db()->proteger($id_element_lie); $sqlTpl = self::obtenirTemplateRequeteMotsClesTexte($mode); $sousRequete = sprintf($sqlTpl, $idElementLieP); list($table, $champId) = self::getNomTablesEtChampsElementsLies($mode); $requete = "UPDATE $table ". "SET mots_cles_texte = ($sousRequete) ". ", date_modification = NOW() ". "WHERE $champId = $idElementLieP ". ' -- '.__FILE__.':'.__LINE__; return Cel::db()->executer($requete); } 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; } /** * Renvoie un template de requete pour selectionner la concatenation de mots clé * pour un element donné (utilisable avec sprintf) */ public static function obtenirTemplateRequeteMotsClesTexte($mode) { list($table_liaison, $table_mots_cles) = self::getTablesMotsClesEtLiaisons($mode); $requeteTpl = 'SELECT GROUP_CONCAT(mot_cle) '. "FROM $table_mots_cles AS cm ". "INNER JOIN $table_liaison AS cml ON cml.id_mot_cle = cm.id_mot_cle ". 'AND cml.id_element_lie = %s '; return $requeteTpl; } /** * Renvoie un template de recherche sur les ids de mots clés utilisables avec sprintf. */ public static function obtenirTemplateRequeteMotsClesIds($mode) { list($table_liaison, $table_mots_cles) = self::getTablesMotsClesEtLiaisons($mode); $requeteTpl = "SELECT id_element_lie FROM $table_liaison WHERE id_mot_cle IN (%s) "; return $requeteTpl; } // Méthodes utilitaires /** * 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é. */ static public function comparerProfNoeuds($a, $b) { $nb_slashs_a = substr_count($a['chemin'], '/'); $nb_slashs_b = substr_count($a['chemin'], '/'); $cmp = 0; if ($nb_slashs_a == $nb_slashs_b) { $cmp = strcasecmp($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.'/'; $chemin = str_replace('//', '/', $chemin); // mise en minuscule du chemin afin d'éviter des cas où l'on aurait // des même mots clés avec minuscule et majuscule $chemin = strtolower($chemin); $chemin = self::supprimerAccents($chemin); return $chemin; } static function supprimerAccents($str, $charset='utf-8') { $str = htmlentities($str, ENT_NOQUOTES, $charset); $str = preg_replace('#&([A-za-z])(?:acute|cedil|circ|grave|orn|ring|slash|th|tilde|uml);#', '\1', $str); $str = preg_replace('#&([A-za-z]{2})(?:lig);#', '\1', $str); // pour les ligatures e.g. 'œ' $str = preg_replace('#&[^;]+;#', '', $str); // supprime les autres caractères return $str; } /** * Fonction de slugification du mot clé * * Ni slashes ou antislashes ou virgules (ce qui fausserait l'arbre ou bien les mots * clés texte dans les tables obs ou image) */ static public function simplifier($text) { $caracteresASupprimer = array('\\','/', ','); $text = str_replace($caracteresASupprimer, '', $text); $text = trim($text); return $text; } /** * Gardée pour compatibilité ancienne version (mais devrait être supprimée * dans le futur */ static function nettoyerMotsClesAvantSuppression($chaine) { $valeur = str_replace('null', '', $chaine); $valeur = trim($valeur, ';;'); return $valeur; } public static function startsWith($haystack, $needle) { return $needle === '' || strpos($haystack, $needle) === 0; } public static 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'); } /** * 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é */ private static function migrerLiaisonEtMotsCles($email_utilisateur, $infos_utilisateur, $mode) { list($table_liaisons, $table_mots_cles) = self::getTablesMotsClesEtLiaisons($mode); $idUtilisateurP = Cel::db()->proteger($infos_utilisateur['id_utilisateur']); $emailUtilisateurP = Cel::db()->proteger($email_utilisateur); $requete_migration_mc = "UPDATE {$table_mots_cles} ". "SET id_utilisateur = $idUtilisateurP ". "WHERE id_utilisateur = $emailUtilisateurP "; $migration = Cel::db()->executer($requete_migration_mc); $migration = ($migration !== false) ? true : false; return $migration; } }