Rev 1878 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php// declare(encoding='UTF-8');// ATTENTION ! Classe compatible uniquement avec nouveau format de bdd du cel ///*** Service de recherche et modification de l'arbre des mots clés associés à un id.* 1: Le service recoit un mot clé à ajouter à l'arbre* 2: Le service recherche l'arbre ou sous arbre correspondant au critères demandé* 3: Le service renvoie l'arbre au format json** Encodage en entrée : utf8* Encodage en sortie : utf8** Cas d'utilisation :** @author Aurélien PERONNET <aurelien@tela-botanica.org>* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>* @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]);$this->envoyerJson(self::getMotsClefs($uid[1], $uid[0]));return TRUE; // compat: pourquoi renvoyer true si vide ?}static function getMotsClefs($uid, $type) {if($type == 'obs') {return Cel::db()->requeter(sprintf('SELECT mot_cle, id_mot_cle_obs, ce_mot_cle_obs_parent'.' FROM cel_mots_cles_obs'.' WHERE id_utilisateur = %s'.' ORDER BY niveau',Cel::db()->proteger($uid)));}if($type == 'images') {return Cel::db()->requeter(sprintf('SELECT mot_cle, id_mot_cle_image, ce_mot_cle_image_parent'.' FROM cel_mots_cles_images'.' WHERE id_utilisateur = %s'.' ORDER BY niveau',Cel::db()->proteger($uid)));}/* pour extraire un mot-clef en particulier (bien que getMotsClefId() soit plus adapté:array_walk($ret,create_function('&$val, $k, $keyword','if($val["mot_cle"] != $keyword) $val = NULL;' .'else $val = $val["id_mot_cle_obs"];'),'XXX');$obsKeywordIdToDetach = array_filter($ret);$obsKeywordIdToDetach = array_pop($obsKeywordIdToDetach); */return array();}static function getMotsClefId($uid, $type, $keyword) {if($type == 'obs') {$ret = Cel::db()->requeter(sprintf('SELECT mot_cle, id_mot_cle_obs, ce_mot_cle_obs_parent'.' FROM cel_mots_cles_obs'.' WHERE id_utilisateur = %s'.' AND mot_cle = %s'.' ORDER BY niveau',Cel::db()->proteger($uid),Cel::db()->proteger($keyword) ));}if($type == 'images') {$ret = Cel::db()->requeter(sprintf('SELECT mot_cle, id_mot_cle_image, ce_mot_cle_image_parent'.' FROM cel_mots_cles_images'.' WHERE id_utilisateur = %s'.' AND mot_cle = %s'.' ORDER BY niveau',Cel::db()->proteger($uid),Cel::db()->proteger($keyword) ));}return @$ret[0]['id_mot_cle_obs'];}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 = '.Cel::db()->proteger($nouveau_nom).' , '.' md5 = '.Cel::db()->proteger($nouvel_id_general).' '.'WHERE id_mot_cle'.$this->suffixe_champ.' = '.Cel::db()->proteger($id_mot_cle).' '.' AND id_utilisateur = '.Cel::db()->proteger($id_utilisateur) ;$reussite = Cel::db()->executer($requete);if ($reussite !== false) {echo 'OK';return true;} else {return false;}} else if ($action == 'deplacement') {self::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) {self::completerTransaction();return true;} else {self::annulerTransaction();return false;}}return true;}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);$bornes = $this->calculerBornesEtNiveau($id_parent, $id_utilisateur);$borne_pere = $bornes['bd'];$niveau = $bornes['niveau'] + 1;$bg = $bornes['bd'];$bd = $bg + 1;if(!$borne_pere) return false;self::commencerTransaction();$transaction_reussie_1 = $this->decalerBornesPlusDeux($borne_pere,$id_utilisateur) ? true : false;$requete = 'INSERT INTO cel_mots_cles'.$this->suffixe_table.' '.'VALUES ( '.Cel::db()->proteger($id_mot_cle).', '.Cel::db()->proteger($id_utilisateur).', '.Cel::db()->proteger($mot_cle).', '.Cel::db()->proteger($id_mot_cle_general).', '.Cel::db()->proteger($bg).', '.Cel::db()->proteger($bd).', '.Cel::db()->proteger($niveau).', '.Cel::db()->proteger($id_parent).') ' ;$transaction_reussie_2 = Cel::db()->executer($requete);if ($transaction_reussie_1 && $transaction_reussie_2) {// on sort de self::createElement ==> JRest::(get|post) ==> JRest->created() qui fait header().// or si nous dépassons ini_get(output_buffering) nous ne pouvons plus réécrire le code de retour// HTTP, de plus, si ini_get(output_buffering) == off, nous enverrions un warning.// d'où ce clone de JRest::created();header('HTTP/1.0 201 Created');self::completerTransaction();exit;} else {// cf ci-dessus: JRest::badRequestheader('HTTP/1.0 400 Bad Request');self::annulerTransaction();exit;}return true;}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);self::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 >= '.Cel::db()->proteger($bg).' '.' AND bd <= '.Cel::db()->proteger($bd).' '.' AND id_utilisateur = '.Cel::db()->proteger($id_utilisateur).' ';$mots_cles_fils = Cel::db()->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 >= '.Cel::db()->proteger($bg).' '.' AND bd <= '.Cel::db()->proteger($bd).' '.' AND id_utilisateur = '.Cel::db()->proteger($id_utilisateur).' ';$transaction_reussie_1 = Cel::db()->executer($requete);$transaction_reussie_2 = $this->decalerBornesMoinsIntervalle($bg, $bd, $id_utilisateur) ? true : false;if ($transaction_reussie_1 !== false && $transaction_reussie_2 !== false) {self::completerTransaction();} else {self::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);return true;}private function ajouterMotCleRacine($id) {$requete = 'SELECT COUNT(*) as nb_mc '.'FROM cel_mots_cles'.$this->suffixe_table.' '.'WHERE id_utilisateur = '.Cel::db()->proteger($id).' ';$resultat = Cel::db()->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 = Cel::db()->proteger(md5($nom_racine));$id_racine = Cel::db()->proteger($id_racine);$nom_racine = Cel::db()->proteger($nom_racine);$id_utilisateur = Cel::db()->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, '') ";Cel::db()->executer($requete);}}}/*** Désactive l'auto-commit puis débute la transaction*/static function commencerTransaction() {// Désactive l'autocommit le temps de la manipulation de l'arbre$reussite_autocommit = Cel::db()->executer("SET AUTOCOMMIT = 0");// Débute une nouvelle transaction$reussite_begin = Cel::db()->executer("BEGIN");}/*** Termine la transaction puis réactive l'auto-commit*/static function completerTransaction() {// Complète la transaction$reussite_commit = Cel::db()->executer("COMMIT");// Réactive l'autocommit le temps de la manipulation de l'arbre$reussite_autocommit = Cel::db()->executer("SET AUTOCOMMIT = 1");echo 'OK';}/*** Annule la transaction et réactive l'auto-commit*/static function annulerTransaction() {// Annule la transaction$reussite_rollback = Cel::db()->executer("ROLLBACK");// Réactive l'autocommit le temps de la manipulation de l'arbre$reussite_autocommit = Cel::db()->executer("SET AUTOCOMMIT = 1");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.' = '.Cel::db()->proteger($id_mot_cle).' '.' AND id_utilisateur = '.Cel::db()->proteger($id_utilisateur).' ';$resultat = Cel::db()->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 = '.Cel::db()->proteger($id_utilisateur).' ';$reussi_1 = Cel::db()->executer($requete);// Décalage borne gauche$requete = 'UPDATE cel_mots_cles'.$this->suffixe_table.' '.'SET bg = bg + 2 '.'WHERE bg >= '.$valeur.' '.' AND id_utilisateur = '.Cel::db()->proteger($id_utilisateur).' ';$reussi_2 = Cel::db()->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 = '.Cel::db()->proteger($id_utilisateur).' ';$reussi_1 = Cel::db()->executer($requete);// Décalage borne gauche$requete = 'UPDATE cel_mots_cles'.$this->suffixe_table.' '.'SET bg = bg - '.$decalage.' '.'WHERE bg > '.$bg.' '.' AND id_utilisateur = '.Cel::db()->proteger($id_utilisateur).' ';$reussi_2 = Cel::db()->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 = '.Cel::db()->proteger($id_utilisateur).' ';$reussi_1 = Cel::db()->executer($requete);// decalage borne gauche$requete = 'UPDATE cel_mots_cles'.$this->suffixe_table.' '.'SET bg = bg + '.$decalage.' '.'WHERE bg >= '.$valeur_bornes.' '.' AND id_utilisateur = '.Cel::db()->proteger($id_utilisateur).' ';$reussi_2 = Cel::db()->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 = '.Cel::db()->proteger($id_utilisateur).' ';return Cel::db()->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 = '.Cel::db()->proteger($id_utilisateur).' ';return Cel::db()->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 = '.Cel::db()->proteger($id_pere).' '.'WHERE id_mot_cle'.$this->suffixe_champ.' = '.Cel::db()->proteger($id_mot_cle).' '.' AND id_utilisateur = '.Cel::db()->proteger($id_utilisateur).' ';return Cel::db()->executer($requete);}}?>