JOOMLA中国
  • Joomla中国首页
  • 社区
  • 教程
  • 应用市场
  • B计划
Joomla! Framework TM
  • Namespace
  • Class
  • Tree
  • Deprecated

Namespaces

  • Composer
    • Autoload
  • Joomla
    • Application
      • Cli
        • Output
          • Processor
      • Web
    • Data
    • DI
      • Exception
    • Event
    • Filter
    • Input
    • Ldap
    • Registry
      • Format
    • Session
      • Storage
    • String
    • Uri
    • Utilities
  • None
  • PasswordCompat
    • binary
  • PHP
  • Psr
    • Log
  • Symfony
    • Component
      • Yaml
        • Exception
    • Polyfill
      • Util

Classes

  • AbstractEvent
  • DelegatingDispatcher
  • Dispatcher
  • Event
  • EventImmutable
  • ListenersPriorityQueue
  • Priority

Interfaces

  • DispatcherAwareInterface
  • DispatcherInterface
  • EventInterface

Traits

  • DispatcherAwareTrait
  1 <?php
  2 /**
  3  * Part of the Joomla Framework Event Package
  4  *
  5  * @copyright  Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
  6  * @license    GNU General Public License version 2 or later; see LICENSE
  7  */
  8 
  9 namespace Joomla\Event;
 10 
 11 use InvalidArgumentException;
 12 use Closure;
 13 
 14 /**
 15  * Implementation of a DispatcherInterface supporting
 16  * prioritized listeners.
 17  *
 18  * @since  1.0
 19  */
 20 class Dispatcher implements DispatcherInterface
 21 {
 22     /**
 23      * An array of registered events indexed by
 24      * the event names.
 25      *
 26      * @var    EventInterface[]
 27      *
 28      * @since  1.0
 29      */
 30     protected $events = array();
 31 
 32     /**
 33      * A regular expression that will filter listener method names.
 34      *
 35      * @var    string
 36      * @since  1.0
 37      * @deprecated
 38      */
 39     protected $listenerFilter;
 40 
 41     /**
 42      * An array of ListenersPriorityQueue indexed
 43      * by the event names.
 44      *
 45      * @var    ListenersPriorityQueue[]
 46      *
 47      * @since  1.0
 48      */
 49     protected $listeners = array();
 50 
 51     /**
 52      * Set an event to the dispatcher.
 53      * It will replace any event with the same name.
 54      *
 55      * @param   EventInterface  $event  The event.
 56      *
 57      * @return  Dispatcher  This method is chainable.
 58      *
 59      * @since   1.0
 60      */
 61     public function setEvent(EventInterface $event)
 62     {
 63         $this->events[$event->getName()] = $event;
 64 
 65         return $this;
 66     }
 67 
 68     /**
 69      * Sets a regular expression to filter the class methods when adding a listener.
 70      *
 71      * @param   string  $regex  A regular expression (for example '^on' will only register methods starting with "on").
 72      *
 73      * @return  Dispatcher  This method is chainable.
 74      *
 75      * @since       1.0
 76      * @deprecated  Incorporate a method in your listener object such as `getEvents` to feed into the `setListener` method.
 77      */
 78     public function setListenerFilter($regex)
 79     {
 80         $this->listenerFilter = $regex;
 81 
 82         return $this;
 83     }
 84 
 85     /**
 86      * Add an event to this dispatcher, only if it is not existing.
 87      *
 88      * @param   EventInterface  $event  The event.
 89      *
 90      * @return  Dispatcher  This method is chainable.
 91      *
 92      * @since   1.0
 93      */
 94     public function addEvent(EventInterface $event)
 95     {
 96         if (!isset($this->events[$event->getName()]))
 97         {
 98             $this->events[$event->getName()] = $event;
 99         }
100 
101         return $this;
102     }
103 
104     /**
105      * Tell if the given event has been added to this dispatcher.
106      *
107      * @param   EventInterface|string  $event  The event object or name.
108      *
109      * @return  boolean  True if the listener has the given event, false otherwise.
110      *
111      * @since   1.0
112      */
113     public function hasEvent($event)
114     {
115         if ($event instanceof EventInterface)
116         {
117             $event = $event->getName();
118         }
119 
120         return isset($this->events[$event]);
121     }
122 
123     /**
124      * Get the event object identified by the given name.
125      *
126      * @param   string  $name     The event name.
127      * @param   mixed   $default  The default value if the event was not registered.
128      *
129      * @return  EventInterface|mixed  The event of the default value.
130      *
131      * @since   1.0
132      */
133     public function getEvent($name, $default = null)
134     {
135         if (isset($this->events[$name]))
136         {
137             return $this->events[$name];
138         }
139 
140         return $default;
141     }
142 
143     /**
144      * Remove an event from this dispatcher.
145      * The registered listeners will remain.
146      *
147      * @param   EventInterface|string  $event  The event object or name.
148      *
149      * @return  Dispatcher  This method is chainable.
150      *
151      * @since   1.0
152      */
153     public function removeEvent($event)
154     {
155         if ($event instanceof EventInterface)
156         {
157             $event = $event->getName();
158         }
159 
160         if (isset($this->events[$event]))
161         {
162             unset($this->events[$event]);
163         }
164 
165         return $this;
166     }
167 
168     /**
169      * Get the registered events.
170      *
171      * @return  EventInterface[]  The registered event.
172      *
173      * @since   1.0
174      */
175     public function getEvents()
176     {
177         return $this->events;
178     }
179 
180     /**
181      * Clear all events.
182      *
183      * @return  EventInterface[]  The old events.
184      *
185      * @since   1.0
186      */
187     public function clearEvents()
188     {
189         $events = $this->events;
190         $this->events = array();
191 
192         return $events;
193     }
194 
195     /**
196      * Count the number of registered event.
197      *
198      * @return  integer  The numer of registered events.
199      *
200      * @since   1.0
201      */
202     public function countEvents()
203     {
204         return count($this->events);
205     }
206 
207     /**
208      * Add a listener to this dispatcher, only if not already registered to these events.
209      * If no events are specified, it will be registered to all events matching it's methods name.
210      * In the case of a closure, you must specify at least one event name.
211      *
212      * @param   object|Closure  $listener  The listener
213      * @param   array           $events    An associative array of event names as keys
214      *                                     and the corresponding listener priority as values.
215      *
216      * @return  Dispatcher  This method is chainable.
217      *
218      * @throws  InvalidArgumentException
219      *
220      * @since   1.0
221      */
222     public function addListener($listener, array $events = array())
223     {
224         if (!is_object($listener))
225         {
226             throw new InvalidArgumentException('The given listener is not an object.');
227         }
228 
229         // We deal with a closure.
230         if ($listener instanceof Closure)
231         {
232             if (empty($events))
233             {
234                 throw new InvalidArgumentException('No event name(s) and priority
235                 specified for the Closure listener.');
236             }
237 
238             foreach ($events as $name => $priority)
239             {
240                 if (!isset($this->listeners[$name]))
241                 {
242                     $this->listeners[$name] = new ListenersPriorityQueue;
243                 }
244 
245                 $this->listeners[$name]->add($listener, $priority);
246             }
247 
248             return $this;
249         }
250 
251         // We deal with a "normal" object.
252         $methods = get_class_methods($listener);
253 
254         if (!empty($events))
255         {
256             $methods = array_intersect($methods, array_keys($events));
257         }
258 
259         // @deprecated
260         $regex = $this->listenerFilter ?: '.*';
261 
262         foreach ($methods as $event)
263         {
264             // @deprecated - this outer `if` is deprecated.
265             if (preg_match("#$regex#", $event))
266             {
267                 // Retain this inner code after removal of the outer `if`.
268                 if (!isset($this->listeners[$event]))
269                 {
270                     $this->listeners[$event] = new ListenersPriorityQueue;
271                 }
272 
273                 $priority = isset($events[$event]) ? $events[$event] : Priority::NORMAL;
274 
275                 $this->listeners[$event]->add($listener, $priority);
276             }
277         }
278 
279         return $this;
280     }
281 
282     /**
283      * Get the priority of the given listener for the given event.
284      *
285      * @param   object|Closure         $listener  The listener.
286      * @param   EventInterface|string  $event     The event object or name.
287      *
288      * @return  mixed  The listener priority or null if the listener doesn't exist.
289      *
290      * @since   1.0
291      */
292     public function getListenerPriority($listener, $event)
293     {
294         if ($event instanceof EventInterface)
295         {
296             $event = $event->getName();
297         }
298 
299         if (isset($this->listeners[$event]))
300         {
301             return $this->listeners[$event]->getPriority($listener);
302         }
303 
304         return null;
305     }
306 
307     /**
308      * Get the listeners registered to the given event.
309      *
310      * @param   EventInterface|string  $event  The event object or name.
311      *
312      * @return  object[]  An array of registered listeners sorted according to their priorities.
313      *
314      * @since   1.0
315      */
316     public function getListeners($event)
317     {
318         if ($event instanceof EventInterface)
319         {
320             $event = $event->getName();
321         }
322 
323         if (isset($this->listeners[$event]))
324         {
325             return $this->listeners[$event]->getAll();
326         }
327 
328         return array();
329     }
330 
331     /**
332      * Tell if the given listener has been added.
333      * If an event is specified, it will tell if the listener is registered for that event.
334      *
335      * @param   object|Closure         $listener  The listener.
336      * @param   EventInterface|string  $event     The event object or name.
337      *
338      * @return  boolean  True if the listener is registered, false otherwise.
339      *
340      * @since   1.0
341      */
342     public function hasListener($listener, $event = null)
343     {
344         if ($event)
345         {
346             if ($event instanceof EventInterface)
347             {
348                 $event = $event->getName();
349             }
350 
351             if (isset($this->listeners[$event]))
352             {
353                 return $this->listeners[$event]->has($listener);
354             }
355         }
356         else
357         {
358             foreach ($this->listeners as $queue)
359             {
360                 if ($queue->has($listener))
361                 {
362                     return true;
363                 }
364             }
365         }
366 
367         return false;
368     }
369 
370     /**
371      * Remove the given listener from this dispatcher.
372      * If no event is specified, it will be removed from all events it is listening to.
373      *
374      * @param   object|Closure         $listener  The listener to remove.
375      * @param   EventInterface|string  $event     The event object or name.
376      *
377      * @return  Dispatcher  This method is chainable.
378      *
379      * @since   1.0
380      */
381     public function removeListener($listener, $event = null)
382     {
383         if ($event)
384         {
385             if ($event instanceof EventInterface)
386             {
387                 $event = $event->getName();
388             }
389 
390             if (isset($this->listeners[$event]))
391             {
392                 $this->listeners[$event]->remove($listener);
393             }
394         }
395 
396         else
397         {
398             foreach ($this->listeners as $queue)
399             {
400                 $queue->remove($listener);
401             }
402         }
403 
404         return $this;
405     }
406 
407     /**
408      * Clear the listeners in this dispatcher.
409      * If an event is specified, the listeners will be cleared only for that event.
410      *
411      * @param   EventInterface|string  $event  The event object or name.
412      *
413      * @return  Dispatcher  This method is chainable.
414      *
415      * @since   1.0
416      */
417     public function clearListeners($event = null)
418     {
419         if ($event)
420         {
421             if ($event instanceof EventInterface)
422             {
423                 $event = $event->getName();
424             }
425 
426             if (isset($this->listeners[$event]))
427             {
428                 unset($this->listeners[$event]);
429             }
430         }
431 
432         else
433         {
434             $this->listeners = array();
435         }
436 
437         return $this;
438     }
439 
440     /**
441      * Count the number of registered listeners for the given event.
442      *
443      * @param   EventInterface|string  $event  The event object or name.
444      *
445      * @return  integer  The number of registered listeners for the given event.
446      *
447      * @since   1.0
448      */
449     public function countListeners($event)
450     {
451         if ($event instanceof EventInterface)
452         {
453             $event = $event->getName();
454         }
455 
456         return isset($this->listeners[$event]) ? count($this->listeners[$event]) : 0;
457     }
458 
459     /**
460      * Trigger an event.
461      *
462      * @param   EventInterface|string  $event  The event object or name.
463      *
464      * @return  EventInterface  The event after being passed through all listeners.
465      *
466      * @since   1.0
467      */
468     public function triggerEvent($event)
469     {
470         if (!($event instanceof EventInterface))
471         {
472             if (isset($this->events[$event]))
473             {
474                 $event = $this->events[$event];
475             }
476 
477             else
478             {
479                 $event = new Event($event);
480             }
481         }
482 
483         if (isset($this->listeners[$event->getName()]))
484         {
485             foreach ($this->listeners[$event->getName()] as $listener)
486             {
487                 if ($event->isStopped())
488                 {
489                     return $event;
490                 }
491 
492                 if ($listener instanceof Closure)
493                 {
494                     call_user_func($listener, $event);
495                 }
496 
497                 else
498                 {
499                     call_user_func(array($listener, $event->getName()), $event);
500                 }
501             }
502         }
503 
504         return $event;
505     }
506 }
507 
Joomla! Framework TM API documentation generated by ApiGen 2.8.0
Joomla!® and Joomla! Framework™ are trademarks of Open Source Matters, Inc. in the United States and other countries.