*/ class EventManager extends ConfigurableService { const SERVICE_ID = 'generis/event'; /** * @deprecated use SERVICE_ID */ const CONFIG_ID = 'generis/event'; const OPTION_LISTENERS = 'listeners'; /** * Dispatch an event and trigger its listeners * * @param mixed $event either an Event object or a string * @param array $params */ public function trigger($event, $params = []) { $eventObject = is_object($event) ? $event : new GenericEvent($event, $params); foreach ($this->getListeners($eventObject) as $callback) { if (is_array($callback) && count($callback) == 2) { list($key, $function) = $callback; if (is_string($key)) { try { $service = $this->getServiceManager()->get($key); $callback = [$service, $function]; } catch (ServiceNotFoundException $e) { //do nothing } } } call_user_func($callback, $eventObject); } } /** * Attach a Listener to one or multiple events * * @param mixed $event either an Event object or a string * @param callable $callback */ public function attach($event, $callback) { $events = is_array($event) ? $event : [$event]; $listeners = $this->getOption(self::OPTION_LISTENERS); foreach ($events as $event) { $eventObject = is_object($event) ? $event : new GenericEvent($event); if (!isset($listeners[$eventObject->getName()])) { $listeners[$eventObject->getName()] = []; } if (!in_array($callback, $listeners[$eventObject->getName()], true)) { $listeners[$eventObject->getName()][] = $callback; } } $this->setOption(self::OPTION_LISTENERS, $listeners); } /** * remove listener from an event and delete event if it dosn't have any listeners * @param array $listeners * @param string $eventName * @param callable $callback * @return array */ protected function removeListener(array $listeners, $eventObject, $callback) { if (isset($listeners[$eventObject->getName()])) { if (($index = array_search($callback, $listeners[$eventObject->getName()])) !== false) { unset($listeners[$eventObject->getName()][$index]); if (empty($listeners[$eventObject->getName()])) { unset($listeners[$eventObject->getName()]); } else { $listeners[$eventObject->getName()] = array_values($listeners[$eventObject->getName()]); } } } return $listeners; } /** * Detach a Listener from one or multiple events * * @param mixed $event either an Event object or a string * @param Callable $callback */ public function detach($event, $callback) { $events = is_array($event) ? $event : [$event]; $listeners = $this->getOption(self::OPTION_LISTENERS); foreach ($events as $event) { $eventObject = is_object($event) ? $event : new GenericEvent($event); $listeners = $this->removeListener($listeners, $eventObject, $callback); } $this->setOption(self::OPTION_LISTENERS, $listeners); } /** * Get all Listeners listening to this kind of event * * @param Event $eventObject * @return Callable[] listeners associated with this event */ protected function getListeners(Event $eventObject) { $listeners = $this->getOption(self::OPTION_LISTENERS); return isset($listeners[$eventObject->getName()]) ? $listeners[$eventObject->getName()] : []; } }