Résolution issue 268
Présentation de l'issue
Description de l'issue #268
Permettre l’édition des commentaires
L’admin, en plus d’avoir une option pour supprimer un commentaire peut avoir une option pour éditer le commentaire
https://framagit.org/framasoft/framadate/issues/268
Justification du choix des issues
Cette issue fait appel à plusieurs notions de Framadate, de Javascript, de la base de données, et de l’objet. Une issue idéale pour ma dernière résolution. Également, l’édition des commentaires se passe sur la même page que l’issue 237.
Voici à quoi ressemble le front :
Travail réalisé
Itération 1 : créer un bouton edit
Pour cela on analyse la page (tips), il y a déjà un bouton “suppression” et de nombreux boutons “edit” sur pollinfo.tpl “btn-edit” qui servent à éditer, soit : *titre *nom *description On rajoute donc dans tpl/part/commentslist.tpl un bouton “edit” , comme on a pu le voir précédemment le bootstrap permet de simplifier le travail .
Les types hidden servent à l’édition du “comment” pour transmettre des données .
<div class="comment" > {if $admin && !$expired} <! ici le bouton croix concernant la suppression> <button type="submit" name="delete_comment" value="{$comment->id|html}" class="btn btn-link" title="{__('Comments', 'Remove the comment')}"><span class="glyphicon glyphicon-remove text-danger"></span><span class="sr-only">{__('Generic', 'Remove')}</span></button> et l'édition <button class="btn btn-link btn-sm btn-edit" value="{$comment->id|html}" title="{__('Comments', 'Edit the comment' )}" ><span class="glyphicon glyphicon-pencil"></span><span class="sr-only">{__('Generic', 'Edit')}</span></button> {/if} {if $admin && !$expired}
<code> <div class="hidden js-comment"> <div class="input-group"> <input type="text" class="form-control" id="newcomment" name="newcomment" size="40" value="{$comment->comment|html}" /> //contient l'ancien comment, renvoie une erreur si l'utilisateur ne le modifie pas <input type="hidden" id="edit_id" name="edit_id" value="{$comment->id|html}" /> <span class="input-group-btn"> <button type="submit" class="btn btn-success" name="edit_comment" value="comment" title="{__('PollInfo', 'Save the new com')}"><span class="glyphicon glyphicon-ok"></span><span class="sr-only">{__('Generic', 'Save')}</span></button> <button class="btn btn-link btn-cancel" title="{__('PollInfo', 'Cancel the name edit')}"><span class="glyphicon glyphicon-remove"></span><span class="sr-only">{__('Generic', 'Cancel')}</span></button> //annulation </span> </code> Ce morceau ci dessus gère l'envoie et la validation, il apparait seulement lorsque le bouton édit a été sélectionné .
Itération 2 : réagir à l'évènement
C’est bien beau d’avoir un bouton “edit” mais il doit réagir dynamiquement aux évènements des utilisateurs, pour cela l’usage du Javascript est intéressant puisqu’il faut simplement modifier une petite partie de la page.
On ajoute donc dans adminstuds.js
$('#comment-form .btn-edit').on('click', function() { $('#comment-form p').hide(); $('.js-comment').removeClass('hidden'); //le fait d'enlever "hidden" devant une classe la fait apparaitre, gérer depuis le bootstrap $('.js-comment input').focus(); //place le curseur sur le menu créé return false; //permet de répéter en boucle l'évènement }); $('#comment-form .btn-cancel').on('click', function() { // ce code concerne la croix du menu ouvert $('#comment-form p').show(); $('#comment-form .js-name').addClass('hidden'); $('#comment-form .btn-edit').focus(); return false; });
Remarque suite à l'itération 2
- Actuellement, le Javascript ouvre le bouton “edit” pour tous les commentaires, il y a plusieurs pistes pour résoudre ce problème :
- avec les hiddens on a l’id de chaque comment , on peut prendre en paramètre la valeur de l’id dans le javascript
- obtenir la localisation sur la page du click
- Si l’utilisateur édite plusieurs commentaires en même temps seul le premier modifié sera pris en compte.
- en CSS et en Javascript les déclarations doivent se faire avec des # pour les classes et des . pour des ID.
Itération 3 : update dans la base de donnée
Cette itération correspond à la plus grande part de l’issue, il est intéressant de voir le wiki de Justine puisque l’on va toucher à toutes ces classes.
3.1 Adminstuds.php
Adminstuds est la page de manipulation de classe , il sert principalement à faire deux choses :
- gérer les erreurs
- faire les appels des différentes classes
On rajoute donc le code permettant de gérer les erreurs ( les différents if ) et les appels des filtres et le passage des
if (!empty($_POST['edit_comment'])) { $_POST['edit_id'];// obtention de la valeur de l'id en hidden $updated = false; $comment_id = filter_input(INPUT_POST, 'edit_id', FILTER_VALIDATE_INT); $comment = $inputService->filterComment($_POST['newcomment']); if ($comment) { $comment->comment = $comment; $updated = true; } if ($updated && $adminPollService->updatecomment($poll_id, $comment_id, $comment)) { // pour que cela soit vrai il il faut que le filtre soit bon, donc pas de / " et tout les caractères de programmation et qu'il n'y ai pas d'erreurs dans le SQL $message = new Message('success', __('adminstuds', 'Poll saved')); $notificationService->sendUpdateNotification($poll, NotificationService::UPDATE_POLL); }else { $message = new Message('danger', __('Error', 'Failed to edit the comment'));//erreur BDD } }
3.2 Adminpollservices.php
Adminstuds. fait appel à updatecomment dans adminPollservices.php qui prend en paramètres
- pollid *commentid
- comment : il s’agit ici du nouveau comment
il retourne true si l’action a été un succès
function updateComment($poll_id,$comment_id,$comment){ return $this->commentRepository->update($poll_id,$comment_id,$comment); }
A noter, on passe par la page adminpollservices car la class est en private, ce qui est important pour éviter des failles de sécurité, mais aussi pour rassembler au même endroit les fonctions concernant les manipulations sur les polls.
3.3 commentrepository.php
} public function update($poll_id,$comment_id,$comment) { return $this->connect->update(Utils::table('comment'),[ 'comment' => $comment, ],[ 'poll_id' => $poll_id, 'id' => $comment_id, ] ); } }
A noter, la syntaxe est différente pour l’usage du SQL, les classes services font différemment ; en voici une description des principales. Consultez les tips pour observer la structure de la base donnée. Avant chaque requête SQL il faut rajouter : $this→connect→une requête
La fonction update
update(Utils::table('nom de la table dans la bdd ') >['le champ a update' =>* votre nouvelle variable*] , [' champ dans la BDD '=> $votre variable depuis le php] ,[' champ dans la BDD '=> $votre variable depuis le php ]);
la fonction delete
delete (Utils::table('nom de la table dans la BDD'), ['le champ dans la bdd => *$votre variable depuis le php*'] )>0 supérieur a 0 important pour le retour
la fonction select renvoie dans un tableau $prepared la requête
$prepared = $this->prepare('SELECT 1 FROM ' . Utils::table('nom de la table') . ' WHERE champ BDD = ? AND champ BDD = ? '); $prepared->execute([$variable php, $variable PHP, ]) ; <! les variables correspond a vos ? dans l'ordre . return $prepared
La fonction insert
insert(Utils::table('nom de la table dans la bdd '),[ 'champ dans la BDD' =>$variable PHP, ' champ dans la BDD' => $variable PHP ]);
Suite
Ma résolution de l’issue n’est pas complète, il reste à faire des modifications sur le Javascript (itération 2)
Il est aussi très facile de permettre l’édition d’un commentaire si l’utilisateur vient de le publier, il faut simplement faire un appel de la fonction editcomment mais autoriser seulement pour le comment stocker dans le $smarty
Merge request
Un grand merci à Thomas !