alexis-j
10/8/2012 - 12:52 PM

Asynchronous Event Dispatcher

Asynchronous Event Dispatcher

services:
    async_events.dispatcher:
        class: Ormigo\Component\EventDispatcher\AsynchronousEventDispatcher
        arguments:
            - '@event_dispatcher'
        tags:
            - { name: 'kernel.event_subscriber' }
<?php

namespace Ormigo\Component\EventDispatcher;

use Symfony\Component\Console\ConsoleEvents;

use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

class AsynchronousEventDispatcher implements EventDispatcherInterface, EventSubscriberInterface
{
    protected $dispatcher;
    protected $asyncEvents = array();

    /**
     * Constructor.
     *
     * @param EventDispatcherInterface $dispatcher
     */
    public function __construct(EventDispatcherInterface $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }

    /**
     * Dispatch all saved events.
     *
     * @return void
     */
    public function dispatchAsync()
    {
        foreach ($this->asyncEvents as $eachEntry) {
            $this->dispatcher->dispatch($eachEntry['name'], $eachEntry['event']);
        }
    }

    /**
     * Store an asynchronous event to be dispatched later.
     *
     * @param string $eventName
     * @param Event|null $event
     *
     * @return void
     */
    public function addAsyncEvent($eventName, Event $event = null)
    {
        $this->asyncEvents[] = array(
            'name' => $eventName,
            'event' => $event,
        );
    }

    public function dispatch($eventName, Event $event = null)
    {
        return $this->dispatcher->dispatch($eventName, $event);
    }

    public function addListener($eventName, $listener, $priority = 0)
    {
        return $this->dispatcher->addListener($eventName, $listener, $priority);
    }

    public function addSubscriber(EventSubscriberInterface $subscriber)
    {
        return $this->dispatcher->addSubscriber($subscriber);
    }

    public function removeListener($eventName, $listener)
    {
        return $this->dispatcher->removeListener($eventName, $listener);
    }

    public function removeSubscriber(EventSubscriberInterface $subscriber)
    {
        $this->dispatcher->removeSubscriber($subscriber);
    }

    public function getListeners($eventName = null)
    {
        return $this->dispatcher->getListeners($eventName);
    }

    public function hasListeners($eventName = null)
    {
        return $this->dispatcher->hasListeners($eventName);
    }

    public function onKernelTerminate(PostResponseEvent $event)
    {
        $this->dispatchAsync();
    }

    public function onConsoleTerminate(ConsoleTerminateEvent $event)
    {
        $this->dispatchAsync();
    }

    public static function getSubscribedEvents()
    {
        return array(
            KernelEvents::TERMINATE => [ 'onKernelTerminate', 2048 ],
            ConsoleEvents::TERMINATE => [ 'onConsoleTerminate', 2048 ],
        );
    }
}