Project

General

Profile

Extension de fonctionnalités » History » Version 8

Simon, 07/04/2012 09:55 AM

1 1 Simon
{{>toc}}
2
3
4
h2. Généralités
5
 
6
7 6 Simon
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.
8 1 Simon
9 5 Simon
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)
10 1 Simon
11 6 Simon
h2. Extension des fonctionnalités de l'application
12 1 Simon
13 6 Simon
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.
14 1 Simon
15 6 Simon
Nous allons par exemple créer un plugin qui logguera chaque tentative d'authentification.
16 1 Simon
17 6 Simon
La fonction _AuthenthificationProcess()_ dans le fichier _/lib/functions_auth.php_ déclare l'événement *authentication.main_authentication* : 
18
19
<pre>
20
<code class="php">
21
22
function AuthenthificationProcess($login, $pass, $type)
23
{
24
	// Notify the beginning of the current method
25
	global $dispatcher;
26
	$dispatcher->notify(new sfEvent(__FUNCTION__, 'authentication.main_authentication', array('login' => $login, 'password' => $pass, 'type' => $type)));
27
	
28
       // ..... 
29
       // Processus d'authentification
30
}
31
32
</code>
33
</pre>
34
35
Le fichier __init__.php du nouveau plugin devra contenir les instructions suivantes :
36
37
<pre>
38
<code class="php">
39
40
// Log de l'authentification dans [path to app]/tmp
41
function logAction(sfEvent $event) {
42
	$a[0]= $event['login']. " s'est authentifé le ".date('d/n/Y à H:i:s')." depuis ". $event['type'];
43
	logfile(SITE_PATH.'/tmp/auth.log', $a);
44
}
45
46
// Execute la fonction logAction lorsque l'événement authentication.main_authentication est notifié
47
$dispatcher->connect('authentication.main_authentication', 'logAction');
48
49
</code>
50
</pre>
51
52
Votre plugin est terminé! Chaque fois qu'un utilisateur s'authentifiera, le fichier _auth.log_ sera renseigné.
53
54
55
h2. Ajout d'une méthode grâce à la fonction magique __call()
56
57
58
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. 
59
60
Remarque : L'événement créé par Linea21 se nomme *[nom_de_la_class].extensible_function*.
61
62
A titre d'illustration, voici un exemple d'implémentation sur le module News (qui gère l'actualité) :
63
64 1 Simon
<pre><code class="php">
65
66 6 Simon
  public function __call($method, $arguments)
67 1 Simon
  {
68 6 Simon
    $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'news.extensible_function', array(
69
      'method'    => $method,
70
      'arguments' => $arguments
71
    )));
72
    if (!$event->isProcessed())
73
    {
74
      throw new Exception(sprintf('Call to undefined method %s::%s.', get_class($this), $method));
75
    }
76 1 Simon
77 6 Simon
    return $event->getReturnValue();
78 1 Simon
  }
79 6 Simon
80 1 Simon
</code>
81
</pre>
82
83 6 Simon
84
85 1 Simon
Dans le <code>__init__.php</code> de mon plugin :
86
87
88
<pre><code class="php">
89
90 6 Simon
// 1 -Création de la classe extensibleNews() et ajout des méthodes
91
class extensibleNews
92 1 Simon
{
93 6 Simon
	static public function listenToMethodNotFound(sfEvent $event)
94
	{
95 1 Simon
96 6 Simon
		switch ($event['method'])
97
		{
98
			case 'performAction':
99
				self::doTest($event->getSubject(), $event['arguments']);
100
				return true;
101
			default:
102
				return false;
103
		}
104
	}
105
106
	static private function performAction($subject, $arguments)
107
	{
108
                if(is_string($arguments)) $msg = $arguments;
109
                if(is_array($arguments))	$msg = join(', ', $arguments);
110
                mail('info@xxxx.com', 'extension de Linea21', 'Voici les arguments passés à ma fonction : '. $msg);
111
                _debug('[event/dispatcher] (INTERNAL) - we run ' . __FUNCTION__ . '() function by extensibleFunc() call with arguments : '. $msg);
112
	}
113
114 1 Simon
}
115 2 Simon
116 6 Simon
// 2 - On connecte l'événement en précisant la classe et la méthode à appeler
117
$dispatcher->connect('news.extensible_function', array('extensibleNews', 'listenToMethodNotFound'));
118
119
// 3 - Enfin, on appelle la nouvelle méthode depuis l'objet news
120
// ici après un test conditionnel pour exécuter l'action sur la section 'news' seulement
121
if(isset($_REQUEST['rub']) && $_REQUEST['rub'] == 'news') {
122
	include_once '../class/class.news.php';
123
	$n = new news;
124
	$n->performAction('arg 1', 'arg 2', 'arg 3');
125
}
126
127 1 Simon
</code>
128
</pre>
129 7 Simon
130
131
h2. Téléchargez le module d'exemple
132
133 8 Simon
Pour mieux comprendre ou pour aller plus loin, essayez vous-même en téléchargeant le plugin suivant : attachment:l21_eventDispatcherSample.zip
134
Installez-le et assurez-vous qu'il soit bien activé. Vous pourrez observer son comportement via la barre de debug et en analysant son code source.