views:

17

answers:

0

I have implemented the event listener pattern in PHP, and setup a test case to validate that it is working within a single call to a URL.

I'd like to be able to persist this state between calls while avoiding setup/teardown of all of the events within the application. I'm hoping that by persisting the state, when an event is fired, the service can do a lookup for all listeners registered for that specific event fired by a specific target, then notify them of the event.

Another of my goals here is to enable event based messaging between systems allowing for injection of logging or email notification without the need to modify and deploy source changes.

I'm relatively new to modelling code in this way so any thoughts/suggestions are welcome.

Here is the test code I've created:

class Api_BeanstreamController extends Zend_Controller_Action 
                               implements Blackline_Event_Listener, 
                                          Blackline_Event_Source 
{
    public function getUUID() {
            return '1';
    }

    public function processEvent(Blackline_Event $event) {
            echo 'processed!';
    }

    public function eventtestAction() {
            Blackline_Event::addListener('test', $this, $this);
            $e = new Blackline_Event('test', $this);
            $e->fire();
    }
}

class Blackline_Event 
{       
    static protected $_listeners = array();

    protected $_source;
    protected $_type;
    protected $_createdDate;

    function __construct($type, Blackline_Event_Source $source) {
            $this->_type = $type;
            $this->_source = $source;
            $this->_createdDate = time();
    }

    public function getSource() {
            return $this->_source;
    }

    public function getType() {
            return $this->_type;
    }

    public function getCreatedDate() {
            return $this->_createdDate;
    }

    public function fire() {
            // Get the general listeners to notify
            $listeners = self::$_listeners[$this->_type];
            // Get the specific listeners to notify
            $listeners = self::$_listeners[$this->_type][$this->_source->getUUID()];
            foreach($listeners as $listener) {
                    $listener->processEvent($this);
            }
            //TODO: autoload this data from a datastore
    }

    public static function addListener($eventType = '', Blackline_Event_Source $source = null, Blackline_Event_Listener $listener) {
            if($source)
                    self::$_listeners[$eventType][$source->getUUID()][$listener->getUUID()] = $listener;
            else
                    self::$_listeners[$eventType][''][$listener->getUUID()] = $listener;

            // TODO: persist this association
    }

    public static function removeListener($eventType = '', Blackline_Event_Source $source = null, Blackline_Event_Listener $listener) {
            if($source)
                    unset(self::$_listeners[$eventType][$source->getUUID()][$listener->getUUID()]);
            else
                    unset(self::$_listeners[$eventType][''][$listener->getUUID()]);

            // TODO: remove any persisted association
    }
}