pastebin - collaborative debugging

pastebin is a collaborative debugging tool allowing you to share and modify code snippets while chatting on IRC, IM or a message board.

This site is developed to XHTML and CSS2 W3C standards. If you see this paragraph, your browser does not support those standards and you need to upgrade. Visit WaSP for a variety of options.

PHP pastebin - collaborative debugging tool View Help


Posted by naholyr on Mon 12 May 11:54
report abuse | download | new post

  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. }

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.

Syntax highlighting:

To highlight particular lines, prefix each line with @@


Remember me so that I can delete my post