Source for file Dispatcher.php
Documentation is available at Dispatcher.php
// +-----------------------------------------------------------------------+
// | Copyright (c) 2005, Bertrand Mansion |
// | All rights reserved. |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | o Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | o Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution.|
// | o The names of the authors may not be used to endorse or promote |
// | products derived from this software without specific prior written |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
// +-----------------------------------------------------------------------+
// | Author: Bertrand Mansion <bmansion@mamasam.com> |
// | Stephan Schmidt <schst@php.net> |
// +-----------------------------------------------------------------------+
// $Id: Dispatcher.php 284686 2009-07-24 05:22:17Z clockwerx $
require_once 'Event/Notification.php';
* Pseudo 'static property' for Notification object
* @global array $GLOBALS["_Event_Dispatcher"]
$GLOBALS['_Event_Dispatcher'] = array (
'NotificationClass' => 'Event_Notification'
* Registers a global observer
define('EVENT_DISPATCHER_GLOBAL', '');
* Dispatch notifications using PHP callbacks
* The Event_Dispatcher acts acts as a notification dispatch table.
* It is used to notify other objects of interesting things, if
* they meet certain criteria. This information is encapsulated
* in {@link Event_Notification} objects. Client objects register
* themselves with the Event_Dispatcher as observers of specific
* notifications posted by other objects. When an event occurs,
* an object posts an appropriate notification to the Event_Dispatcher.
* The Event_Dispatcher dispatches a message to each
* registered observer, passing the notification as the sole argument.
* The Event_Dispatcher is actually a combination of three design
* patterns: the Singleton, {@link http://c2.com/cgi/wiki?MediatorPattern Mediator},
* and Observer patterns. The idea behind Event_Dispatcher is borrowed from
* {@link http://developer.apple.com/documentation/Cocoa/Conceptual/Notifications/index.html Apple's Cocoa framework}.
* @package Event_Dispatcher
* @author Bertrand Mansion <bmansion@mamasam.com>
* @author Stephan Schmidt <schst@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/Event_Dispatcher
* Registered observer callbacks
var $_nestedDispatchers = array ();
* Class used for notifications
var $_notificationClass = null;
* Please use {@link getInstance()} instead.
* @param string Name of the notification dispatcher.
function Event_Dispatcher ($name)
* Please use {@link getInstance()} instead.
* @param string Name of the notification dispatcher.
function __construct ($name)
$this->_notificationClass = $GLOBALS['_Event_Dispatcher']['NotificationClass'];
* Returns a notification dispatcher singleton
* There is usually no need to have more than one notification
* center for an application so this is the recommended way
* to get a Event_Dispatcher object.
* @param string Name of the notification dispatcher.
* The default notification dispatcher is named __default.
* @return object Event_Dispatcher
static $dispatchers = array ();
if (!isset ($dispatchers[$name])) {
$dispatchers[$name] = new Event_Dispatcher ($name);
return $dispatchers[$name];
* Registers an observer callback
* This method registers a {@link http://www.php.net/manual/en/language.pseudo-types.php#language.types.callback callback}
* which is called when the notification corresponding to the
* criteria given at registration time is posted.
* The criteria are the notification name and eventually the
* class of the object posted with the notification.
* If there are any pending notifications corresponding to the criteria
* given here, the callback will be called straight away.
* If the notification name is empty, the observer will receive all the
* posted notifications. Same goes for the class name.
* @param mixed A PHP callback
* @param string Expected notification name, serves as a filter
* @param string Expected contained object class, serves as a filter
function addObserver($callback, $nName = EVENT_DISPATCHER_GLOBAL , $class = null )
// Note : PHP4 does not allow correct object comparison so
// only the class name is used for registration checks.
$reg = get_class($callback[0 ]). '::'. $callback[1 ];
$reg = $callback[0 ]. '::'. $callback[1 ];
$this->_ro[$nName][$reg] = array (
// Post eventual pending notifications for this observer
if (isset ($this->_pending[$nName])) {
foreach (array_keys($this->_pending[$nName]) as $k) {
$notification = & $this->_pending[$nName][$k];
if (!$notification->isNotificationCancelled ()) {
$objClass = get_class($notification->getNotificationObject ());
if (empty ($class) || strcasecmp($class, $objClass) == 0 ) {
$notification->increaseNotificationCount ();
* Creates and posts a notification object
* The purpose of the optional associated object is generally to pass
* the object posting the notification to the observers, so that the
* observers can query the posting object for more information about
* Notifications are by default added to a pending notification list.
* This way, if an observer is not registered by the time they are
* posted, it will still be notified when it is added as an observer.
* This behaviour can be turned off in order to make sure that only
* the registered observers will be notified.
* The info array serves as a container for any kind of useful
* information. It is added to the notification object and posted along.
* @param object Notification associated object
* @param string Notification name
* @param array Optional user information
* @param bool Whether the notification is pending
* @param bool Whether you want the notification to bubble up
* @return object The notification object
function &post(&$object, $nName, $info = array (), $pending = true , $bubble = true )
$notification = & new $this->_notificationClass ($object, $nName, $info);
* Posts the {@link Event_Notification} object
* @param object The Notification object
* @param bool Whether to post the notification immediately
* @param bool Whether you want the notification to bubble up
* @see Event_Dispatcher::post()
* @return object The notification object
$nName = $notification->getNotificationName ();
$this->_pending[$nName][] = & $notification;
$objClass = get_class($notification->getNotificationObject ());
// Find the registered observers
if (isset ($this->_ro[$nName])) {
$rObserver = & $this->_ro[$nName][$k];
if ($notification->isNotificationCancelled ()) {
if (empty ($rObserver['class']) ||
strcasecmp($rObserver['class'], $objClass) == 0 ) {
$notification->increaseNotificationCount ();
// Notify globally registered observers
if ($notification->isNotificationCancelled ()) {
if (empty ($rObserver['class']) ||
strcasecmp($rObserver['class'], $objClass) == 0 ) {
$notification->increaseNotificationCount ();
// Notify in nested dispatchers
foreach (array_keys($this->_nestedDispatchers) as $nested) {
$notification = & $this->_nestedDispatchers[$nested]->postNotification ($notification, $pending);
* Removes a registered observer that correspond to the given criteria
* @param mixed A PHP callback
* @param string Notification name
* @param string Contained object class
* @return bool True if an observer was removed, false otherwise
function removeObserver($callback, $nName = EVENT_DISPATCHER_GLOBAL , $class = null )
$reg = get_class($callback[0 ]). '::'. $callback[1 ];
$reg = $callback[0 ]. '::'. $callback[1 ];
if (isset ($this->_ro[$nName][$reg])) {
if (strcasecmp($this->_ro[$nName][$reg]['class'], $class) == 0 ) {
unset ($this->_ro[$nName][$reg]);
unset ($this->_ro[$nName][$reg]);
if (isset ($this->_ro[$nName]) && count($this->_ro[$nName]) == 0 ) {
unset ($this->_ro[$nName]);
* Check, whether the specified observer has been registered with the
* @param mixed A PHP callback
* @param string Notification name
* @param string Contained object class
* @return bool True if the observer has been registered, false otherwise
$reg = get_class($callback[0 ]). '::'. $callback[1 ];
$reg = $callback[0 ]. '::'. $callback[1 ];
if (!isset ($this->_ro[$nName][$reg])) {
if (strcasecmp($this->_ro[$nName][$reg]['class'], $class) == 0 ) {
* Get all observers, that have been registered for a notification
* @param string Notification name
* @param string Contained object class
* @return array List of all observers
function getObservers($nName = EVENT_DISPATCHER_GLOBAL , $class = null )
if (!isset ($this->_ro[$nName])) {
foreach ($this->_ro[$nName] as $reg => $observer) {
if ($class == null || $observer['class'] == null || strcasecmp($observer['class'], $class) == 0 ) {
* Get the name of the dispatcher.
* The name is the unique identifier of a dispatcher.
* @return string name of the dispatcher
* add a new nested dispatcher
* Notifications will be broadcasted to this dispatcher as well, which
* allows you to create event bubbling.
* @param Event_Dispatcher The nested dispatcher
$name = $dispatcher->getName ();
$this->_nestedDispatchers[$name] = & $dispatcher;
* remove a nested dispatcher
* @param Event_Dispatcher Dispatcher to remove
$dispatcher = $dispatcher->getName ();
if (!isset ($this->_nestedDispatchers[$dispatcher])) {
unset ($this->_nestedDispatchers[$dispatcher]);
* Changes the class used for notifications
* You may call this method on an object to change it for a single
* dispatcher or statically, to set the default for all dispatchers
* @param string name of the notification class
if (isset ($this) && is_a($this, 'Event_Dispatcher')) {
$this->_notificationClass = $class;
$GLOBALS['_Event_Dispatcher']['NotificationClass'] = $class;
Documentation generated on Mon, 11 Mar 2019 15:32:31 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|