Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?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
- protected static $registeredEvents = array();
- // Prévenir que cet objet écoute cet évènement
- public static function register(EventListener $listener, $eventName)
- {
- if (!isset(Events::$registeredEvents[$eventName])) {
- Events::$registeredEvents[$eventName] = array();
- }
- if (!Events::isRegistered($eventName, $listener)) {
- Events::$registeredEvents[$eventName][] = $listener;
- return true;
- }
- return false;
- }
- // L'évènement est-il enregistré pour l'objet donné ?
- public static function isRegistered($eventName, EventListener $listener)
- {
- 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é
- public static function getListeners($eventName)
- {
- if (isset(Events::$registeredEvents[$eventName])) {
- return Events::$registeredEvents[$eventName];
- } else {
- return array();
- }
- }
- // Effacer l'écoute d'un évènement
- public static function unregister(EventListener $listener, $eventName)
- {
- unset(Events::$registeredEvents[$eventName][$listener->getUUID()]);
- return true;
- }
- // Notification d'un évènement de manière globale
- // Retourne l'évènement (modifié, voir $event->getReturnValue() et $event->getProcessed())
- public static function notifyGlobal($eventName, $settings = array())
- {
- $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
- public static function notify(EventListener $listener, $eventName, $settings = array())
- {
- $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
- protected $callbacks = array();
- // Universal Unique ID
- protected $UUID = null;
- // Retourne un identifiant unique pour l'objet
- public function getUUID()
- {
- if (is_null($this->UUID)) {
- $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);
- unset($this->callbacks[$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)
- {
- if (isset($this->callbacks[$event->getName()])) {
- $callback = $this->callbacks[$event->getName()];
- if (!is_callable($callback)) {
- throw new EventCallbackError("Cannot run " . (is_array($callback) ? $callback[0].'::'.$callback[1] : $callback));
- } else {
- $event->setProcessed($this);
- $return = call_user_func($callback, $event);
- $event->setReturnValue($this, $return);
- }
- }
- }
- }
- // Classe décrivant un évènement
- class Event
- {
- /* string */ protected $name = '';
- /* array */ protected $settings = array();
- /* array */ public $returnValues = array();
- /* array */ protected $processors = array();
- // Constructeur : nom, paramètres supplémentaires
- public function __construct($name, $settings = array())
- {
- $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;
- while (($pos = strpos($name, '.')) !== false) {
- $index = substr($name, 0, $pos);
- if (isset($settings[$index])) {
- $settings = $settings[$index];
- $name = substr($name, $pos+1);
- } else {
- return $default;
- }
- }
- if (isset($settings[$name])) {
- 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()
- {
- return count($this->processors);
- }
- // 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)
- {
- if (is_null($listener)) {
- $lastNotNull = null;
- foreach ($this->returnValues as $value) {
- if (!is_null($value)) {
- $lastNotNull = $value;
- }
- }
- return $lastNotNull;
- } else {
- return $this->returnValues[$listener->getUUID()];
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement