* @license GPL v3 * @license CECILL v2 * @version $Id$ * @copyright © 2011, Tela-Botanica */ class InventoryKeyWordList extends Cel { protected $suffixe = ''; protected $suffixe_table = null; protected $suffixe_champ = null; private function setChampsEtTablePourSuffixe($suffixe) { $this->suffixe = $suffixe; switch($suffixe) { case 'obs': $this->suffixe_table = '_obs'; $this->suffixe_champ = '_obs'; break; case 'images': $this->suffixe_table = '_images'; $this->suffixe_champ = '_image'; break; } } public function getElement($uid) { // Controle detournement utilisateur $id_utilisateur = $uid[1] ; $this->controleUtilisateur($uid[1]); $this->setChampsEtTablePourSuffixe($uid[0]); $requete = 'SELECT mot_cle, id_mot_cle'.$this->suffixe_champ.', ce_mot_cle'.$this->suffixe_champ.'_parent '. 'FROM cel_mots_cles'.$this->suffixe_table.' '. 'WHERE id_utilisateur = '.$this->proteger($id_utilisateur).' '. 'ORDER BY niveau '; $resultats_mots_cles = $this->requeter($requete); if (is_array($resultats_mots_cles)) { $mots_cles = array(); foreach($resultats_mots_cles as $mot_cle) { $mots_cles[] = $mot_cle; } $this->envoyerJson($mots_cles); return true; } } public function updateElement($uid, $pairs) { $id_utilisateur = $uid[1]; $this->controleUtilisateur($uid[1]); $this->setChampsEtTablePourSuffixe($uid[0]); $id_mot_cle = $pairs['id']; $action = $pairs['action']; if ($action == 'modification') { $nouveau_nom = $pairs['motcle']; $nouvel_id_general = md5(mb_strtolower($nouveau_nom)); $requete = 'UPDATE cel_mots_cles'.$this->suffixe_table.' '. 'SET mot_cle = '.$this->proteger($nouveau_nom).' , '. ' md5 = '.$this->proteger($nouvel_id_general).' '. 'WHERE id_mot_cle'.$this->suffixe_champ.' = '.$this->proteger($id_mot_cle).' '. ' AND id_utilisateur = '.$this->proteger($id_utilisateur) ; $reussite = $this->executer($requete); if ($reussite !== false) { echo 'OK'; } } else if ($action == 'deplacement') { $this->commencerTransaction(); $transaction_reussie_1 = true; $id_pere = $pairs['parent']; $bornes = $this->calculerBornesEtNiveau($id_mot_cle, $id_utilisateur); $bg = $bornes['bg']; $bd = $bornes['bd']; $niveau = $bornes['niveau']; // on inverse l'intervalle de l'élément déplacé et du sous arbre $transaction_reussie_2 = $this->exclureIntervalle($bg, $bd, $id_utilisateur); $bg_negative = $bg - $bd - 1; $bd_negative = $bd - $bd - 1; // on recalcule les intervalles de l'arbre privé de ce sous arbre $transaction_reussie_3 = $this->decalerBornesMoinsIntervalle($bg, $bd, $id_utilisateur); $bornes_pere = $this->calculerBornesEtNiveau($id_pere, $id_utilisateur); $bg_pere = $bornes_pere['bg']; $bd_pere = $bornes_pere['bd']; $niveau_pere = $bornes_pere['niveau']; $decalage = $bd - $bg + 1; // on decale les bornes droite du pere pour préparer l'insertion $transaction_reussie_4 = $this->decalerBornesPlusIntervalle($bd_pere, $decalage, $id_utilisateur); $nouvelle_bd = $bd_pere + $decalage; $modif_niveau = $niveau_pere - $niveau + 1; $transaction_reussie_5 = $this->inclureIntervalle($bg_negative, $bd_negative, $nouvelle_bd, $modif_niveau, $id_utilisateur); $transaction_reussie_6 = $this->changerPere($id_mot_cle, $id_pere, $id_utilisateur); if ($transaction_reussie_1 !== false && $transaction_reussie_2 !== false && $transaction_reussie_3 !== false && $transaction_reussie_4 !== false && $transaction_reussie_5 !== false && $transaction_reussie_6 !== false) { $this->completerTransaction(); } else { $this->annulerTransaction(); } } } public function createElement($pairs) { // Controle detournement utilisateur $this->controleUtilisateur($pairs['identifiant']); $this->setChampsEtTablePourSuffixe($pairs['mode']); $id_utilisateur = $pairs['identifiant']; $mot_cle = $pairs['motcle']; // TODO supprimer accents $id_mot_cle_general = md5(mb_strtolower($mot_cle)); $id_mot_cle = $pairs['id']; $id_parent = $pairs['parent']; $this->ajouterMotCleRacine($id_utilisateur); $this->commencerTransaction(); $bornes = $this->calculerBornesEtNiveau($id_parent, $id_utilisateur); $borne_pere = $bornes['bd']; $niveau = $bornes['niveau'] + 1; $bg = $bornes['bd']; $bd = $bg + 1; $transaction_reussie_1 = $this->decalerBornesPlusDeux($borne_pere,$id_utilisateur) ? true : false; $requete = 'INSERT INTO cel_mots_cles'.$this->suffixe_table.' '. 'VALUES ( '. $this->proteger($id_mot_cle).', '. $this->proteger($id_utilisateur).', '. $this->proteger($mot_cle).', '. $this->proteger($id_mot_cle_general).', '. $this->proteger($bg).', '. $this->proteger($bd).', '. $this->proteger($niveau).', '. $this->proteger($id_parent).') ' ; $transaction_reussie_2 = $this->executer($requete); if ($transaction_reussie_1 && $transaction_reussie_2) { $this->completerTransaction(); } else { $this->annulerTransaction(); } } public function deleteElement($uid) { $this->setChampsEtTablePourSuffixe($uid[0]); $id_utilisateur = $uid[1]; $id_mot_cle = $uid[2]; $tableau_ids_mots_cles = array(); $tableau_ids_mots_cles[] = $id_mot_cle; $this->controleUtilisateur($id_utilisateur); $this->commencerTransaction(); $bornes = $this->calculerBornesEtNiveau($id_mot_cle, $id_utilisateur); if($bornes) { $bg = $bornes['bg']; $bd = $bornes['bd']; $requete_mots_cles_fils = 'SELECT id_mot_cle'.$this->suffixe_champ.' as id FROM cel_mots_cles'.$this->suffixe_table.' '. 'WHERE bg >= '.$this->proteger($bg).' '. ' AND bd <= '.$this->proteger($bd).' '. ' AND id_utilisateur = '.$this->proteger($id_utilisateur).' '; $mots_cles_fils = $this->requeter($requete_mots_cles_fils); foreach ($mots_cles_fils as $fils) { $tableau_ids_mots_cles[] = $fils['id']; } $requete = 'DELETE FROM cel_mots_cles'.$this->suffixe_table.' '. 'WHERE bg >= '.$this->proteger($bg).' '. ' AND bd <= '.$this->proteger($bd).' '. ' AND id_utilisateur = '.$this->proteger($id_utilisateur).' '; $transaction_reussie_1 = $this->executer($requete); $transaction_reussie_2 = $this->decalerBornesMoinsIntervalle($bg, $bd, $id_utilisateur) ? true : false; if ($transaction_reussie_1 !== false && $transaction_reussie_2 !== false) { $this->completerTransaction(); } else { $this->annulerTransaction(); } } // Suppression des liaisons associées à ce mot clé $gestion_liaisons = new LiaisonMotsCles($this->config, $this->suffixe); $gestion_liaisons->supprimerToutesLiaisonsPourIdMotCle($id_utilisateur, $tableau_ids_mots_cles); } private function ajouterMotCleRacine($id) { $requete = 'SELECT COUNT(*) as nb_mc '. 'FROM cel_mots_cles'.$this->suffixe_table.' '. 'WHERE id_utilisateur = '.$this->proteger($id).' '; $resultat = $this->requeter($requete); if (is_array($resultat) && count($resultat) > 0) { $valeurs = $resultat[0]['nb_mc']; switch ($this->suffixe) { case 'obs' : $nom_racine = 'Projets'; $id_racine = 'racine_obs'; break; case 'images' : $nom_racine = 'Mots clés'; $id_racine = 'racine'; break; default: $nom_racine = $this->suffixe; $id_racine = $this->suffixe; } $md5_racine = $this->proteger(md5($nom_racine)); $id_racine = $this->proteger($id_racine); $nom_racine = $this->proteger($nom_racine); $id_utilisateur = $this->proteger($id); if ($valeurs == 0) { $requete = "INSERT INTO cel_mots_cles{$this->suffixe_table} ". "VALUES ($id_racine, $id_utilisateur, $nom_racine, $md5_racine, ". "1, 2, 0, '') "; $this->executer($requete); } } } /** * Désactive l'auto-commit puis débute la transaction */ private function commencerTransaction() { // Désactive l'autocommit le temps de la manipulation de l'arbre $requete = 'SET AUTOCOMMIT = 0 '; $reussite_autocommit = $this->executer($requete); // Débute une nouvelle transaction $requete = 'BEGIN '; $reussite_begin = $this->executer($requete); } /** * Termine la transaction puis réactive l'auto-commit */ private function completerTransaction() { // Complète la transaction $requete = 'COMMIT '; $reussite_commit = $this->executer($requete); // Réactive l'autocommit le temps de la manipulation de l'arbre $requete = 'SET AUTOCOMMIT = 1 '; $reussite_autocommit = $this->executer($requete); echo 'OK'; } /** * Annule la transaction et réactive l'auto-commit */ private function annulerTransaction() { // Annule la transaction $requete = 'ROLLBACK '; $reussite_rollback = $this->executer($requete); // Réactive l'autocommit le temps de la manipulation de l'arbre $requete = 'SET AUTOCOMMIT = 1 '; $reussite_autocommit = $this->executer($requete); echo 'ERROR'; } /** * Renvoie les bornes d'un noeud de l'arbre des mots clés */ private function calculerBornesEtNiveau($id_mot_cle,$id_utilisateur) { $requete = 'SELECT bd, bg, niveau '. 'FROM cel_mots_cles'.$this->suffixe_table.' '. 'WHERE id_mot_cle'.$this->suffixe_champ.' = '.$this->proteger($id_mot_cle).' '. ' AND id_utilisateur = '.$this->proteger($id_utilisateur).' '; $resultat = $this->requeter($requete); $valeurs = null; if(is_array($resultat) && count($resultat) > 0) { $valeurs = $resultat[0]; } return $valeurs; } /** * Décale les bornes de deux pour insérer un nouvel élément */ private function decalerBornesPlusDeux($valeur, $id_utilisateur) { // Décalage borne droite $requete = 'UPDATE cel_mots_cles'.$this->suffixe_table.' '. 'SET bd = bd + 2 WHERE bd >= '.$valeur.' '. ' AND id_utilisateur = '.$this->proteger($id_utilisateur).' '; $reussi_1 = $this->executer($requete); // Décalage borne gauche $requete = 'UPDATE cel_mots_cles'.$this->suffixe_table.' '. 'SET bg = bg + 2 '. 'WHERE bg >= '.$valeur.' '. ' AND id_utilisateur = '.$this->proteger($id_utilisateur).' '; $reussi_2 = $this->executer($requete); return $reussi_1 !== false && $reussi_2 !== false; } /** * Décale les bornes d'un intervalle negatif donne (pour la suppression d'un sous arbre). */ private function decalerBornesMoinsIntervalle($bg, $bd, $id_utilisateur) { $decalage = $bd - $bg + 1; // Décalage borne droite $requete = 'UPDATE cel_mots_cles'.$this->suffixe_table.' '. 'SET bd = bd - '.$decalage.' '. 'WHERE bd >= '.$bg.' '. ' AND id_utilisateur = '.$this->proteger($id_utilisateur).' '; $reussi_1 = $this->executer($requete); // Décalage borne gauche $requete = 'UPDATE cel_mots_cles'.$this->suffixe_table.' '. 'SET bg = bg - '.$decalage.' '. 'WHERE bg > '.$bg.' '. ' AND id_utilisateur = '.$this->proteger($id_utilisateur).' '; $reussi_2 = $this->executer($requete); return $reussi_1 !== false && $reussi_2 !== false; } /** * Décale à droite des bornes donées d'un intervalle positif donne (pour l'ajout d'un sous arbre). */ private function decalerBornesPlusIntervalle($valeur_bornes, $largeur, $id_utilisateur) { $decalage = $largeur; // decalage borne droite $requete = 'UPDATE cel_mots_cles'.$this->suffixe_table.' '. 'SET bd = bd + '.$decalage.' '. 'WHERE bd >= '.$valeur_bornes.' '. ' AND id_utilisateur = '.$this->proteger($id_utilisateur).' '; $reussi_1 = $this->executer($requete); // decalage borne gauche $requete = 'UPDATE cel_mots_cles'.$this->suffixe_table.' '. 'SET bg = bg + '.$decalage.' '. 'WHERE bg >= '.$valeur_bornes.' '. ' AND id_utilisateur = '.$this->proteger($id_utilisateur).' '; $reussi_2 = $this->executer($requete); return $reussi_1 !== false && $reussi_2 !== false; } /** * Inverse les bornes d'un intervalle pour l'exclure des modifications sur l'arbre sans changer la hiérarchie. */ private function exclureIntervalle($bg, $bd, $id_utilisateur) { $requete = 'UPDATE cel_mots_cles'.$this->suffixe_table.' '. 'SET bd = bd - '.$bd.' - 1 , '. ' bg = bg - '.$bd.' - 1 '. 'WHERE bd <= '.$bd.' '. ' AND bg >= '.$bg.' '. ' AND id_utilisateur = '.$this->proteger($id_utilisateur).' '; return $this->executer($requete); } /** * Recale les bornes dun intervalle pour l'inclure dans l'arbre à la bonne place. * Décalage borne droite */ private function inclureIntervalle($bg, $bd, $decalage,$modif_niveau, $id_utilisateur) { $requete = 'UPDATE cel_mots_cles'.$this->suffixe_table.' '. 'SET bg = bg + '.$decalage.' , '. ' bd = bd + '.$decalage.', '. ' niveau = niveau + '.$modif_niveau.' '. ' WHERE bg >= '.$bg.' '. ' AND bd <= '.$bd.' '. ' AND id_utilisateur = '.$this->proteger($id_utilisateur).' '; return $this->executer($requete); } private function changerPere($id_mot_cle, $id_pere, $id_utilisateur) { $requete = 'UPDATE cel_mots_cles'.$this->suffixe_table.' '. 'SET ce_mot_cle'.$this->suffixe_champ.'_parent = '.$this->proteger($id_pere).' '. 'WHERE id_mot_cle'.$this->suffixe_champ.' = '.$this->proteger($id_mot_cle).' '. ' AND id_utilisateur = '.$this->proteger($id_utilisateur).' '; return $this->executer($requete); } } ?>