Série : développer une extension Joomla! 3.0 - Episode 4 : plus de fonctionnalités

Written by | 01 June 2013 | Published in 2013 June
Depuis quelques mois maintenant, notre série sur le développement pour Joomla! 3.x progresse à un rythme régulier. À ce stade, vous devriez avoir une assez bonne compréhension des bases du développement d'extensions et j'espère que vous avez d'ores et déjà commencé l'écriture de votre propre code. Dans cet article, vous allez pouvoir approfondir vos connaissances en code par l'utilisation de Bootstrap dans le cadre de notre développement. N'oubliez pas de réviser vos connaissances actuelles en relisant les précédents articles de la série.

Etape 0 : préparez-vous un café

Cela fait quelques temps maintenant que nous passons ensemble quant à la mise en œuvre de notre composant. Je suis convaincu qu'à ce stade vous maîtrisez déjà la première étape de chacun des articles précédents. Avant de débuter l'écriture du code ou de structurer l'étape suivante du développement, il est important de poursuivre la routine que nous avons adoptée dès le départ. Récupérez votre tasse préférée, et remplissez la du nectar de votre choix. Si vous découvrez tout juste cette étape, je vous invite à lire chacun des précédents articles. Commencez par le début et progressez jusqu'à ces quelques lignes.
Allez-y, je vous atttends.

Ok, c'est fait ? Alors, bon retour parmi nous.
Dans cet article, nous allons étudier quelques unes des autres fonctionnalités utilisées pour Lendr. Vous remarquerez que j'ai complété le code de bon nombre de fichiers qui étaient précédemment vides. Plutôt que prendre du temps à étudier chacun d'entre eux, je préfère me concentrer sur certaines parties auxquelles nous avons ajouté de nouvelles fonctionnalités ou certains concepts. Vous devriez être en mesure de comprendre aisément le code que nous avons étudié dans les articles précédents. Nous poursuivons donc cette série avec l'écriture des différentes fenêtres modales nécessaires au bon fonctionnement du composant Lendr.

Etape 1 : création des fenêtres modales

Dans cet article, notre approche sera moins stressante car nous travaillerons sur quelques fonctionnalités additionnelles et sur certains détails. Vous remarquerez tout d'abord que nous avons ajouté différentes fenêtres modales. Nous les avons toutes créées de la même façon (en utilisant la technique Bootstrap). Afin d'entrer un peu plus dans le détail, je vais vous expliquer les deux options offertes et je décrirai l'option choisie.
Tout d'abord, vous pouvez charger une vue et une mise en page via AJAX et utiliser la méthode classique de Joomla! qui, bien qu'offrant elle aussi l'affichage d'une fenêtre modale, charge un fichier complet de vue lorsque qu'un bouton ou un lien est cliqué. C'est la méthode standard traditionnellement utilisée dans Joomla! pour l'affichage des fenêtres modales (pensez à elles un peu comme à des iframes).
La seconde méthode consiste à charger les détails de la fenêtre modale par dessus la page et ceci, après le chargement initial de la page. Cependant, la fenêtre modale (en substance, une div contenant la vue) sera masquée par défaut et donc invisible jusqu'à son activation par un lien ou un bouton cliqué.

Concernant les fenêtres modales pour Lendr, j'ai opté pour la seconde méthode et pour deux raisons.
Avec l'ajout d'une div modale dans la page à charger, et même en cachant son affichage initial, la page sera déjà intégralement chargée en une seule procédure. Vous pouvez penser que cela ralentisse le chargement de votre page, mais ce n'est quasiment pas le cas; l'ajout étant tout à fait mineur. De plus, la totalité du code html étant déjà chargé, la fenêtre modale s'affichera instantanément lorsqu'un lien ou un bouton sera cliqué. On a ainsi l'impression que la page s'est chargée incroyablement rapidement. Bien que cela soit une préférence très subjective, la rapidité d'affichage de la fenêtre est une des raisons de mon choix.
La seconde raison qui m'a fait opter pour cette méthode d'affichage des fenêtres modales, réside dans le fait qu'il n'y a que très peu de champs de données à ajouter à la fenêtre. Les données requises étant minimes, il est donc moins compliqué d'assigner "à la volée" ces variables à l'affichage modale plutôt que d'appeler une page entière via AJAX. Encore une fois, c'est une préférence très subjective mais dictée notamment par la vitesse.

