Changeset View
Changeset View
Standalone View
Standalone View
src/events/PhutilEventEngine.php
- This file was added.
<?php | |||||
final class PhutilEventEngine extends Phobject { | |||||
private static $instance; | |||||
private $listeners = array(); | |||||
private function __construct() { | |||||
// <empty> | |||||
} | |||||
public static function getInstance() { | |||||
if (!self::$instance) { | |||||
self::$instance = new PhutilEventEngine(); | |||||
} | |||||
return self::$instance; | |||||
} | |||||
public function addListener(PhutilEventListener $listener, $type) { | |||||
$this->listeners[$type][] = $listener; | |||||
return $this; | |||||
} | |||||
/** | |||||
* Get all the objects currently listening to any event. | |||||
*/ | |||||
public function getAllListeners() { | |||||
$listeners = array_mergev($this->listeners); | |||||
$listeners = mpull($listeners, null, 'getListenerID'); | |||||
return $listeners; | |||||
} | |||||
public static function dispatchEvent(PhutilEvent $event) { | |||||
$instance = self::getInstance(); | |||||
$listeners = idx($instance->listeners, $event->getType(), array()); | |||||
$global_listeners = idx( | |||||
$instance->listeners, | |||||
PhutilEventType::TYPE_ALL, | |||||
array()); | |||||
// Merge and deduplicate listeners (we want to send the event to each | |||||
// listener only once, even if it satisfies multiple criteria for the | |||||
// event). | |||||
$listeners = array_merge($listeners, $global_listeners); | |||||
$listeners = mpull($listeners, null, 'getListenerID'); | |||||
$profiler = PhutilServiceProfiler::getInstance(); | |||||
$profiler_id = $profiler->beginServiceCall( | |||||
array( | |||||
'type' => 'event', | |||||
'kind' => $event->getType(), | |||||
'count' => count($listeners), | |||||
)); | |||||
$caught = null; | |||||
try { | |||||
foreach ($listeners as $listener) { | |||||
if ($event->isStopped()) { | |||||
// Do this first so if someone tries to dispatch a stopped event it | |||||
// doesn't go anywhere. Silly but less surprising. | |||||
break; | |||||
} | |||||
$listener->handleEvent($event); | |||||
} | |||||
} catch (Exception $ex) { | |||||
$profiler->endServiceCall($profiler_id, array()); | |||||
throw $ex; | |||||
} | |||||
$profiler->endServiceCall($profiler_id, array()); | |||||
} | |||||
} |