Raccourcis : Contenu - rubriques - sous rubriques
FR

Piste : generic2

Création de Modules Génériques "Jelix" (partie 2/2)

(version de Jelix supportée 1.1.x)

Voici la seconde partie, de l'article Création de module génériques (1/2).

Le premier article détaillait le moyen d'ajouter facilement des Tags à ses discussions, lors de la création/modification d'une discussion.

Ici, je dispose d'une page listant des discussions et j'ai envi que les visiteurs/membres du site puissent donner une appréciation (via une note) sur le contenu de ce qu'ils lisent.

Ce article repose sur le code du module HfnuRates de l'application HaveFnuBB

Rappel

  • j'appelle module “générique” le module offrant un service ;
  • j'appelle module “utilisateur” le module exploitant ledit service.

Aparté

Une fois un formulaire enregistré, l'utilisateur est redirigé sur la page présentant la discussion ajoutée.

C'est classique !

Classique oui, mais cela est possible car tout est traité par le même module qui “sait” d'où vient l'utilisateur et où l'envoyer.

La difficulté qui se pose ici est :

je suis sur une page présentant la liste des discussions (d'un module forum), et à l'intérieure de celle-ci

j'utilise un autre module (HfnuRates) qui ne sait pas où renvoyer l'utilisateur une fois les données soumises.

On utilisera donc une astuce pour y remédier.

Fin Aparté

SECOND VOLET : HfnuRates

INGREDIENTS

  1. une zone
  2. une table (et dao)
  3. une classe métier
  4. un contrôleur

J'ouvre donc le template de ma page discussions et ajoute ce qui suit où bon me semble :

{zone 'hfnurates~rates', array('id_source'=>$id_posts'
                            'source'=>'posts',
                            'return_url'=>'havefnubb~posts:list',
                            'return_url_param'=>array('id_posts'=>$id_posts)) }
  • Q1 : {zone …} sert à quoi ?
  • R1 : la zone permet d'ajouter des portions de page à l'intérieure d'une autre.
  • Q2 : à quoi sert array() ?
  • R2 : l'array ici permet de fournir à la zone, des paramètres, qui sont dans notre présent cas :
    • 'id_source' = l'id de la table du module “utilisateur”
    • 'source' = une chaine permettant d'identifier la provenance des données
    • return_url qui contient le chemin “jelix” du module “utilisateur”
    • return_url_paramcontient des params nécessaires pour retourner au module “utilisateur”
  • Q3 : Pourquoi tous ces paramètres ?
  • R3 : Comme évoqué en aparté, HfnuRates n'est pas en mesure de savoir où renvoyer l'utilisateur une fois les données transmises.

Donc, dans le template du module “forum”, on ajoutera les paramètres de “provenance” pour qu'ensuite le module HfnuRates puisse renvoyer l'utilisateur sur la page d'où il venait !

LA ZONE

Dans la zone je récupère donc les paramètres passés, pour les assigner dans le template de la zone 'zone.rates'.

Toujours dans la zone, j'en profite pour récupérer les “notes” pour cette discussion et calculer la moyenne et l'afficher dans la zone 'zone.rates'

zone ratesZone

class ratesZone extends jZone {
 
    protected $_tplname='zone.rates';
 
    protected function _prepareTpl(){
        //get the params 
        $id_source = $this->intParam('id_source');
        $source = $this->param('source');          
        $return_url = $this->param('return_url');
        $return_url_params = $this->param('return_url_params');
        // get the rates from the class
	$rates 	= jClasses::getService('hfnurates~rates');
	$result =  $rates->getTotalRatesBySource($id_source,$source);	        
        $resultText = jLocale::get('hfnurates~main.total.of.rates') . ':'.$result->total_rates . ' ' . jLocale::get('hfnurates~main.rate') .':'. $result->avg_level;
 
        //let's assign the var to the template
	$this->_tpl->assign('id_source',$id_source);
        $this->_tpl->assign('source',$source);
	$this->_tpl->assign('result',$resultText);
        $this->_tpl->assign('return_url',$return_url);
        $this->_tpl->assign('return_url_params',$return_url_params);        
    }
}

LE TEMPLATE zone.rates

le template de la zone ressemble à ceci :

<div class="rates-result">{$result}</div>
<form id="form{$id_source}" action="{formurl 'hfnurates~default:rate_it'}" method="post">    
    <div class="post-rates">      
    <input type="hidden" value="{$id_source}" id="id_source" name="id_source"/>
    <input type="hidden" value="{$source}" id="source" name="source"/>
    <input type="hidden" value="{$return_url}" name="return_url" />    
    {foreach $return_url_params as $key => $value}
    <input type="hidden" value="{$value}" name="return_url_params[{$key}]" />
    {/foreach}
[...ici le code HTML affichant le radiobutton "star1"... ]    
    </div>
</form>
<div id="post-rates-msg"></div>

on verra plus bas que la méthode rate_it du controleur default du module hfnurates exploitera les parms return_url* pour renvoyer l'utilisateur sur la bonne page.

LA TABLE

La table du module “générique”, ici HfnuRates doit stocker les données le reliant au module “utilisateur”, ici “forum” :

CREATE TABLE `hf_rates` (	
    `id_user`   INT NOT NULL ,
    `id_source` INT NOT NULL ,
    `source`    VARCHAR(40) NOT NULL,
    `ip`        VARCHAR(80) NOT NULL,
    level FLOAT NOT NULL ,
    INDEX ( `id_user` ),
    INDEX ( `id_source` ),    
    INDEX ( `source` ),
    PRIMARY KEY rates_id (id_user,id_source,SOURCE)
);

la colonne “id_source” contiendra l'id de la discussion, et “source”, la chaine “posts”. Le reste de la table est spécifique au module HfnuRates et la clé primaire permet à un même utilisateur de mettre à jour sa note si bon lui semble.

LA CLASSE

class rates {
    // get the Rate of a given source and ID
    function getTotalRatesBySource($id_source, $source) {
       $cnx = jDb::getConnection();        
       $strQuery = 'SELECT COUNT(*) as total_rates, SUM(level) as total_level, AVG(level) as avg_level ' . 
	                ' FROM '.$cnx->prefixTable('rates'). 
	                " WHERE id_source = '".$id_source."' AND source='".addslashes($source). "' GROUP BY id_source";
        $rs = $cnx->query($strQuery);        
        $total = $rs->fetch();
 
        return $total;
    }
    // save the Rate to a given source and ID
    function saveRatesBySource($id_source, $source, $rate) {
        [...]
    }
}

LE CONTROLEUR

class defaultCtrl extends jController {
 
	function rate_it() {
		//info about the "source" from where the datas come from
		$id_source 	= $this->Intaram('id_source');
		$source		= (string) $this->param('source');		
		// the star
		$rate 		= $this->floatParam('star1');
		$rates 		= jClasses::getService('hfnurates~rates');
		$result 	= $rates->saveRatesBySource($id_source,$source,$rate);
		$rep 		= $this->getResponse('redirect');
		$rep->action= (string) $this->param('return_url');
               $rep->params= (array) $this->param('return_url_params');
		return $rep;
	}
	function rate_ajax_it() {
		//info about the "source" from where the datas come from
		$id_source 	= $this->intParam('id_source');
		$source		= (string) $this->param('source');		
 
		//check if the cancel button was selected
		if ($id_source == 0 or $source == '') return;
 
		$rate 		=  $this->floatParam('star1');
		$rates 		= jClasses::getService('hfnurates~rates');
		$rates->saveRatesBySource($id_source,$source,$rate);
                $result     = $rates->getTotalRatesBySource($id_source,$source);
                // used for Ajax response
		$rep = $this->getResponse('htmlfragment');
                $rep->addContent( jLocale::get('hfnurates~main.total.of.rates').':'.$result->total_rates . ' ' . jLocale::get('hfnurates~main.rate') .':'. $result->avg_level );
		return $rep;
	}	
}
  • La première méthode traite la soumission des données quand le Javascript n'est pas activé
  • La seconde méthode traite la soumission des données quand le Javascript est pas activé et utilise Ajax

Conclusion

Pour obtenir un module, on ne peut plus générique, la zone est l'arme absolue puisqu'elle embarque toute la mécanique nécessaire aux échanges entre les modules concernés.

Pour résumer ce qu'il faut pour qu'un module qui soit ré-exploitable à souhait :

  • une table avec 2 colonnes pour mémoriser la provenance des données du module “utilisateur”
  • une classe métier pour gérer ces données
  • une zone et son template.
  • et enfin placer {zone 'module~nomzone', array('id_source'⇒$id,'source'⇒'masource',…) } dans le template du module “utilisateur”

Revenir sur Création de module génériques (1/2)

fr/tutoriels/modules/generic2.txt · Dernière modification : 2010/09/18 15:24 de foxmask

Fils rss des changements récents dans le wiki Creative Commons License