Jetons un œil aux lignes de code nécessaires à l'inclusion d'une fenêtre modale dans notre page.
En premier lieu, nous allons regarder le fichier html.php pour la vue de "container". Il peut également être considéré comme étant la vue "parente" de la fenêtre modale que nous envisageons de charger.

html.php
_lend.php
book.php

J'utiliserai ce code à plusieurs reprises pour charger les fenêtres modales dans Lendr. Vous remarquerez qu'il existe deux types d'appels différents pour charger ces fenêtres. Le premier est un chargement direct de la fenêtre modale (lorsque aucune donnée supplémentaire n'est nécessaire dans la fenêtre modale) et le second utilise un appel javascript pour charger la fenêtre (j'utiliserai cette seconde méthode lorsque je veux ajouter une variable à la fenêtre modale avant son affichage).

Retrouvez les autres fichiers pour fenêtres modales (la structure est identique pour tous) sur notre dépôt GitHub.

Etape 2 : l'écriture de la fonctionnalité de prêt et de retour de prêt

Maintenant que nos fenêtres modales sont en mesure de se charger et d'afficher des informations complémentaires, nous allons commencer l'ajout de fonctionnalités pour Lendr par l'utilisation des ces fenêtres. Premièrement, nous examinerons la procédure de base du noyau pour traiter le prêt et le retour de prêt. Si vous vous inquiétez quant à cette fonctionnalité, je me dois de vous rassurer en précisant que nous n'allons pas ici créer un système de suivi et de surveillance trop poussé (cela pourra faire l'objet d'une étude ultérieure plus détaillée en fonction de vos demandes). Dans Lendr, nous allons simplement vous permettre de prêter un livre et de le signaler comme étant rendu lorsque celui-ci vous sera restitué.
Deux fichiers sont associés à la procédure de prêt et de retour de prêt. Examinons-les en détail :

Contrôleur

En premier lieu, examinons le fichier contrôleur lend.php qui sert de contrôleur principal pour le prêt comme pour le retour.

joomla_root/components/com_lendr/controllers/lend.php

?php defined( '_JEXEC' ) or die( 'Restricted access' ); 
 
class LendrControllersLend extends JControllerBase
{
  public function execute()
  {
 
    $return = array("success"=>false);
 
    $model = new LendrModelsBook();
    if ( $row = $model->lend() )
    {
      $return['success'] = true;
      $return['msg'] = JText::_('COM_LENDR_BOOK_LEND_SUCCESS');
 
    }else{
      $return['msg'] = JText::_('COM_LENDR_BOOK_LEND_FAILURE');
    }
 
    echo json_encode($return);
 
  }
}

Modèle

Dans le contrôleur, une fois encore, nous nous n'exécutons qu'une seule tâche (execute) qui transmet les données et la demande directement au modèle book qui va gérer l'appel de la fonction de prêt. Voici la fonction de prêt dans le modèle book :

joomla_root/components/com_lendr/models/book.php

public function lend($data = null)
  {
    $data = isset($data) ? $data : JRequest::get('post');
 
    if (isset($data['lend']) && $data['lend']==1)
    {
      $date = date("Y-m-d H:i:s");
 
      $data['lent'] = 1;
      $data['lent_date'] = $date;
      $data['lent_uid'] = $data['borrower_id'];
 
      $waitlistData = array('waitlist_id'=> $data['waitlist_id'], 'fulfilled' => 1, 'fulfilled_time' => $date, 'table' => 'Waitlist');
      $waitlistModel = new LendrModelsWaitlist();
      $waitlistModel->store($waitlistData);
    } else {
      $data['lent'] = 0;
      $data['lent_date'] = NULL;
      $data['lent_uid'] = NULL;
    }
    
    $row = parent::store($data);    
    
    return $row;
 
  }

Dans cette fonction, vous remarquerez que nous traitons à la fois le prêt et le retour de prêt. De plus, lorsque le prêt est effectué avec succès, nous validons dans la liste d'attente correspondante l'élément comme étant réalisé.

Javascript

Voici les fonctions javascript associées aux fonctionnalités de prêt et de retour de prêt. Comme je vous l'ai indiqué précédemment, je vais commencer par créer une fonction pour charger la fenêtre modale (ainsi je suis en mesure de lui injecter des variables). La deuxième fonction est utilisée pour le prêt du livre. J'utilise un appel jQuery AJAX pour transmettre les données du formulaire au contrôleur de prêt (voir ci-dessus). Si le contrôleur/modèle s'exécute avec succès, alors la fenêtre modale se fermera.

joomla_root/components/com_lendr/assets/js/lendr.js

function loadLendModal(book_id, borrower_id, borrower, waitlist_id)
{
  jQuery("#lendBookModal").modal('show');
  jQuery('#borrower_name').html(borrower);
  jQuery("#book_id").val(book_id);
  jQuery("#borrower_id").val(borrower_id);
  jQuery("#waitlist_id").val(waitlist_id);
}
 
function lendBook()
{
  var lendForm = {};
  jQuery("#lendForm :input").each(function(idx,ele){
    lendForm[jQuery(ele).attr('name')] = jQuery(ele).val();
  });
  
  jQuery.ajax({
    url:'index.php?option=com_lendr&controller=lend&format=raw&tmpl=component',
    type:'POST',
    data:lendForm,
    dataType:'JSON',
    success:function(data)
    {
      if ( data.success )
      {
        jQuery("#lendBookModal").modal('hide');
      }
    }
  });
}

Vous pouvez remarquer l'absence de messages d'erreur à de nombreux endroits. Nous les écrirons tous en une seule fois et cela fera l'objet d'un prochain article à venir.

Etape 3 : ajouter des listes d'envie, listes d'attente et des commentaires

Nous allons travailler sur trois éléments en relation avec les livres. Les fonctionnalités de liste d'envie et de liste d'attente, sont relativement simples. Toutes deux vont constituer simplement au chargement d'une fenêtre modale afin d'ajouter le livre en question soit : à la liste d'envie, soit : à la liste d'attente de l'utilisateur. Encore une fois, ce code est en plusieurs point similaire au code pour fenêtres modales et ceux listés plus haut. Le code concernant la fonctionnalité des commentaires nécessitant un peu plus de travail personnalisé que les deux autres, nous allons nous concentrer sur celui-ci.

Retrouvez le code pour la liste d'envie et celui de la liste d'attente sur notre dépôt GitHub.

A l'origine, mon intention était d'utiliser le contrôleur de commentaire pour les nouveaux commentaires mais, après mure réflexion, j'ai décidé que techniquement, un nouveau commentaire devrait suivre le même contrôleur "add" (Ajouter) que d'autres parties du système. Cela impose une réécriture partielle du contrôleur "add" afin que les données soient correctement acheminées vers le bon modèle.

Un commentaire est crée depuis une fenêtre modale. La fenêtre affiche un formulaire contenant le titre et le résumé du commentaire. Des champs masqués permettent de suivre le livre et l'utilisateur qui soumet le commentaire. Voici le formulaire pour un nouveau commentaire :

joomla_root/components/com_lendr/views/review/tmpl/_add.php

<div id="newReviewModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="newReviewModal" aria-hidden="true">
  <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
    <h3 id="myModalLabel"<>?php echo JText::_('COM_LENDR_ADD_REVIEW'); ?></h3>
  </div>
  <div class="modal-body">
  <div class="row-fluid">
    <form id="reviewForm">
      <input class="span12" type="text" name="title" placeholder="<?php echo JText::_('COM_LENDR_TITLE'); ?>" />
      <textarea class="span12" placeholder="<?php echo JText::_('COM_LENDR_SUMMARY'); ?>" name="review" rows="10"</textarea>
      <input type="hidden" name="user_id" value=">?php echo $this->user->id; ?>" />
      <input type="hidden" name="view" value="review" />
      <input type="hidden" name="book_id" value="<?php echo $this->book->book_id; ?>" />
      <input type="hidden" name="model" value="review" />
      <input type="hidden" name="item" value="review" />
      <input type="hidden" name="table" value="review" />
    </form>
  </div>
  </div>
  <div class="modal-footer">
    <button class="btn" data-dismiss="modal" aria-hidden="true"><?php echo JText::_('COM_LENDR_CLOSE'); ?<>/button>
    <button class="btn btn-primary" onclick="addReview()"><?php echo JText::_('COM_LENDR_ADD'); ?></button>
  </div>
</div>
Note : Nous récupérons la table et d'autres champs nécessaires pour les passer au modèle et fonction appropriés.

Ci-dessous le javascript associé au processus des commentaires :

joomla_root/components/com_lendr/assets/js/lendr.js

//add a review
function addReview()
{
  var reviewInfo = {};
  jQuery("#reviewForm :input").each(function(idx,ele){
    reviewInfo[jQuery(ele).attr('name')] = jQuery(ele).val();
  });
 
  jQuery.ajax({
    url:'index.php?option=com_lendr&controller=add&format=raw&tmpl=component',
    type:'POST',
    data:reviewInfo,
    dataType:'JSON',
    success:function(data)
    {
      if ( data.success ){
        console.log(data.html);
        jQuery("#review-list").append(data.html);
        jQuery("#newReviewModal").modal('hide');
      }else{
 
      }
    }
  });
}

Dans cette fonction, nous réalisons deux actions. Tout d'abord, nous utilisons une astucieuse boucle JQuery afin de récupérer toutes les données du formulaire et les faire transiter par le contrôleur. Après la soumission du formulaire, nous attendons la répone. Si la réponse est existe, alors nous ajoutons la réponse à la liste des commentaires et masquons la fenêtre modale. Cela signifie que nous passons l'intégralité du html depuis l'appel Ajax. Ci-dessous, la façon dont ceci est traité par notre contrôleur mis à jour.

joomla_root/components/com_lendr/controllers/add.php

<?php defined( '_JEXEC' ) or die( 'Restricted access' ); 
class LendrControllersAdd extends JControllerBase
{
  public function execute()
  {
    $app      = JFactory::getApplication();
    $return   = array("success"=>false);
 
    $modelName  = $app->input->get('model', 'Book');
    $view       = $app->input->get('view', 'Book');
    $layout     = $app->input->get('layout', '_entry');
    $item       = $app->input->get('item', 'book');
 
    $modelName  = 'LendrModels'.ucwords($modelName);
 
    $model = new $modelName();
    if ( $row = $model->store() )
    {
      $return['success'] = true;
      $return['msg'] = JText::_('COM_LENDR_SAVE_SUCCESS');
      $return['html'] = LendrHelpersView::getHtml($view, $layout, $item, $row);
    }else{
      $return['msg'] = JText::_('COM_LENDR_SAVE_FAILURE');
    }
    echo json_encode($return);
  }
}

Le html retourné au javascript est chargé depuis le fichier Helper. Vous remarquerez que nous passons directement la vue, la mise en page, l'élément et les données par la fonction getHtml. A ce stade, il est donc nécessaire de reprendre la fonction du fichier helper concernant ce getHtml.

joomla_root/components/com_lendr/helpers/view.php

function getHtml($view, $layout, $item, $data)
{
  $objectView = LendrHelpersView::load($view, $layout, 'phtml');
  $objectView->$item = $data;
  
  ob_start();
   echo $objectView->render();
   $html = ob_get_contents();
  ob_clean();
    
  return $html;
}

Cette vue a un double objectif. Tout d'abord, elle charge une vue partielle située plus haut dans le fichier View helper, puis, une fois chargée, elle passe cette vue à une variable. Cette variable est alors retournée pour être transmise au javascript qui à son tour va l'ajouter à la page.

Nous terminons ainsi le processus concernant notre fonctionnalité de commentaires.
Vous pouvez retrouver directement tous les fichiers associés sur notre dépôt GitHub.

Etape 4 : rechercher des livres

La fonctionnalité de recherche est très intéressante à étudier. Une nouvelle fois, deux options s'offrent à vous.
Vous pouvez soit intégrer un système complet et autonome de recherche dans votre composant, soit tirez avantage du système préexistant de Joomla! avec son composant (Finder), module et ses plugins de recherche.
Bien qu’il ne soit pas toujours approprié d’utiliser le système de recherche natif, nous allons choisir cette option afin de l'intégrer au composant Lendr. En agissant ainsi, nous réduisons la quantité de code et simplifions la structure de Lendr. De plus, nous serons également en mesure d’étudier le code nécessaire pour la création d’un plugin dont la finalité sera d’ajouter un nouveau type de contenu à la fonctionnalité native de recherche.

Le plugin que j'ai écrit pour l'ajout à la fonctionnalité native de recherche est très simple et ne couvre certainement pas l'ensemble des fonctionnalités types d'un plugin système. Voici le fichier XML associé au plugin de recherche que nous avons écrit (je l'ai appelé Smart Search - Books)

books.xml
books.php

Ces fonctions sont utilisées par le Finder pour indexer la bonne table, charger les données et les acheminer correctement dans les résultats de recherche. Au regard du niveau souhaité pour ce tutoriel, je ne détaillerai pas chacune des fonctionnalités supplémentaires, fonctions utilisées ni les chemins secondaires des fichiers helpers qui sont souvent utilisés pour la définition d'une langue spécifique. Si vous souhaitez en apprendre plus sur le plugin système de recherche, laissez moi un message dans les commentaires ou contactez-moi pour plus d'informations.

Etape 5 : en conclusion

Dans cet article, nous avons abordé différentes fonctions, la structure du design et quelques idées additionnelles qui peuvent aussi bien être appliquées à d'autres composants que Lendr.
Nous avons examiné comment utiliser au mieux Bootstrap pour les fenêtres modales, nous avons étudié plus en détail les fonctions javascript ainsi que leur utilisation, puis nous avons élargi notre champ d'application avec l'intégration d'un plugin secondaire. Volontairement, je n'ai pas inclus ici l'intégralité des fichiers écrits ni toutes les fonctions modifiées afin, tout simplement, de nous focaliser sur le principal objectif de cet article : le processus de raisonnement et les concepts généraux dans le cadre du développement d'un composant. J'ai ainsi mis de côté le traitement de fonctions spécifiques, qui ont d'ailleurs pu être abordées dans les articles précédents.
Si pour quelque raison que ce soit, vous avez des questions concernant le présent code, n'hésitez pas à me les poser.

Dans le prochain article, nous allons commencer la finalisation du code. Nous couvrirons les sujets concernant l'interface d'administration, l'utilisation des mises à jour en direct sur la page lorsqu'un appel Ajax est terminé et nous commencerons à nettoyer notre code, à supprimer les fichiers inutiles et étudierons les différentes possibilités pour simplifier ou réduire notre code.

Téléchargement

Téléchargez le composant (tel qu'il existe à cette étape) depuis le dépôt GitHub

Téléchargement

Visitez le site tutoriel complet: http://lendr.sparkbuilt.com/

Ressources :

lendr.sparkbuilt.com

Dans la série :

Read 17419 times Tagged under French