<?php
/**
* Web Application Component Toolkit
*
* @link http://www.phpwact.org/
*
* @author Wact Development Team
* @link http://www.phpwact.org/team
*
* @copyright Copyright 2006, Jeff Moore
* @license http://opensource.org/licenses/mit-license.php MIT
*/

/**
* A notifier holds a collection of callbacks and can call multiple callbacks
* in sequence.
*/
class Wact_Event_Notifier {

    /**
    * A list of callbacks.
    * @var array
    */
    protected $listeners = array();

    /**
    * Add a callback that will be called when a notification is triggered.
    * @param callback A Wact callback object or a PHP callback psuedo type
    */
    function addListener($callback) {
        // Transform the results of a func_get_args() into a valid callback.
        if (is_array($callback) && count($callback) == 1) {
            $callback = $callback[0];
        }
        $this->listeners[] = $callback;        
    }

    /**
    * invoke all callback methods.
    * parameters to this method become parameters to the method invoked.
    * No special exception handling is performed.  An exception in one of the
    * notification handlers will interrupt subsequent notifications.
    */
    function notify() {
        $args = func_get_args();
        $this->notifyWIth($args);
    }

    /**
    * invoke all callback methods.
    * No special exception handling is performed.  An exception in one of the
    * notification handlers will interrupt subsequent notifications.
    * @param array A list of parameters to use for the call.
    */
    function notifyWith($args) {
        foreach($this->listeners as $listener) {
            call_user_func_array($listener, $args);
        }
    }

    /**
    * invoke each callback sequentially until the first non-NULL value
    * is returned.  This method returns that value.
    * parameters to this method become parameters to the method invoked.
    */
    function notifyUntil() {
        $args = func_get_args();
        return $this->notifyUntilWith($args);
    }

    /**
    * invoke each callback method sequentially until the first non-NULL value
    * is returned.  This method returns that value.
    * @param array A list of parameters to use for the call.
    */
    function notifyUntilWith($args, $exceptionLogger = NULL) {
        foreach($this->listeners as $listener) {
            try {
                $result = call_user_func_array($listener, $args);
                if (!is_null($result)) {
                    return $result;
                }
            } catch (Exception $e) {
                if (is_null($exceptionLogger)) {
                    throw $e;
                } else {
                    call_user_func_array($exceptionLogger, $e);
                }
            }
        }
    }

    /**
    * Filter a value through a series of callbacks.  The return value of
    * each callback is the single parameter to the next callback.
    * returns the value returned by the last callback.
    */
    function filter($value) {
        foreach($this->listeners as $listener) {
            $value = call_user_func_array($listener, $value);
        }
        return $value;
    }
    
    /**
    * Indicates if this notifier contains active callbacks.
    * @return Boolean TRUE if this notifier contains active callbacks.
    */
    function hasListeners() {
        return count($this->listeners) != 0;
    }

}

?>