Extension de fonctionnalités » History » Revision 7
Revision 6 (Simon, 07/04/2012 09:48 AM) → Revision 7/10 (Simon, 07/04/2012 09:52 AM)
{{>toc}}
h2. Généralités
Le système de plugins est conçu autour du composant "Event Dispatcher du framework symfony":http://components.symfony-project.org/event-dispatcher/documentation, basé sur le concept d'"Observer pattern":http://fr.wikipedia.org/wiki/Observateur_%28patron_de_conception%29.
A l'exception des classes systèmes externes et dela classe _culture_, les classes peuvent être étendues par le système de plugin et la fonction magique __call(). (voir "documentation":http://components.symfony-project.org/event-dispatcher/trunk/book/02-Recipes#chapter_02_adding_methods_to_a_class)
h2. Extension des fonctionnalités de l'application
Il est, via le [[Systeme de Plugins|système de plugins]], aisé d'écouter un événement pour exécuter une nouvelle action lors de son appel.
Nous allons par exemple créer un plugin qui logguera chaque tentative d'authentification.
La fonction _AuthenthificationProcess()_ dans le fichier _/lib/functions_auth.php_ déclare l'événement *authentication.main_authentication* :
<pre>
<code class="php">
function AuthenthificationProcess($login, $pass, $type)
{
// Notify the beginning of the current method
global $dispatcher;
$dispatcher->notify(new sfEvent(__FUNCTION__, 'authentication.main_authentication', array('login' => $login, 'password' => $pass, 'type' => $type)));
// .....
// Processus d'authentification
}
</code>
</pre>
Le fichier __init__.php du nouveau plugin devra contenir les instructions suivantes :
<pre>
<code class="php">
// Log de l'authentification dans [path to app]/tmp
function logAction(sfEvent $event) {
$a[0]= $event['login']. " s'est authentifé le ".date('d/n/Y à H:i:s')." depuis ". $event['type'];
logfile(SITE_PATH.'/tmp/auth.log', $a);
}
// Execute la fonction logAction lorsque l'événement authentication.main_authentication est notifié
$dispatcher->connect('authentication.main_authentication', 'logAction');
</code>
</pre>
Votre plugin est terminé! Chaque fois qu'un utilisateur s'authentifiera, le fichier _auth.log_ sera renseigné.
h2. Ajout d'une méthode grâce à la fonction magique __call()
La fonction magique __call() permet de traiter les méthodes non déclarées dans la classe. Couplée avec le motif de conception observeur/observable, elle va nous permettre d'étendre la classe.
Remarque : L'événement créé par Linea21 se nomme *[nom_de_la_class].extensible_function*.
A titre d'illustration, voici un exemple d'implémentation sur le module News (qui gère l'actualité) :
<pre><code class="php">
public function __call($method, $arguments)
{
$event = $this->dispatcher->notifyUntil(new sfEvent($this, 'news.extensible_function', array(
'method' => $method,
'arguments' => $arguments
)));
if (!$event->isProcessed())
{
throw new Exception(sprintf('Call to undefined method %s::%s.', get_class($this), $method));
}
return $event->getReturnValue();
}
</code>
</pre>
Dans le <code>__init__.php</code> de mon plugin :
<pre><code class="php">
// 1 -Création de la classe extensibleNews() et ajout des méthodes
class extensibleNews
{
static public function listenToMethodNotFound(sfEvent $event)
{
switch ($event['method'])
{
case 'performAction':
self::doTest($event->getSubject(), $event['arguments']);
return true;
default:
return false;
}
}
static private function performAction($subject, $arguments)
{
if(is_string($arguments)) $msg = $arguments;
if(is_array($arguments)) $msg = join(', ', $arguments);
mail('info@xxxx.com', 'extension de Linea21', 'Voici les arguments passés à ma fonction : '. $msg);
_debug('[event/dispatcher] (INTERNAL) - we run ' . __FUNCTION__ . '() function by extensibleFunc() call with arguments : '. $msg);
}
}
// 2 - On connecte l'événement en précisant la classe et la méthode à appeler
$dispatcher->connect('news.extensible_function', array('extensibleNews', 'listenToMethodNotFound'));
// 3 - Enfin, on appelle la nouvelle méthode depuis l'objet news
// ici après un test conditionnel pour exécuter l'action sur la section 'news' seulement
if(isset($_REQUEST['rub']) && $_REQUEST['rub'] == 'news') {
include_once '../class/class.news.php';
$n = new news;
$n->performAction('arg 1', 'arg 2', 'arg 3');
}
</code>
</pre>
h2. Téléchargez le module d'exemple
Pour mieux comprendre ou pour aller plus loin, essayez vous-même en téléchargeant l'archive suivante : http://dev.linea21.com/attachments/download/26/l21_eventDispatcherSample.zip
Assurez-vous que le plugin soit bien activé. Vous pourrez observer son comportement via la barre de debug et en analysant son code source.