Passage de paramètres aux hooks dans les fonctions de plxShow

bazooka07bazooka07 PluXml Lead Developer, Moderator
Bonjour,

Le passage de paramètres aux hooks est très bien expliqué dans le guide du développeur (PluXml_-_Plugins_Guide_du_developpeur.pdf) à la page 58.

Hélas si on regarde dans la librairie de PluXml le script class.plx.show.php, on s'aperçoie que toutes les fonctions qui appellenet les hooks des plugins ne passent aucun paramètre.Dans un terminal, il suffit de passer la commande suivante pour s'en apercevoir :
[== Indéfini ==]
grep -nB2 callHook class.plx.show.php
Vous pouvez voir le résultat de cette commande sur le fichier que j'ai mis en partage sur Google Drive : plxShow-callHook-140206.txt

Par exemple, c'est ennuyeux pour répondre à certains appels de hooks comme ''plxShowMeta" :
[== PHP ==]
	public function meta($meta='') {
249-		# Hook Plugins
250:		if(eval($this->plxMotor->plxPlugins->callHook('plxShowMeta'))) return;
--
La fonction plxShow->meta est appelé 3 fois dans le template static.php avec une valeur de $meta différente à chaque fois.
En conséquence, il faut faire des touts de passe-passe dans le hook des plugins en renvoyant du code à parser comme dans le plugin plxMyContact que j'ai commencé à ré-écrire et que vous pouvez également trouver sur Google Drive : plxMyContact.php

il faut que cette fonction soit écrite dans la classe class.plx.show.php comme ceci :
[== PHP ==]
	public function meta($meta='') {
249-		# Hook Plugins
250:		if ($this->plxMotor->plxPlugins->callHook('plxShowMeta', $meta)) return;
--
Le hook appelé pourrait retourner une valeur true ou false sans avoir de code php à parser.
Il y a beaucoup de fonctions comme cela pour la classe plxShow.

Dans une moindre mesure, le problème se pose pour la classe plxMotor.

Cela donne une écriture de plugin plus correcte en évitant de retourner des bouts de codes php à parser.

A++

Réponses

  • StéphaneStéphane Member, Former PluXml Project Manager
    Bonjour

    Je t'avoue ne pas comprendre la description du problème que tu fais.
    Est-ce que ce qui te pose problème est le fait le code après l'appel de la ligne suivante soit executée à chaque fois ?
    if(eval($this->plxMotor->plxPlugins->callHook('plxShowMeta'))) return;
    

    Si c'est ça, je te renvoie à la page 50 de la doc des plugins.
    Dans le code de ton plugin qui traite ton hook, en faisant un [em]return true;[/em] le code suivant l'appel du hook ne sera pas executé. Ce qui évite d'avoir du code php évalué inutilement

    exemple:
    public function plxMotorDemarrageBegin(){
    	$string = <<<END
    	<?php
    if(\$this->mode=="galerie"){
    	\$this->template = 'galerie.php';
    	return true;
    }
    ?>
    END;
    	echo $string;
    }
    

    Consultant PluXml

    Ancien responsable du projet (2010 à 2018)

  • bazooka07bazooka07 PluXml Lead Developer, Moderator
    Bonjour Stéphane,

    J'ai bien compris qu'il fallait que le hook de mon plugin renvoie le code à évaluer "<?php return true; ?>" pour stopper l'interprétation du code dans la fonction qui l'a appelé. Mais le problème n'est pas là.

    Dans la classe plxPlugins, la fonction membre callHook($hookName, $parms=null) transmet bien le paramètre $parms au hook qu'il appelle (voir à partir de la ligne n°83 pour la version 5.3 de PluXml). Cela est ok !

    C'est en amont que cela bloque :
    Dans la classe plxShow, la fonction function meta($meta='') ne transmet pas le paramètre $meta à l'appel de la fonction de classe $plxMotor->plxPlugins->callHook. Voici l'extrait de code de class.plx.show.php qui ne fait pas bien le job (à partir de la ligne 248) :
    [== PHP ==] // function original
    	public function meta($meta='') {
    		# Hook Plugins
    		if(eval($this->plxMotor->plxPlugins->callHook('plxShowMeta'))) return;
    
    Pour être correct, l'appel de la fonction de classe devrait se faire comme ceci :
    [== PHP ==]  // modif proposée
    		if(eval($this->plxMotor->plxPlugins->callHook('plxShowMeta', $meta))) return;
    

    Dans le template header.php, la fonction $plxShowMeta est appelée 3 fois avec un paramètre différent (à partir de la ligne 7) :
    [== PHP ==]
    <title><?php $plxShow->pageTitle(); ?></title>
    <?php $plxShow->meta('description') ?>
    <?php $plxShow->meta('keywords') ?>
    <?php $plxShow->meta('author') ?>
    
    Comment le hook 'plxShowMeta' du plugin peut-il renvoyer la bonne réponse en fonction de $parms lorsqu'il est appelé 3 fois de suite ?

    Je cite $plxShow->meta en exemple mais cela vaut pour les autres fonctions qui appellent callHook.

    A+++
  • Jerry WhamJerry Wham Member
    février 2014 modifié
    @bazooka07 : ça fonctionne avec le code suivant:
    Soit le plugin myPlug, écrit dans le fichier myPlug.php, qui contient le code suivant :
    class myPlug extends plxPlugin {
    
    	/**
    	 * Constructeur de la classe maj
    	 *
    	 * @param	default_lang	langue par défaut utilisée par PluXml
    	 * @return	null
    	 * @author	Stephane F
    	 **/
    	public function __construct($default_lang) {
    
    		# Appel du constructeur de la classe plxPlugin (obligatoire)
    		parent::__construct($default_lang);
    
    		# Déclarations des hooks
    		$this->addHook('plxShowMeta', 'plxShowMeta');
    	}
    
    	public function plxShowMeta($value=array()) {
    		$string = <<<END
    		echo '$value[0]';
    		echo '$value[1]';
    		echo '$value[2]';
    		echo '$value[3]';
    		echo '$value[4]';
    		return true;
    END;
    		echo '<?php '.$string.'?>';
    	}
    }
    
    et dans un fichier du thème (page non statique pour laquelle il faudrait instancier plxShow) :
    $params=array('coucou'); 
    eval($plxShow->callHook('plxShowMeta',$params));
    
    affichera
    coucou
    
    $params=array('coucou','salut'); 
    eval($plxShow->callHook('plxShowMeta',$params));
    
    affichera
    coucousalut
    

    Pourquoi ça fonctionne ?

    myPlug est ici une extension de plxPlugin, c'est à dire qu'il hérite des méthodes de ce dernier.
    Le constructeur de myPlug utilise la méthode addHook de plxPlugin pour ajouter le hook plxShowMeta au tableau des hooks disponibles, c'est à dire qu'il ajoute la fonction utilisateur (ici elle porte le même nom que le hook à savoir plxShowMeta mais on aurait pu l'appeler par exemple myPlugMeta. On aurait alors écrit dans le constructeur : $this->addHook('plxShowMeta', 'myPlugMeta');) définie dans le plugin avec ses paramètres éventuels.

    $plxShow est une extension de plxMotor qui instancie une instance de plxPlugins dans son constructeur. Il peut donc utiliser la méthode callHook de plxPlugins.
    Celle-ci possède deux paramètres : $hookName qui est le nom du hook et qui est obligatoire et $parms qui est null par défaut donc optionnel.
    $hookName est en fait la méthode que l'on a définie dans notre plugin (ici plxShowMeta mais qu'on aurait pu l'appeler myPlugMeta). Elle possède des paramètres. Ils seront donc utilisés lors de l'appel du hook.

    Comme tu l'as dit, afin de ne pas exécuter le code suivant le plugin, il faut faire un retour positif (return true) pour que le hook fonctionne correctement et ne renvoie pas d'erreur.

    Pour résumer, ce n'est pas le hook qui passe les paramètres, mais la méthode que tu auras définie dans ton plugin qui elle aura des paramètres (éventuellement).

    Si Stéphane pouvait confirmer que je ne me suis pas trompé dans mon explication on aurait une vision exhaustive du fonctionnement de l'appel des hooks.
  • bazooka07bazooka07 PluXml Lead Developer, Moderator
    @Jerry Wham,

    Si on regarde la déclaration dans le script class.plx.show.php, la classe plxShow n'est pas une extension de plxMotor.
    Mais plxMotor est une propriété de plxShow.
    Dans le fichier du thème, pour reprendre ton code, il faut donc écrire :
    [== PHP ==]
    $params = 'coucou';
    eval($plxShow->plxMotor->plxPlugins->callHook('plxShowmeta', $params));
    
    En passant, $params peut être de type null, string ou array.

    Mais reprendre le code de la function $plxShow->meta($params='') comme je l'ai proposé au début me semble plus simple et plus élégant.
    Pour te rassurer, les 2 méthodes marchent.
  • Ah oui, pardon. J'ai parlé un peu vite et de mémoire. Merci pour la correction.
    Pour $params, le type initial est null. Le transtypage de php fait que l'on peut lui appliquer n'importe quel type ensuite.

    Ensuite, pour ta méthode, je pense que c'est moins universel vis à vis de la façon d'utiliser les plugins de Pluxml.
    Disons que la méthode utilisée par Stéphane peut être transposée à toutes les classes pour tous les plugins, qu'ils aient ou non besoin de paramètres. Je ne suis pas sûr que la tienne le puisse.
  • bazooka07bazooka07 PluXml Lead Developer, Moderator
    Plus c'est universel, plus c'est permissif.

    Pour être universel, tu donnes presque la solution :
    [== PHP ==]
    class myPlug extends plxPlugin {
    
    		public function __construct($default_lang) {
    
    		# Appel du constructeur de la classe plxPlugin (obligatoire)
    		parent::__construct($default_lang);
    
    		# Déclarations des hooks
    		$this->addHook('plxShowMeta', 'plxShowMeta');
    	}
    
    	public function plxShowMeta($param='') {
    		
    		// code qui fait le job
    		echo '<?php return true; ?>';
    	}
    }
    
    Selon les appels, $param sera null, string ou array.
    A méditer pour la prochaine release de PluXml ;)
  • Ce n'est pas presque, c'est la solution. Et c'est déjà ce que Pluxml propose. Relis mon explication. eval permet d'exécuter le code là où on en a besoin.
Connectez-vous ou Inscrivez-vous pour répondre.