EventDispatcher.php 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. <?php
  2. namespace JMS\SerializerBundle\Serializer\EventDispatcher;
  3. /**
  4. * Light-weight event dispatcher.
  5. *
  6. * This implementation focuses primarily on performance, and dispatching
  7. * events for certain classes. It is not a general purpose event dispatcher.
  8. *
  9. * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  10. */
  11. class EventDispatcher implements EventDispatcherInterface
  12. {
  13. private $listeners = array();
  14. private $classListeners = array();
  15. public static function getDefaultMethodName($eventName)
  16. {
  17. return 'on'.str_replace(array('_', '.'), '', $eventName);
  18. }
  19. /**
  20. * Sets the listeners.
  21. *
  22. * @param array $listeners
  23. */
  24. public function setListeners(array $listeners)
  25. {
  26. $this->listeners = $listeners;
  27. $this->classListeners = array();
  28. }
  29. public function addListener($eventName, $callable, $class = null, $format = null)
  30. {
  31. $this->listeners[$eventName][] = array($callable, null === $class ? null : strtolower($class), $format);
  32. unset($this->classListeners[$eventName]);
  33. }
  34. public function addSubscriber(EventSubscriberInterface $subscriber)
  35. {
  36. foreach ($subscriber->getSubscribedEvents() as $eventData) {
  37. if ( ! isset($eventData['event'])) {
  38. throw new \InvalidArgumentException(sprintf('Each event must have a "event" key.'));
  39. }
  40. $method = isset($eventData['method']) ? $eventData['method'] : self::getDefaultMethodName($eventData['event']);
  41. $class = isset($eventData['class']) ? strtolower($eventData['class']) : null;
  42. $format = isset($eventData['format']) ? $eventData['format'] : null;
  43. $this->listeners[$eventData['event']][] = array(array($subscriber, $method), $class, $format);
  44. unset($this->classListeners[$eventData['event']]);
  45. }
  46. }
  47. public function hasListeners($eventName, $class, $format)
  48. {
  49. if ( ! isset($this->listeners[$eventName])) {
  50. return false;
  51. }
  52. $loweredClass = strtolower($class);
  53. if ( ! isset($this->classListeners[$eventName][$loweredClass][$format])) {
  54. $this->classListeners[$eventName][$loweredClass][$format] = $this->initializeListeners($eventName, $loweredClass, $format);
  55. }
  56. return !!$this->classListeners[$eventName][$loweredClass][$format];
  57. }
  58. public function dispatch($eventName, $class, $format, Event $event)
  59. {
  60. if ( ! isset($this->listeners[$eventName])) {
  61. return;
  62. }
  63. $loweredClass = strtolower($class);
  64. if ( ! isset($this->classListeners[$eventName][$loweredClass][$format])) {
  65. $this->classListeners[$eventName][$loweredClass][$format] = $this->initializeListeners($eventName, $loweredClass, $format);
  66. }
  67. foreach ($this->classListeners[$eventName][$loweredClass][$format] as $listener) {
  68. call_user_func($listener, $event);
  69. }
  70. }
  71. protected function initializeListeners($eventName, $loweredClass, $format)
  72. {
  73. $listeners = array();
  74. foreach ($this->listeners[$eventName] as $listener) {
  75. if (null !== $listener[1] && $loweredClass !== $listener[1]) {
  76. continue;
  77. }
  78. if (null !== $listener[2] && $format !== $listener[2]) {
  79. continue;
  80. }
  81. $listeners[] = $listener[0];
  82. }
  83. return $listeners;
  84. }
  85. }