Advertisement
Guest User

naholyr

a guest
May 12th, 2008
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 7.76 KB | None | 0 0
  1. <?php
  2.  
  3. // Exception lancée par notify() quand le callback n'est pas valide
  4. class EventCallbackError extends Exception { }
  5.  
  6. // Registre des évènements écoutés : ce registre sait quel évènement est écouté par quel objet
  7. // Il permet la distribution globale d'un évènement
  8. // C'est ensuite l'objet lui-même qui se charge de réagir à l'évènement
  9. // Voir principalement register(), unregister(), notifyGlobal(), notify()
  10. class Events
  11. {
  12.  
  13.     // Les évènements, et les objets qui les écoutent
  14.     protected static $registeredEvents = array();
  15.  
  16.     // Prévenir que cet objet écoute cet évènement
  17.     public static function register(EventListener $listener, $eventName)
  18.     {
  19.         if (!isset(Events::$registeredEvents[$eventName])) {
  20.             Events::$registeredEvents[$eventName] = array();
  21.         }
  22.        
  23.         if (!Events::isRegistered($eventName, $listener)) {
  24.             Events::$registeredEvents[$eventName][] = $listener;
  25.            
  26.             return true;
  27.         }
  28.        
  29.         return false;
  30.     }
  31.    
  32.     // L'évènement est-il enregistré pour l'objet donné ?
  33.     public static function isRegistered($eventName, EventListener $listener)
  34.     {
  35.         foreach (Events::getListeners($eventName) as $a_listener) {
  36.             if ($listener->getUUID() == $a_listener->getUUID()) {
  37.            
  38.                 return true;
  39.             }
  40.         }
  41.        
  42.         return false;
  43.     }
  44.    
  45.     // Récupérer les objets écoutant l'évènement donné
  46.     public static function getListeners($eventName)
  47.     {
  48.         if (isset(Events::$registeredEvents[$eventName])) {
  49.        
  50.             return Events::$registeredEvents[$eventName];
  51.         } else {
  52.        
  53.             return array();
  54.         }
  55.     }
  56.    
  57.     // Effacer l'écoute d'un évènement
  58.     public static function unregister(EventListener $listener, $eventName)
  59.     {
  60.         unset(Events::$registeredEvents[$eventName][$listener->getUUID()]);
  61.        
  62.         return true;
  63.     }
  64.    
  65.     // Notification d'un évènement de manière globale
  66.     // Retourne l'évènement (modifié, voir $event->getReturnValue() et $event->getProcessed())
  67.     public static function notifyGlobal($eventName, $settings = array())
  68.     {
  69.         $event = new Event($eventName, $settings);
  70.        
  71.         foreach (Events::getListeners($eventName) as $listener) {
  72.             $listener->notifyEvent($event);
  73.         }
  74.        
  75.         return $event;
  76.     }
  77.    
  78.     // Notification d'un évènement à un objet donné
  79.     // Même retour que notifyGlobal
  80.     public static function notify(EventListener $listener, $eventName, $settings = array())
  81.     {
  82.         $event = new Event($eventName, $settings);
  83.        
  84.         if (Events::isRegistered($eventName, $listener)) {
  85.             $listener->notifyEvent($event);
  86.         }
  87.        
  88.         return $event;
  89.     }
  90.    
  91. }
  92.  
  93. // Classe décrivant un objet pouvant écouter des évènements
  94. // Etendre cette classe pour rendre l'objet "écoutant"
  95. // Appeler register() et unregister() pour écouter (ou arrêter d'écouter) un évènement et associer cet évènement à un callback
  96. // Appeler notify() pour exécuter l'évènement écouté
  97. // Une idée d'amélioration : on pourrait étendre cette classe pour autoriser l'association de plusieurs callbacks à un évènement
  98. class EventListener
  99. {
  100.  
  101.     // Callbacks associés aux évènements
  102.     protected $callbacks = array();
  103.    
  104.     // Universal Unique ID
  105.     protected $UUID = null;
  106.  
  107.     // Retourne un identifiant unique pour l'objet
  108.     public function getUUID()
  109.     {
  110.         if (is_null($this->UUID)) {
  111.             $this->UUID = spl_object_hash($this); // PHP 5.2 required
  112.         }
  113.        
  114.         return $this->UUID;
  115.     }
  116.  
  117.     // Enregistre l'évènement et lui associe un callback
  118.     public function registerEvent($eventName, $callback)
  119.     {
  120.         if (Events::register($this, $eventName)) {
  121.             $this->callbacks[$eventName] = $callback;
  122.            
  123.             return true;
  124.         }
  125.            
  126.         return false;
  127.     }
  128.    
  129.     // Enregistre l'évènement et lui associe un callback
  130.     public function unregisterEvent($eventName, $callback)
  131.     {
  132.         Events::register($this, $eventName);
  133.         unset($this->callbacks[$eventName]);
  134.        
  135.         return true;
  136.     }
  137.    
  138.     // Reçoit l'évènement, et exécute le callback associé
  139.     // La valeur de retour du callback est stockée dans la "ReturnValue" de l'évènement
  140.     public function notifyEvent(Event $event)
  141.     {
  142.         if (isset($this->callbacks[$event->getName()])) {
  143.             $callback = $this->callbacks[$event->getName()];
  144.            
  145.             if (!is_callable($callback)) {
  146.            
  147.                 throw new EventCallbackError("Cannot run " . (is_array($callback) ? $callback[0].'::'.$callback[1] : $callback));
  148.             } else {
  149.                 $event->setProcessed($this);
  150.                 $return = call_user_func($callback, $event);
  151.                 $event->setReturnValue($this, $return);
  152.             }
  153.         }
  154.     }
  155.    
  156. }
  157.  
  158. // Classe décrivant un évènement
  159. class Event
  160. {
  161.  
  162.     /* string */ protected $name = '';
  163.     /* array  */ protected $settings = array();
  164.     /* array  */ public $returnValues = array();
  165.     /* array  */ protected $processors = array();
  166.    
  167.     // Constructeur : nom, paramètres supplémentaires
  168.     public function __construct($name, $settings = array())
  169.     {
  170.         $this->name = $name;
  171.         $this->settings = $settings;
  172.     }
  173.    
  174.     // Nom de l'évènement
  175.     public function getName()
  176.     {
  177.         return $this->name;
  178.     }
  179.    
  180.     // Récupère un paramètre
  181.     // Le nom peut être une chaine, ou une chaine de la forme "tableau.valeur1.valeur2" pour aller récupérer une valeur
  182.     // de tableaux imbriqués (dans l'exemple $settings pourrait être array('tableau' => array('valeur1' => array('valeur2' => 'coucou')))
  183.     public function get($name, $default = null)
  184.     {
  185.         $settings = $this->settings;
  186.        
  187.         while (($pos = strpos($name, '.')) !== false) {
  188.             $index = substr($name, 0, $pos);
  189.             if (isset($settings[$index])) {
  190.                 $settings = $settings[$index];
  191.                 $name = substr($name, $pos+1);
  192.             } else {
  193.                 return $default;
  194.             }
  195.         }
  196.        
  197.         if (isset($settings[$name])) {
  198.        
  199.             return $settings[$name];
  200.         }
  201.        
  202.         return $default;
  203.     }
  204.    
  205.     // Retourne le nombre de fois que l'évènement a été traités (nombre d'objets l'écoutant)
  206.     public function getProcessed()
  207.     {
  208.         return count($this->processors);
  209.     }
  210.  
  211.     // Utilisé par l'objet écoutant pour indiquer que l'évènement a été traité
  212.     public function setProcessed(EventListener $listener)
  213.     {
  214.         $this->processors[] = $listener;
  215.     }
  216.    
  217.     // Renvoie la liste des écouteurs qui ont traité l'évènement
  218.     public function getProcessors()
  219.     {
  220.         return $this->processors;
  221.     }
  222.    
  223.     // Définit la veleur de retour pour un écouteur donné
  224.     public function setReturnValue(EventListener $listener, $value)
  225.     {
  226.         $this->returnValues[$listener->getUUID()] = $value;
  227.     }
  228.    
  229.     // Renvoie la valeur de retour du callback pour un écouteur donné
  230.     // Si aucun écouteur n'est spécifié, on renvoie la dernière valeur de retour non null
  231.     public function getReturnValue(EventListener $listener = null)
  232.     {
  233.         if (is_null($listener)) {
  234.             $lastNotNull = null;
  235.             foreach ($this->returnValues as $value) {
  236.                 if (!is_null($value)) {
  237.                     $lastNotNull = $value;
  238.                 }
  239.             }
  240.            
  241.             return $lastNotNull;
  242.         } else {
  243.        
  244.             return $this->returnValues[$listener->getUUID()];
  245.         }
  246.     }
  247.  
  248. }
  249.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement