Posted by naholyr on Mon 12 May 11:54
report abuse | download | new post
- <?php
- // Exception lancée par notify() quand le callback n'est pas valide
- class EventCallbackError extends Exception { }
- // Registre des évènements écoutés : ce registre sait quel évènement est écouté par quel objet
- // Il permet la distribution globale d'un évènement
- // C'est ensuite l'objet lui-même qui se charge de réagir à l'évènement
- // Voir principalement register(), unregister(), notifyGlobal(), notify()
- class Events
- {
- // Les évènements, et les objets qui les écoutent
- // Prévenir que cet objet écoute cet évènement
- {
- }
- if (!Events::isRegistered($eventName, $listener)) {
- Events::$registeredEvents[$eventName][] = $listener;
- return true;
- }
- return false;
- }
- // L'évènement est-il enregistré pour l'objet donné ?
- {
- foreach (Events::getListeners($eventName) as $a_listener) {
- if ($listener->getUUID() == $a_listener->getUUID()) {
- return true;
- }
- }
- return false;
- }
- // Récupérer les objets écoutant l'évènement donné
- {
- return Events::$registeredEvents[$eventName];
- } else {
- }
- }
- // Effacer l'écoute d'un évènement
- {
- return true;
- }
- // Notification d'un évènement de manière globale
- // Retourne l'évènement (modifié, voir $event->getReturnValue() et $event->getProcessed())
- {
- $event = new Event($eventName, $settings);
- foreach (Events::getListeners($eventName) as $listener) {
- $listener->notifyEvent($event);
- }
- return $event;
- }
- // Notification d'un évènement à un objet donné
- // Même retour que notifyGlobal
- {
- $event = new Event($eventName, $settings);
- if (Events::isRegistered($eventName, $listener)) {
- $listener->notifyEvent($event);
- }
- return $event;
- }
- }
- // Classe décrivant un objet pouvant écouter des évènements
- // Etendre cette classe pour rendre l'objet "écoutant"
- // Appeler register() et unregister() pour écouter (ou arrêter d'écouter) un évènement et associer cet évènement à un callback
- // Appeler notify() pour exécuter l'évènement écouté
- // Une idée d'amélioration : on pourrait étendre cette classe pour autoriser l'association de plusieurs callbacks à un évènement
- class EventListener
- {
- // Callbacks associés aux évènements
- // Universal Unique ID
- protected $UUID = null;
- // Retourne un identifiant unique pour l'objet
- public function getUUID()
- {
- $this->UUID = spl_object_hash($this); // PHP 5.2 required
- }
- return $this->UUID;
- }
- // Enregistre l'évènement et lui associe un callback
- public function registerEvent($eventName, $callback)
- {
- if (Events::register($this, $eventName)) {
- $this->callbacks[$eventName] = $callback;
- return true;
- }
- return false;
- }
- // Enregistre l'évènement et lui associe un callback
- public function unregisterEvent($eventName, $callback)
- {
- Events::register($this, $eventName);
- return true;
- }
- // Reçoit l'évènement, et exécute le callback associé
- // La valeur de retour du callback est stockée dans la "ReturnValue" de l'évènement
- public function notifyEvent(Event $event)
- {
- $callback = $this->callbacks[$event->getName()];
- throw new EventCallbackError("Cannot run " . (is_array($callback) ? $callback[0].'::'.$callback[1] : $callback));
- } else {
- $event->setProcessed($this);
- $event->setReturnValue($this, $return);
- }
- }
- }
- }
- // Classe décrivant un évènement
- class Event
- {
- /* string */ protected $name = '';
- // Constructeur : nom, paramètres supplémentaires
- {
- $this->name = $name;
- $this->settings = $settings;
- }
- // Nom de l'évènement
- public function getName()
- {
- return $this->name;
- }
- // Récupère un paramètre
- // Le nom peut être une chaine, ou une chaine de la forme "tableau.valeur1.valeur2" pour aller récupérer une valeur
- // de tableaux imbriqués (dans l'exemple $settings pourrait être array('tableau' => array('valeur1' => array('valeur2' => 'coucou')))
- public function get($name, $default = null)
- {
- $settings = $this->settings;
- $settings = $settings[$index];
- } else {
- return $default;
- }
- }
- return $settings[$name];
- }
- return $default;
- }
- // Retourne le nombre de fois que l'évènement a été traités (nombre d'objets l'écoutant)
- public function getProcessed()
- {
- }
- // Utilisé par l'objet écoutant pour indiquer que l'évènement a été traité
- public function setProcessed(EventListener $listener)
- {
- $this->processors[] = $listener;
- }
- // Renvoie la liste des écouteurs qui ont traité l'évènement
- public function getProcessors()
- {
- return $this->processors;
- }
- // Définit la veleur de retour pour un écouteur donné
- public function setReturnValue(EventListener $listener, $value)
- {
- $this->returnValues[$listener->getUUID()] = $value;
- }
- // Renvoie la valeur de retour du callback pour un écouteur donné
- // Si aucun écouteur n'est spécifié, on renvoie la dernière valeur de retour non null
- public function getReturnValue(EventListener $listener = null)
- {
- $lastNotNull = null;
- foreach ($this->returnValues as $value) {
- $lastNotNull = $value;
- }
- }
- return $lastNotNull;
- } else {
- return $this->returnValues[$listener->getUUID()];
- }
- }
- }
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.