Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- use ISV\Service\Cache\CacheInterface;
- use ISV\Service\Cache\FileCache;
- use Symfony\Component\DependencyInjection\ContainerInterface;
- use Symfony\Component\EventDispatcher\Event;
- use Symfony\Component\EventDispatcher\EventDispatcher;
- /**
- * Overrides the symfony event dispatcher so that we don't call addListener() 400 times for every request when 90%
- * of requests never dispatch an event.
- *
- * When dispatch() is called, we addListener() first and then dispatch().
- *
- * Stole some ideas from ContainerAwareEventDispatcher
- */
- class LazyEventDispatcher extends EventDispatcher
- {
- const CACHE_KEY = 'LazyEventDispatcher';
- // array index in $listeners
- const SERVICE = 0;
- const METHOD = 1;
- const PRIORITY = 2;
- /** @var CacheInterface */
- private $cache;
- /** @var array eventName => array of ['service', 'method', 'priority'] one per listener */
- private $listeners = [];
- /** @var ContainerInterface */
- private $container;
- /**
- * LazyEventDispatcher constructor.
- * @param ContainerInterface $container
- * @param CacheInterface $cache for unit testing: so we can inject a different cache if needed
- */
- public function __construct(ContainerInterface $container, CacheInterface $cache = null)
- {
- $this->container = $container;
- $this->cache = $cache;
- }
- /**
- * @return array
- */
- public function getLazyListeners()
- {
- if (empty($this->listeners)) {
- $this->listeners = $this->getCache()->get(self::CACHE_KEY);
- if (empty($this->listeners)) {
- $this->listeners = [];
- }
- }
- return $this->listeners;
- }
- /**
- * save them to cache so we can load them later.
- * called at compile time.
- */
- public function saveLazyListeners()
- {
- ksort($this->listeners);
- $this->getCache()->set(self::CACHE_KEY, $this->listeners);
- }
- /**
- * Adds an event listener that listens on the specified events. Called by a container compiler class at build time.
- *
- * @param string $eventName The event to listen for
- * @param string $serviceName usually a class name
- * @param string $methodName eg onPersonDelete
- * @param int $priority The higher this value, the earlier an event
- * listener will be triggered in the chain (defaults to 0)
- */
- public function addLazyListener($eventName, $serviceName, $methodName, $priority = 0)
- {
- $this->listeners[$eventName][] = [
- self::SERVICE => $serviceName,
- self::METHOD => $methodName,
- self::PRIORITY => $priority,
- ];
- }
- /**
- * {@inheritdoc}
- */
- public function dispatch($eventName, Event $event = null)
- {
- if ($this->hasListeners($eventName)) {
- return parent::dispatch($eventName, $event);
- }
- $allListeners = $this->getLazyListeners();
- if (!isset($allListeners[$eventName])) {
- return parent::dispatch($eventName, $event);
- }
- // add them then dispatch
- foreach ($allListeners[$eventName] as $handler) {
- $service = $this->container->get($handler[self::SERVICE]);
- $this->addListener($eventName, [$service, $handler[self::METHOD]], $handler[self::PRIORITY]);
- }
- return parent::dispatch($eventName, $event);
- }
- /**
- * no need to clear the cache explicitly: it will be automatically rebuilt when the container is rebuilt
- * @return CacheInterface
- */
- private function getCache()
- {
- if (empty($this->cache)) {
- $this->cache = new FileCache(CACHE_PATH);
- }
- return $this->cache;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement