Moved the core part from Horde_Notification into different
authorGunnar Wrobel <p@rdus.de>
Wed, 28 Oct 2009 11:29:22 +0000 (12:29 +0100)
committerGunnar Wrobel <p@rdus.de>
Wed, 28 Oct 2009 11:29:22 +0000 (12:29 +0100)
Horde_Notification_Handler classes. Added unit testing.

The core part of the functionality went into
Horde_Notification_Handler_Base. Only the segments that require access
to Horde global state have been split off into separate decorators.

The Horde_Notification_Handler_Alarm decorator delegates alarms to the
alarm system provided in the constructor. It needs access to
Horde_Auth::getAuth().

The Horde_Notification_Handler_Hordelog decorator logs error events
via Horde::logMessage().

As the logging part is useful but should be independant of Horde
global state if possible the Horde_Notification_Handler_Logged
decorator has been added. It allows providing a logger in the
constructor.

12 files changed:
framework/Notification/lib/Horde/Notification.php
framework/Notification/lib/Horde/Notification/Handler.php [new file with mode: 0644]
framework/Notification/lib/Horde/Notification/Handler/Alarm.php [new file with mode: 0644]
framework/Notification/lib/Horde/Notification/Handler/Base.php [new file with mode: 0644]
framework/Notification/lib/Horde/Notification/Handler/Hordelog.php [new file with mode: 0644]
framework/Notification/lib/Horde/Notification/Handler/Logged.php [new file with mode: 0644]
framework/Notification/package.xml
framework/Notification/test/Horde/Notification/Class/Notification/Handler/AlarmTest.php [new file with mode: 0644]
framework/Notification/test/Horde/Notification/Class/Notification/Handler/BaseTest.php [new file with mode: 0644]
framework/Notification/test/Horde/Notification/Class/Notification/Handler/HordelogTest.php [new file with mode: 0644]
framework/Notification/test/Horde/Notification/Class/Notification/Handler/LoggedTest.php [new file with mode: 0644]
framework/Notification/test/Horde/Notification/Class/NotificationTest.php

index 2ab002d..07e2d1c 100644 (file)
@@ -22,28 +22,7 @@ class Horde_Notification
     static protected $_instances = array();
 
     /**
-     * Hash containing all attached listener objects.
-     *
-     * @var array
-     */
-    protected $_listeners = array();
-
-    /**
-     * The storage location where we store the messages.
-     *
-     * @var Horde_Notification_Storage
-     */
-    protected $_storage;
-
-    /**
-     * A Horde_Alarm instance.
-     *
-     * @var Horde_Alarm
-     */
-    protected $_alarm;
-
-    /**
-     * Returns a reference to the global Notification object, only
+     * Returns a reference to the global Notification handler, only
      * creating it if it doesn't already exist.
      *
      * This method must be invoked as:
@@ -51,212 +30,23 @@ class Horde_Notification
      *
      * @param string $stack  The name of the message stack to use.
      *
-     * return Notification  The Horde Notification instance.
+     * return Horde_Notification_Handler The Horde Notification handler.
      */
     static public function singleton($stack = 'horde_notification_stacks')
     {
         if (!isset(self::$_instances[$stack])) {
             $storage = new Horde_Notification_Storage_Session($stack);
-            self::$_instances[$stack] = new Horde_Notification($storage);
-        }
-
-        return self::$_instances[$stack];
-    }
-
-    /**
-     * Initialize the notification system, set up any needed session
-     * variables, etc.
-     *
-     * @param Horde_Notification_Storage $storage The storage location to use.
-     */
-    protected function __construct(Horde_Notification_Storage $storage)
-    {
-        $this->_storage = $storage;
-
-        if (!empty($GLOBALS['conf']['alarms']['driver'])) {
-            $this->_alarm = Horde_Alarm::factory();
-        }
-    }
-
-    /**
-     * Registers a listener with the notification object and includes
-     * the necessary library file dynamically.
-     *
-     * @param string $listener  The name of the listener to attach. These
-     *                          names must be unique; further listeners with
-     *                          the same name will be ignored.
-     * @param array $params     A hash containing any additional configuration
-     *                          or connection parameters a listener driver
-     *                          might need.
-     * @param string $class     The class name from which the driver was
-     *                          instantiated if not the default one. If given
-     *                          you have to include the library file
-     *                          containing this class yourself. This is useful
-     *                          if you want the listener driver to be
-     *                          overriden by an application's implementation.
-     *
-     * @return Horde_Notification_Listener  The listener object.
-     * @throws Horde_Exception
-     */
-    public function attach($listener, $params = array(), $class = null)
-    {
-        $listener = strtolower(basename($listener));
-        if (!empty($this->_listeners[$listener])) {
-            return $this->_listeners[$listener];
-        }
-
-        if (is_null($class)) {
-            $class = 'Horde_Notification_Listener_' . ucfirst($listener);
-        }
-
-        if (class_exists($class)) {
-            $this->_listeners[$listener] = new $class($params);
-            if (!isset($this->_storage[$listener])) {
-                $this->_storage[$listener] = array();
-            }
-            return $this->_listeners[$listener];
-        }
-
-        throw new Horde_Exception(sprintf('Notification listener %s not found.', $class));
-    }
-
-    /**
-     * Remove a listener from the notification list. This will discard any
-     * notifications in this listeners stack.
-     *
-     * @param string $listner  The name of the listener to detach.
-     *
-     * @throws Horde_Exception
-     */
-    public function detach($listener)
-    {
-        $listener = strtolower(basename($listener));
-        if (!isset($this->_listeners[$listener])) {
-            throw new Horde_Exception(sprintf('Notification listener %s not found.', $listener));
-        }
-
-        $list = $this->_listeners[$listener];
-        unset($this->_listeners[$listener], $this->_storage[$list->getName()]);
-    }
-
-    /**
-     * Replaces a listener in the notification list. This preserves all
-     * notifications in this listeners stack. If the listener does not exist,
-     * the new listener will be added automatically.
-     *
-     * @param string $listener  See attach().
-     * @param array $params     See attach().
-     * @param string $class     See attach().
-     *
-     * @return Horde_Notification_Listener  See attach()
-     * @throws Horde_Exception
-     */
-    public function replace($listener, $params = array(), $class = null)
-    {
-        $listener = strtolower(basename($listener));
-        unset($this->_listeners[$listener]);
-        return $this->attach($listener, $params, $class);
-    }
-
-    /**
-     * Add an event to the Horde message stack.
-     *
-     * The event type parameter should begin with 'horde.' unless the
-     * application defines its own Horde_Notification_Listener subclass that
-     * handles additional codes.
-     *
-     * @param mixed $event   Horde_Notification_Event object or message string.
-     * @param integer $type  The type of message: 'horde.error',
-     *                       'horde.warning', 'horde.success', or
-     *                       'horde.message'.
-     * @param array $flags   Array of optional flags that will be passed to the
-     *                       registered listeners.
-     */
-    public function push($event, $type = null, $flags = array())
-    {
-        if (!($event instanceof Horde_Notification_Event) &&
-            !($event instanceof PEAR_Error) &&
-            !($event instanceof Exception)) {
-            /* Transparently create a Horde_Notification_Event object and
-             * set the message attribute. */
-            $event = new Horde_Notification_Event($event);
-        }
 
-        if ($event instanceof PEAR_Error || $event instanceof Exception) {
-            if (is_null($type)) {
-                $type = 'horde.error';
-            }
-            Horde::logMessage($event, __FILE__, __LINE__, PEAR_LOG_DEBUG);
-        } elseif (is_null($type)) {
-            $type = 'horde.message';
-        }
-
-        foreach ($this->_listeners as $listener) {
-            if ($listener->handles($type)) {
-                $this->_storage->push(
-                    $listener->getName(),
-                    array(
-                        'class' => get_class($event),
-                        'event' => serialize($event),
-                        'flags' => serialize($flags),
-                        'type' => $type
-                    )
+            $handler = new Horde_Notification_Handler_Base($storage);
+            $handler = new Horde_Notification_Handler_Hordelog($handler);
+            if (!empty($GLOBALS['conf']['alarms']['driver'])) {
+                $handler = new Horde_Notification_Handler_Alarm(
+                    $handler, Horde_Alarm::factory()
                 );
             }
+            self::$_instances[$stack] = $handler;
         }
-    }
-
-    /**
-     * Passes the message stack to all listeners and asks them to
-     * handle their messages.
-     *
-     * @param array $options  An array containing display options for the
-     *                        listeners.
-     */
-    public function notify($options = array())
-    {
-        if (!isset($options['listeners'])) {
-            $options['listeners'] = array_keys($this->_listeners);
-        } elseif (!is_array($options['listeners'])) {
-            $options['listeners'] = array($options['listeners']);
-        }
-
-        $options['listeners'] = array_map('strtolower', $options['listeners']);
-
-        if ($this->_alarm && in_array('status', $options['listeners'])) {
-            $this->_alarm->notify(Horde_Auth::getAuth());
-        }
-
-        foreach ($options['listeners'] as $listener) {
-            if (isset($this->_listeners[$listener])) {
-                $instance = $this->_storage[$this->_listeners[$listener]->getName()];
-                $this->_listeners[$listener]->notify($instance, $options);
-            }
-        }
-    }
 
-    /**
-     * Return the number of notification messages in the stack.
-     *
-     * @author David Ulevitch <davidu@everydns.net>
-     *
-     * @param string $my_listener  The name of the listener.
-     *
-     * @return integer  The number of messages in the stack.
-     */
-    public function count($my_listener = null)
-    {
-        if (is_null($my_listener)) {
-            $count = 0;
-            foreach ($this->_listeners as $listener) {
-                if (isset($this->_storage[$listener->getName()])) {
-                    $count += count($this->_storage[$listener->getName()]);
-                }
-            }
-            return $count;
-        } else {
-            return @count($this->_storage[$this->_listeners[strtolower($my_listener)]->getName()]);
-        }
+        return self::$_instances[$stack];
     }
-
 }
diff --git a/framework/Notification/lib/Horde/Notification/Handler.php b/framework/Notification/lib/Horde/Notification/Handler.php
new file mode 100644 (file)
index 0000000..0be252f
--- /dev/null
@@ -0,0 +1,117 @@
+<?php
+/**
+ * The Horde_Notification_Handler:: interfaces describes the handlers that
+ * notify the listeners.
+ *
+ * Copyright 2001-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Notification
+ */
+interface Horde_Notification_Handler
+{
+    /**
+     * Registers a listener with the notification object and includes
+     * the necessary library file dynamically.
+     *
+     * @param string $listener  The name of the listener to attach. These
+     *                          names must be unique; further listeners with
+     *                          the same name will be ignored.
+     * @param array $params     A hash containing any additional configuration
+     *                          or connection parameters a listener driver
+     *                          might need.
+     * @param string $class     The class name from which the driver was
+     *                          instantiated if not the default one. If given
+     *                          you have to include the library file
+     *                          containing this class yourself. This is useful
+     *                          if you want the listener driver to be
+     *                          overriden by an application's implementation.
+     *
+     * @return Horde_Notification_Listener  The listener object.
+     * @throws Horde_Exception
+     */
+    public function attach($listener, array $params = array(), $class = null);
+
+    /**
+     * Remove a listener from the notification list. This will discard any
+     * notifications in this listeners stack.
+     *
+     * @param string $listner  The name of the listener to detach.
+     *
+     * @throws Horde_Exception
+     */
+    public function detach($listener);
+
+    /**
+     * Replaces a listener in the notification list. This preserves all
+     * notifications in this listeners stack. If the listener does not exist,
+     * the new listener will be added automatically.
+     *
+     * @param string $listener  See attach().
+     * @param array $params     See attach().
+     * @param string $class     See attach().
+     *
+     * @return Horde_Notification_Listener  See attach()
+     * @throws Horde_Exception
+     */
+    public function replace($listener, array $params = array(), $class = null);
+
+    /**
+     * Add an event to the Horde message stack.
+     *
+     * The event type parameter should begin with 'horde.' unless the
+     * application defines its own Horde_Notification_Listener subclass that
+     * handles additional codes.
+     *
+     * @param mixed $event   Horde_Notification_Event object or message string.
+     * @param integer $type  The type of message: 'horde.error',
+     *                       'horde.warning', 'horde.success', or
+     *                       'horde.message'.
+     * @param array $flags   Array of optional flags that will be passed to the
+     *                       registered listeners.
+     */
+    public function push($event, $type = null, array $flags = array());
+
+    /**
+     * Passes the message stack to all listeners and asks them to
+     * handle their messages.
+     *
+     * @param array $options  An array containing display options for the
+     *                        listeners.
+     */
+    public function notify(array $options = array());
+
+    /**
+     * Convert the 'listeners' option into the format expected by the
+     * notification handler.
+     *
+     * @param array $options  An array containing display options for the
+     *                        listeners.
+     */
+    public function setNotificationListeners(array &$options);
+
+    /**
+     * Passes the message stack to all listeners and asks them to
+     * handle their messages.
+     *
+     * @param array $options An array containing display options for the
+     *                       listeners. This array is required to contain the
+     *                       correct lowercased listener names as array in the
+     *                       entry 'listeners'.
+     */
+    public function notifyListeners(array $options);
+
+    /**
+     * Return the number of notification messages in the stack.
+     *
+     * @author David Ulevitch <davidu@everydns.net>
+     *
+     * @param string $my_listener  The name of the listener.
+     *
+     * @return integer  The number of messages in the stack.
+     */
+    public function count($my_listener = null);
+}
diff --git a/framework/Notification/lib/Horde/Notification/Handler/Alarm.php b/framework/Notification/lib/Horde/Notification/Handler/Alarm.php
new file mode 100644 (file)
index 0000000..3b5d947
--- /dev/null
@@ -0,0 +1,178 @@
+<?php
+/**
+ * The Horde_Notification_Handler_Alarm notifies the alarm system if required.
+ *
+ * Copyright 2001-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Notification
+ */
+class Horde_Notification_Handler_Alarm
+implements Horde_Notification_Handler
+{
+    /**
+     * The notification handler decorated by this instance.
+     *
+     * @var Horde_Notification_Handler
+     */
+    private $_handler;
+
+    /**
+     * A Horde_Alarm instance.
+     *
+     * @var Horde_Alarm
+     */
+    protected $_alarm;
+
+    /**
+     * Initialize the notification system, set up any needed session
+     * variables, etc.
+     *
+     * @param Horde_Notification_Handler $handler The handler this instance
+     *                                            provides with logging.
+     * @param Horde_Alarm                $alarm   The alarm system to notify.
+     */
+    public function __construct(
+        Horde_Notification_Handler $handler,
+        Horde_Alarm $alarm
+    ) {
+        $this->_handler = $handler;
+        $this->_alarm   = $alarm;
+    }
+
+    /**
+     * Registers a listener with the notification object and includes
+     * the necessary library file dynamically.
+     *
+     * @param string $listener  The name of the listener to attach. These
+     *                          names must be unique; further listeners with
+     *                          the same name will be ignored.
+     * @param array $params     A hash containing any additional configuration
+     *                          or connection parameters a listener driver
+     *                          might need.
+     * @param string $class     The class name from which the driver was
+     *                          instantiated if not the default one. If given
+     *                          you have to include the library file
+     *                          containing this class yourself. This is useful
+     *                          if you want the listener driver to be
+     *                          overriden by an application's implementation.
+     *
+     * @return Horde_Notification_Listener  The listener object.
+     * @throws Horde_Exception
+     */
+    public function attach($listener, array $params = array(), $class = null)
+    {
+        return $this->_handler->attach($listener, $params, $class);
+    }
+
+    /**
+     * Remove a listener from the notification list. This will discard any
+     * notifications in this listeners stack.
+     *
+     * @param string $listner  The name of the listener to detach.
+     *
+     * @throws Horde_Exception
+     */
+    public function detach($listener)
+    {
+        $this->_handler->detach($listener);
+    }
+
+    /**
+     * Replaces a listener in the notification list. This preserves all
+     * notifications in this listeners stack. If the listener does not exist,
+     * the new listener will be added automatically.
+     *
+     * @param string $listener  See attach().
+     * @param array $params     See attach().
+     * @param string $class     See attach().
+     *
+     * @return Horde_Notification_Listener  See attach()
+     * @throws Horde_Exception
+     */
+    public function replace($listener, array $params = array(), $class = null)
+    {
+        return $this->_handler->replace($listener, $params, $class);
+    }
+
+    /**
+     * Add an event to the Horde message stack.
+     *
+     * The event type parameter should begin with 'horde.' unless the
+     * application defines its own Horde_Notification_Listener subclass that
+     * handles additional codes.
+     *
+     * @param mixed $event   Horde_Notification_Event object or message string.
+     * @param integer $type  The type of message: 'horde.error',
+     *                       'horde.warning', 'horde.success', or
+     *                       'horde.message'.
+     * @param array $flags   Array of optional flags that will be passed to the
+     *                       registered listeners.
+     */
+    public function push($event, $type = null, array $flags = array())
+    {
+        $this->_handler->push($event, $type, $flags);
+    }
+
+    /**
+     * Passes the message stack to all listeners and asks them to
+     * handle their messages.
+     *
+     * @param array $options  An array containing display options for the
+     *                        listeners.
+     */
+    public function notify(array $options = array())
+    {
+        $this->_handler->setNotificationListeners($options);
+
+        if (in_array('status', $options['listeners'])) {
+            $this->_alarm->notify(Horde_Auth::getAuth());
+        }
+
+        $this->_handler->notifyListeners($options);
+    }
+
+    /**
+     * Convert the 'listeners' option into the format expected by the
+     * notification handler.
+     *
+     * @param array $options  An array containing display options for the
+     *                        listeners.
+     */
+    public function setNotificationListeners(array &$options)
+    {
+        $this->_handler->setNotificationListeners($options);
+    }
+
+    /**
+     * Passes the message stack to all listeners and asks them to
+     * handle their messages.
+     *
+     * @param array $options An array containing display options for the
+     *                       listeners. This array is required to contain the
+     *                       correct lowercased listener names as array in the
+     *                       entry 'listeners'.
+     */
+    public function notifyListeners(array $options)
+    {
+        $this->_handler->notifyListeners($options);
+    }
+
+    /**
+     * Return the number of notification messages in the stack.
+     *
+     * @author David Ulevitch <davidu@everydns.net>
+     *
+     * @param string $my_listener  The name of the listener.
+     *
+     * @return integer  The number of messages in the stack.
+     */
+    public function count($my_listener = null)
+    {
+        return $this->_handler->count($my_listener);
+    }
+
+}
diff --git a/framework/Notification/lib/Horde/Notification/Handler/Base.php b/framework/Notification/lib/Horde/Notification/Handler/Base.php
new file mode 100644 (file)
index 0000000..1b687aa
--- /dev/null
@@ -0,0 +1,254 @@
+<?php
+/**
+ * The Horde_Notification:: package provides a subject-observer pattern for
+ * raising and showing messages of different types and to different
+ * listeners.
+ *
+ * Copyright 2001-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Notification
+ */
+class Horde_Notification_Handler_Base
+implements Horde_Notification_Handler
+{
+    /**
+     * Hash containing all attached listener objects.
+     *
+     * @var array
+     */
+    protected $_listeners = array();
+
+    /**
+     * The storage location where we store the messages.
+     *
+     * @var Horde_Notification_Storage
+     */
+    protected $_storage;
+
+    /**
+     * A Horde_Alarm instance.
+     *
+     * @var Horde_Alarm
+     */
+    protected $_alarm;
+
+    /**
+     * Initialize the notification system, set up any needed session
+     * variables, etc.
+     *
+     * @param Horde_Notification_Storage $storage The storage location to use.
+     */
+    public function __construct(Horde_Notification_Storage $storage)
+    {
+        $this->_storage = $storage;
+    }
+
+    /**
+     * Registers a listener with the notification object and includes
+     * the necessary library file dynamically.
+     *
+     * @param string $listener  The name of the listener to attach. These
+     *                          names must be unique; further listeners with
+     *                          the same name will be ignored.
+     * @param array $params     A hash containing any additional configuration
+     *                          or connection parameters a listener driver
+     *                          might need.
+     * @param string $class     The class name from which the driver was
+     *                          instantiated if not the default one. If given
+     *                          you have to include the library file
+     *                          containing this class yourself. This is useful
+     *                          if you want the listener driver to be
+     *                          overriden by an application's implementation.
+     *
+     * @return Horde_Notification_Listener  The listener object.
+     * @throws Horde_Exception
+     */
+    public function attach($listener, array $params = array(), $class = null)
+    {
+        $listener = strtolower(basename($listener));
+        if (!empty($this->_listeners[$listener])) {
+            return $this->_listeners[$listener];
+        }
+
+        if (is_null($class)) {
+            $class = 'Horde_Notification_Listener_' . ucfirst($listener);
+        }
+
+        if (class_exists($class)) {
+            $this->_listeners[$listener] = new $class($params);
+            if (!isset($this->_storage[$listener])) {
+                $this->_storage[$listener] = array();
+            }
+            return $this->_listeners[$listener];
+        }
+
+        throw new Horde_Exception(sprintf('Notification listener %s not found.', $class));
+    }
+
+    /**
+     * Remove a listener from the notification list. This will discard any
+     * notifications in this listeners stack.
+     *
+     * @param string $listner  The name of the listener to detach.
+     *
+     * @throws Horde_Exception
+     */
+    public function detach($listener)
+    {
+        $listener = strtolower(basename($listener));
+        if (!isset($this->_listeners[$listener])) {
+            throw new Horde_Exception(sprintf('Notification listener %s not found.', $listener));
+        }
+
+        $list = $this->_listeners[$listener];
+        unset($this->_listeners[$listener], $this->_storage[$list->getName()]);
+    }
+
+    /**
+     * Replaces a listener in the notification list. This preserves all
+     * notifications in this listeners stack. If the listener does not exist,
+     * the new listener will be added automatically.
+     *
+     * @param string $listener  See attach().
+     * @param array $params     See attach().
+     * @param string $class     See attach().
+     *
+     * @return Horde_Notification_Listener  See attach()
+     * @throws Horde_Exception
+     */
+    public function replace($listener, array $params = array(), $class = null)
+    {
+        $listener = strtolower(basename($listener));
+        unset($this->_listeners[$listener]);
+        return $this->attach($listener, $params, $class);
+    }
+
+    /**
+     * Add an event to the Horde message stack.
+     *
+     * The event type parameter should begin with 'horde.' unless the
+     * application defines its own Horde_Notification_Listener subclass that
+     * handles additional codes.
+     *
+     * @param mixed $event   Horde_Notification_Event object or message string.
+     * @param integer $type  The type of message: 'horde.error',
+     *                       'horde.warning', 'horde.success', or
+     *                       'horde.message'.
+     * @param array $flags   Array of optional flags that will be passed to the
+     *                       registered listeners.
+     */
+    public function push($event, $type = null, array $flags = array())
+    {
+        if (!($event instanceof Horde_Notification_Event) &&
+            !($event instanceof PEAR_Error) &&
+            !($event instanceof Exception)) {
+            /* Transparently create a Horde_Notification_Event object and
+             * set the message attribute. */
+            $event = new Horde_Notification_Event($event);
+        }
+
+        if (is_null($type)) {
+            if ($event instanceof PEAR_Error || $event instanceof Exception) {
+                $type = 'horde.error';
+            } else {
+                $type = 'horde.message';
+            }
+        }
+
+        foreach ($this->_listeners as $listener) {
+            if ($listener->handles($type)) {
+                $this->_storage->push(
+                    $listener->getName(),
+                    array(
+                        'class' => get_class($event),
+                        'event' => serialize($event),
+                        'flags' => serialize($flags),
+                        'type' => $type
+                    )
+                );
+            }
+        }
+    }
+
+    /**
+     * Passes the message stack to all listeners and asks them to
+     * handle their messages.
+     *
+     * @param array $options  An array containing display options for the
+     *                        listeners.
+     */
+    public function notify(array $options = array())
+    {
+        $this->setNotificationListeners($options);
+        $this->notifyListeners($options);
+    }
+
+    /**
+     * Convert the 'listeners' option into the format expected by the
+     * notification handler.
+     *
+     * @param array $options  An array containing display options for the
+     *                        listeners.
+     */
+    public function setNotificationListeners(array &$options)
+    {
+        if (!isset($options['listeners'])) {
+            $options['listeners'] =  $this->getListeners();
+        } elseif (!is_array($options['listeners'])) {
+            $options['listeners'] = array($options['listeners']);
+        }
+        $options['listeners'] = array_map('strtolower', $options['listeners']);
+    }
+
+    /**
+     * Passes the message stack to all listeners and asks them to
+     * handle their messages.
+     *
+     * @param array $options An array containing display options for the
+     *                       listeners. This array is required to contain the
+     *                       correct lowercased listener names as array in the
+     *                       entry 'listeners'.
+     */
+    public function notifyListeners(array $options)
+    {
+        foreach ($options['listeners'] as $listener) {
+            if (isset($this->_listeners[$listener])) {
+                $instance = $this->_storage[$this->_listeners[$listener]->getName()];
+                $this->_listeners[$listener]->notify($instance, $options);
+            }
+        }
+    }
+
+    /**
+     * Return the number of notification messages in the stack.
+     *
+     * @author David Ulevitch <davidu@everydns.net>
+     *
+     * @param string $my_listener  The name of the listener.
+     *
+     * @return integer  The number of messages in the stack.
+     */
+    public function count($my_listener = null)
+    {
+        if (is_null($my_listener)) {
+            $count = 0;
+            foreach ($this->_listeners as $listener) {
+                if (isset($this->_storage[$listener->getName()])) {
+                    $count += count($this->_storage[$listener->getName()]);
+                }
+            }
+            return $count;
+        } else {
+            return @count($this->_storage[$this->_listeners[strtolower($my_listener)]->getName()]);
+        }
+    }
+
+    protected function getListeners()
+    {
+        return array_keys($this->_listeners);
+    }
+}
diff --git a/framework/Notification/lib/Horde/Notification/Handler/Hordelog.php b/framework/Notification/lib/Horde/Notification/Handler/Hordelog.php
new file mode 100644 (file)
index 0000000..cc93225
--- /dev/null
@@ -0,0 +1,164 @@
+<?php
+/**
+ * The Horde_Notification_Handler_Hordelog logs error events via
+ * Horde::logMessage().
+ *
+ * Copyright 2001-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Notification
+ */
+class Horde_Notification_Handler_Hordelog
+implements Horde_Notification_Handler
+{
+    /**
+     * The notification handler decorated by this instance.
+     *
+     * @var Horde_Notification_Handler
+     */
+    private $_handler;
+
+    /**
+     * Initialize the notification system, set up any needed session
+     * variables, etc.
+     *
+     * @param Horde_Notification_Handler $handler The handler this instance
+     *                                            provides with logging.
+     */
+    public function __construct(Horde_Notification_Handler $handler)
+    {
+        $this->_handler = $handler;
+    }
+
+    /**
+     * Registers a listener with the notification object and includes
+     * the necessary library file dynamically.
+     *
+     * @param string $listener  The name of the listener to attach. These
+     *                          names must be unique; further listeners with
+     *                          the same name will be ignored.
+     * @param array $params     A hash containing any additional configuration
+     *                          or connection parameters a listener driver
+     *                          might need.
+     * @param string $class     The class name from which the driver was
+     *                          instantiated if not the default one. If given
+     *                          you have to include the library file
+     *                          containing this class yourself. This is useful
+     *                          if you want the listener driver to be
+     *                          overriden by an application's implementation.
+     *
+     * @return Horde_Notification_Listener  The listener object.
+     * @throws Horde_Exception
+     */
+    public function attach($listener, array $params = array(), $class = null)
+    {
+        return $this->_handler->attach($listener, $params, $class);
+    }
+
+    /**
+     * Remove a listener from the notification list. This will discard any
+     * notifications in this listeners stack.
+     *
+     * @param string $listner  The name of the listener to detach.
+     *
+     * @throws Horde_Exception
+     */
+    public function detach($listener)
+    {
+        $this->_handler->detach($listener);
+    }
+
+    /**
+     * Replaces a listener in the notification list. This preserves all
+     * notifications in this listeners stack. If the listener does not exist,
+     * the new listener will be added automatically.
+     *
+     * @param string $listener  See attach().
+     * @param array $params     See attach().
+     * @param string $class     See attach().
+     *
+     * @return Horde_Notification_Listener  See attach()
+     * @throws Horde_Exception
+     */
+    public function replace($listener, array $params = array(), $class = null)
+    {
+        return $this->_handler->replace($listener, $params, $class);
+    }
+
+    /**
+     * Add an event to the Horde message stack.
+     *
+     * The event type parameter should begin with 'horde.' unless the
+     * application defines its own Horde_Notification_Listener subclass that
+     * handles additional codes.
+     *
+     * @param mixed $event   Horde_Notification_Event object or message string.
+     * @param integer $type  The type of message: 'horde.error',
+     *                       'horde.warning', 'horde.success', or
+     *                       'horde.message'.
+     * @param array $flags   Array of optional flags that will be passed to the
+     *                       registered listeners.
+     */
+    public function push($event, $type = null, array $flags = array())
+    {
+        if ($event instanceof PEAR_Error || $event instanceof Exception) {
+            Horde::logMessage($event, __FILE__, __LINE__, PEAR_LOG_DEBUG);
+        }
+        $this->_handler->push($event, $type, $flags);
+    }
+
+    /**
+     * Passes the message stack to all listeners and asks them to
+     * handle their messages.
+     *
+     * @param array $options  An array containing display options for the
+     *                        listeners.
+     */
+    public function notify(array $options = array())
+    {
+        $this->_handler->notify($options);
+    }
+
+    /**
+     * Convert the 'listeners' option into the format expected by the
+     * notification handler.
+     *
+     * @param array $options  An array containing display options for the
+     *                        listeners.
+     */
+    public function setNotificationListeners(array &$options)
+    {
+        $this->_handler->setNotificationListeners($options);
+    }
+
+    /**
+     * Passes the message stack to all listeners and asks them to
+     * handle their messages.
+     *
+     * @param array $options An array containing display options for the
+     *                       listeners. This array is required to contain the
+     *                       correct lowercased listener names as array in the
+     *                       entry 'listeners'.
+     */
+    public function notifyListeners(array $options)
+    {
+        $this->_handler->notifyListeners($options);
+    }
+
+    /**
+     * Return the number of notification messages in the stack.
+     *
+     * @author David Ulevitch <davidu@everydns.net>
+     *
+     * @param string $my_listener  The name of the listener.
+     *
+     * @return integer  The number of messages in the stack.
+     */
+    public function count($my_listener = null)
+    {
+        return $this->_handler->count($my_listener);
+    }
+}
diff --git a/framework/Notification/lib/Horde/Notification/Handler/Logged.php b/framework/Notification/lib/Horde/Notification/Handler/Logged.php
new file mode 100644 (file)
index 0000000..979f8b9
--- /dev/null
@@ -0,0 +1,184 @@
+<?php
+/**
+ * The Horde_Notification_Handler_Logged logs error events once they are pushed
+ * to the stack.
+ *
+ * Copyright 2001-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Notification
+ */
+class Horde_Notification_Handler_Logged
+implements Horde_Notification_Handler
+{
+    /**
+     * The notification handler decorated by this instance.
+     *
+     * @var Horde_Notification_Handler
+     */
+    private $_handler;
+
+    /**
+     * The log handler.
+     *
+     * @var mixed
+     */
+    private $_logger;
+
+    /**
+     * Initialize the notification system, set up any needed session
+     * variables, etc.
+     *
+     * @param Horde_Notification_Handler $handler The handler this instance
+     *                                            provides with logging.
+     *
+     * @param mixed                      $logger  The log handler. The provided
+     *                                            instance is required to
+     *                                            implement the debug() function.
+     *                                            You should be able to use a
+     *                                            common Logger here (PEAR Log,
+     *                                            Horde_Log_Logger, or Zend_Log).
+     */
+    public function __construct(Horde_Notification_Handler $handler, $logger)
+    {
+        $this->_handler = $handler;
+        $this->_logger  = $logger;
+    }
+
+    /**
+     * Registers a listener with the notification object and includes
+     * the necessary library file dynamically.
+     *
+     * @param string $listener  The name of the listener to attach. These
+     *                          names must be unique; further listeners with
+     *                          the same name will be ignored.
+     * @param array $params     A hash containing any additional configuration
+     *                          or connection parameters a listener driver
+     *                          might need.
+     * @param string $class     The class name from which the driver was
+     *                          instantiated if not the default one. If given
+     *                          you have to include the library file
+     *                          containing this class yourself. This is useful
+     *                          if you want the listener driver to be
+     *                          overriden by an application's implementation.
+     *
+     * @return Horde_Notification_Listener  The listener object.
+     * @throws Horde_Exception
+     */
+    public function attach($listener, array $params = array(), $class = null)
+    {
+        return $this->_handler->attach($listener, $params, $class);
+    }
+
+    /**
+     * Remove a listener from the notification list. This will discard any
+     * notifications in this listeners stack.
+     *
+     * @param string $listner  The name of the listener to detach.
+     *
+     * @throws Horde_Exception
+     */
+    public function detach($listener)
+    {
+        $this->_handler->detach($listener);
+    }
+
+    /**
+     * Replaces a listener in the notification list. This preserves all
+     * notifications in this listeners stack. If the listener does not exist,
+     * the new listener will be added automatically.
+     *
+     * @param string $listener  See attach().
+     * @param array $params     See attach().
+     * @param string $class     See attach().
+     *
+     * @return Horde_Notification_Listener  See attach()
+     * @throws Horde_Exception
+     */
+    public function replace($listener, array $params = array(), $class = null)
+    {
+        return $this->_handler->replace($listener, $params, $class);
+    }
+
+    /**
+     * Add an event to the Horde message stack.
+     *
+     * The event type parameter should begin with 'horde.' unless the
+     * application defines its own Horde_Notification_Listener subclass that
+     * handles additional codes.
+     *
+     * @param mixed $event   Horde_Notification_Event object or message string.
+     * @param integer $type  The type of message: 'horde.error',
+     *                       'horde.warning', 'horde.success', or
+     *                       'horde.message'.
+     * @param array $flags   Array of optional flags that will be passed to the
+     *                       registered listeners.
+     */
+    public function push($event, $type = null, array $flags = array())
+    {
+        if ($event instanceof PEAR_Error || $event instanceof Exception) {
+            /**
+             * Some loggers only accept string messages. As both PEAR_Error and
+             * Exception accept being casted into a string we can ensure that
+             * the logger receives a string here.
+             */
+            $this->_logger->debug((string) $event);
+        }
+        $this->_handler->push($event, $type, $flags);
+    }
+
+    /**
+     * Passes the message stack to all listeners and asks them to
+     * handle their messages.
+     *
+     * @param array $options  An array containing display options for the
+     *                        listeners.
+     */
+    public function notify(array $options = array())
+    {
+        $this->_handler->notify($options);
+    }
+
+    /**
+     * Convert the 'listeners' option into the format expected by the
+     * notification handler.
+     *
+     * @param array $options  An array containing display options for the
+     *                        listeners.
+     */
+    public function setNotificationListeners(array &$options)
+    {
+        $this->_handler->setNotificationListeners($options);
+    }
+
+    /**
+     * Passes the message stack to all listeners and asks them to
+     * handle their messages.
+     *
+     * @param array $options An array containing display options for the
+     *                       listeners. This array is required to contain the
+     *                       correct lowercased listener names as array in the
+     *                       entry 'listeners'.
+     */
+    public function notifyListeners(array $options)
+    {
+        $this->_handler->notifyListeners($options);
+    }
+
+    /**
+     * Return the number of notification messages in the stack.
+     *
+     * @author David Ulevitch <davidu@everydns.net>
+     *
+     * @param string $my_listener  The name of the listener.
+     *
+     * @return integer  The number of messages in the stack.
+     */
+    public function count($my_listener = null)
+    {
+        return $this->_handler->count($my_listener);
+    }
+}
index 8a695b4..ee6a5aa 100644 (file)
@@ -33,6 +33,13 @@ http://pear.php.net/dtd/package-2.0.xsd">
    <dir name="lib">
     <dir name="Horde">
      <dir name="Notification">
+      <file name="Handler.php" role="php" />
+      <dir name="Handler">
+       <file name="Alarm.php" role="php" />
+       <file name="Base.php" role="php" />
+       <file name="Hordelog.php" role="php" />
+       <file name="Logged.php" role="php" />
+      </dir> <!-- /lib/Horde/Notification/Handler -->
       <dir name="Listener">
        <file name="Audio.php" role="php" />
        <file name="Javascript.php" role="php" />
@@ -58,6 +65,12 @@ http://pear.php.net/dtd/package-2.0.xsd">
        <file name="NotificationTest.php" role="test" />
        <dir name="Notification">
         <file name="EventTest.php" role="test" />
+        <dir name="Handler">
+         <file name="AlarmTest.php" role="test" />
+         <file name="BaseTest.php" role="test" />
+         <file name="HordelogTest.php" role="test" />
+         <file name="LoggedTest.php" role="test" />
+        </dir> <!-- /test/Horde/Notification/Class/Notification/Handler -->
         <file name="ListenerTest.php" role="test" />
         <dir name="Listener">
          <file name="AudioTest.php" role="test" />
@@ -98,6 +111,11 @@ http://pear.php.net/dtd/package-2.0.xsd">
  </dependencies>
  <phprelease>
   <filelist>
+   <install name="lib/Horde/Notification/Handler.php" as="Horde/Notification/Handler.php" />
+   <install name="lib/Horde/Notification/Handler/Alarm.php" as="Horde/Notification/Handler/Alarm.php" />
+   <install name="lib/Horde/Notification/Handler/Base.php" as="Horde/Notification/Handler/Base.php" />
+   <install name="lib/Horde/Notification/Handler/Hordelog.php" as="Horde/Notification/Handler/Hordelog.php" />
+   <install name="lib/Horde/Notification/Handler/Logged.php" as="Horde/Notification/Handler/Logged.php" />
    <install name="lib/Horde/Notification/Listener/Audio.php" as="Horde/Notification/Listener/Audio.php" />
    <install name="lib/Horde/Notification/Listener/Javascript.php" as="Horde/Notification/Listener/Javascript.php" />
    <install name="lib/Horde/Notification/Listener/Mobile.php" as="Horde/Notification/Listener/Mobile.php" />
@@ -111,6 +129,10 @@ http://pear.php.net/dtd/package-2.0.xsd">
    <install name="test/Horde/Notification/Autoload.php" as="Horde/Notification/Autoload.php" />
    <install name="test/Horde/Notification/Class/NotificationTest.php" as="Horde/Notification/Class/NotificationTest.php" />
    <install name="test/Horde/Notification/Class/Notification/EventTest.php" as="Horde/Notification/Class/Notification/EventTest.php" />
+   <install name="test/Horde/Notification/Class/Notification/Handler/AlarmTest.php" as="Horde/Notification/Class/Notification/Handler/AlarmTest.php" />
+   <install name="test/Horde/Notification/Class/Notification/Handler/TestTest.php" as="Horde/Notification/Class/Notification/Handler/BaseTest.php" />
+   <install name="test/Horde/Notification/Class/Notification/Handler/HordelogTest.php" as="Horde/Notification/Class/Notification/Handler/HordelogTest.php" />
+   <install name="test/Horde/Notification/Class/Notification/Handler/LoggedTest.php" as="Horde/Notification/Class/Notification/Handler/LoggedTest.php" />
    <install name="test/Horde/Notification/Class/Notification/ListenerTest.php" as="Horde/Notification/Class/Notification/ListenerTest.php" />
    <install name="test/Horde/Notification/Class/Notification/Listener/AudioTest.php" as="Horde/Notification/Class/Notification/Listener/AudioTest.php" />
    <install name="test/Horde/Notification/Class/Notification/Listener/JavascriptTest.php" as="Horde/Notification/Class/Notification/Listener/JavascriptTest.php" />
diff --git a/framework/Notification/test/Horde/Notification/Class/Notification/Handler/AlarmTest.php b/framework/Notification/test/Horde/Notification/Class/Notification/Handler/AlarmTest.php
new file mode 100644 (file)
index 0000000..7261b5c
--- /dev/null
@@ -0,0 +1,138 @@
+<?php
+/**
+ * Test the alarm notification handler class.
+ *
+ * PHP version 5
+ *
+ * @category Horde
+ * @package  Notification
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Notification
+ */
+
+/**
+ * Prepare the test setup.
+ */
+require_once dirname(__FILE__) . '/../../../Autoload.php';
+
+/**
+ * Test the alarm notification handler class.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Horde
+ * @package  Notification
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Notification
+ */
+
+class Horde_Notification_Class_Notification_Handler_AlarmTest extends PHPUnit_Framework_TestCase
+{
+    public function setUp()
+    {
+        $this->handler = $this->getMock(
+            'Horde_Notification_Handler_Base', array(), array(), '', false, false
+        );
+        $this->alarm   = $this->getMock('Horde_Alarm');
+        $this->alarm_handler = new Horde_Notification_Handler_Alarm(
+            $this->handler, $this->alarm
+        );
+    }
+
+    public function testMethodNotifyHasPostconditionThatTheAlarmSystemGotNotifiedIfTheStatusListenerShouldBeNotified()
+    {
+        $this->alarm->expects($this->once())
+            ->method('notify')
+            ->with('');
+        $this->handler->expects($this->once())
+            ->method('setNotificationListeners')
+            ->with(array('listeners' => array('status')));
+        $this->handler->expects($this->once())
+            ->method('notifyListeners')
+            ->with(array('listeners' => array('status')));
+        $this->alarm_handler->notify(array('listeners' => array('status')));
+    }
+
+    public function testMethodAttachGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('attach')
+            ->with('listener', array(), 'class')
+            ->will($this->returnValue('instance'));
+        $this->assertEquals(
+            'instance',
+            $this->alarm_handler->attach('listener', array(), 'class')
+        );
+    }
+
+    public function testMethodDetachGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('detach')
+            ->with('listener');
+        $this->alarm_handler->detach('listener');
+    }
+
+    public function testMethodReplaceGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('replace')
+            ->with('listener', array(), 'class')
+            ->will($this->returnValue('instance'));
+        $this->assertEquals(
+            'instance',
+            $this->alarm_handler->replace('listener', array(), 'class')
+        );
+    }
+
+    public function testMethodPushGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('push')
+            ->with('event', 'type', array());
+        $this->alarm_handler->push('event', 'type', array());
+    }
+
+    public function testMethodNotifyGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('setNotificationListeners')
+            ->with(array('listeners' => array('test')));
+        $this->handler->expects($this->once())
+            ->method('notifyListeners')
+            ->with(array('listeners' => array('test')));
+        $this->alarm_handler->notify(array('listeners' => array('test')));
+    }
+
+    public function testMethodSetnotificationlistenersGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('setNotificationListeners')
+            ->with(array());
+        $array = array();
+        $this->alarm_handler->setNotificationListeners($array);
+    }
+
+    public function testMethodNotifylistenersGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('notifyListeners')
+            ->with(array());
+        $this->alarm_handler->notifyListeners(array());
+    }
+
+    public function testMethodCountGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('count')
+            ->with('listener')
+            ->will($this->returnValue(1));
+        $this->assertEquals(1, $this->alarm_handler->count('listener'));
+    }
+
+}
\ No newline at end of file
diff --git a/framework/Notification/test/Horde/Notification/Class/Notification/Handler/BaseTest.php b/framework/Notification/test/Horde/Notification/Class/Notification/Handler/BaseTest.php
new file mode 100644 (file)
index 0000000..d4bdb15
--- /dev/null
@@ -0,0 +1,221 @@
+<?php
+/**
+ * Test the basic notification handler class.
+ *
+ * PHP version 5
+ *
+ * @category Horde
+ * @package  Notification
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Notification
+ */
+
+/**
+ * Prepare the test setup.
+ */
+require_once dirname(__FILE__) . '/../../../Autoload.php';
+
+/**
+ * Test the basic notification handler class.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Horde
+ * @package  Notification
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Notification
+ */
+
+class Horde_Notification_Class_Notification_Handler_BaseTest extends PHPUnit_Framework_TestCase
+{
+    public function setUp()
+    {
+        $this->storage = new Horde_Notification_Storage_Session('test');
+        $this->handler = new Horde_Notification_Handler_Base($this->storage);
+    }
+
+    public function testMethodAttachHasResultNotificationlistener()
+    {
+        $this->assertType(
+            'Horde_Notification_Listener_Audio',
+            $this->handler->attach('audio')
+        );
+    }
+
+    public function testMethodAttachHasResultNotificationlistenerTheSameListenerAsBeforeIfThisListenerHasAlreadyBeenAttached()
+    {
+        $listener = $this->handler->attach('audio');
+        $this->assertSame($listener, $this->handler->attach('audio'));
+    }
+
+    public function testMethodAttachHasResultNotificationlistenerClassAsSpecifiedInParameterClass()
+    {
+        $this->assertType(
+            'Horde_Notification_Listener_Audio',
+            $this->handler->attach(
+                'MyAudio', array(), 'Horde_Notification_Listener_Audio'
+            )
+        );
+    }
+
+    public function testMethodAttachHasPostconditionThatTheListenerGotInitializedWithTheProvidedParmeters()
+    {
+        $listener = $this->handler->attach('dummy', array('test'));
+        $this->assertEquals(array('test'), $listener->params);
+    }
+
+    public function testMethodAttachHasPostconditionThatTheListenerStackGotInitializedAsArray()
+    {
+        $this->handler->attach('audio');
+        $this->assertEquals(array(), $_SESSION['test']['audio']);
+    }
+
+    public function testMethodAttachThrowsExceptionIfTheListenerTypeIsUnkown()
+    {
+        try {
+            $this->handler->attach('MyAudio');
+            $this->fail('No exception!');
+        } catch (Horde_Exception $e) {
+            $this->assertEquals(
+                'Notification listener Horde_Notification_Listener_Myaudio not found.',
+                $e->getMessage()
+            );
+        }
+    }
+
+    public function testMethodReplaceHasResultNotificationlistener()
+    {
+        $this->handler->attach(
+            'test', array(), 'Horde_Notification_Listener_Audio'
+        );
+        $this->assertType(
+            'Horde_Notification_Listener_Dummy',
+            $this->handler->replace(
+                'test', array(), 'Horde_Notification_Listener_Dummy'
+            )
+        );
+    }
+
+    public function testMethodDetachHasPostconditionThatTheListenerStackGotUnset()
+    {
+        $this->handler->attach('audio');
+        $this->handler->detach('audio');
+        $this->assertFalse(isset($_SESSION['test']['audio']));
+    }
+
+    public function testMethodDetachThrowsExceptionIfTheListenerIsUnset()
+    {
+        try {
+            $this->handler->detach('MyAudio');
+            $this->fail('No exception!');
+        } catch (Horde_Exception $e) {
+            $this->assertEquals(
+                'Notification listener myaudio not found.',
+                $e->getMessage()
+            );
+        }
+    }
+
+    public function testMethodPushHasPostconditionThatTheEventGotSavedInAllAttachedListenerStacksHandlingTheEvent()
+    {
+        $event = new Horde_Notification_Event('test');
+        $flags= array();
+        $this->handler->attach('audio');
+        $this->handler->push('test', 'audio');
+        $result = array_shift($_SESSION['test']['audio']);
+        $this->assertEquals('Horde_Notification_Event', $result['class']);
+        $this->assertEquals(serialize($event), $result['event']);
+        $this->assertEquals(serialize($flags), $result['flags']);
+        $this->assertEquals('audio', $result['type']);
+    }
+
+    public function testMethodPushHasPostconditionThatAnExceptionGetsMarkedAsTypeErrorIfTheTypeWasUnset()
+    {
+        $this->handler->attach('dummy');
+        $this->handler->push(new Exception('test'));
+        $result = array_shift($_SESSION['test']['dummy']);
+        $this->assertEquals('horde.error', $result['type']);
+    }
+
+    public function testMethodPushHasPostconditionThatEventsWithoutTypeGetMarkedAsTypeMessage()
+    {
+        $this->handler->attach('dummy');
+        $this->handler->push('test');
+        $result = array_shift($_SESSION['test']['dummy']);
+        $this->assertEquals('horde.message', $result['type']);
+    }
+
+    public function testMethodNotifyHasPostconditionThatAllListenersWereNotified()
+    {
+        $event = new Horde_Notification_Event('test');
+        $dummy = $this->handler->attach('dummy');
+        $flags= array();
+        $this->handler->push('test');
+        $this->handler->notify();
+        $result = array_shift($dummy->notifications);
+        $this->assertEquals('Horde_Notification_Event', $result['class']);
+        $this->assertEquals(serialize($event), $result['event']);
+        $this->assertEquals(serialize($flags), $result['flags']);
+        $this->assertEquals('horde.message', $result['type']);
+    }
+
+    public function testMethodNotifyHasPostconditionThatTheSpecifiedListenersWereNotified()
+    {
+        $event = new Horde_Notification_Event('test');
+        $dummy = $this->handler->attach('dummy');
+        $flags= array();
+        $this->handler->push('test');
+        $this->handler->notify(array('listeners' => 'dummy'));
+        $result = array_shift($dummy->notifications);
+        $this->assertEquals(serialize($event), $result['event']);
+    }
+
+    public function testMethodCountHasResultTheTotalNumberOfEventsInTheStack()
+    {
+        $this->handler->attach('audio');
+        $this->handler->attach('dummy');
+        $this->handler->push('test', 'audio');
+        $this->assertEquals(2, $this->handler->count());
+    }
+
+    public function testMethodCountHasResultTheEventNumberForASpecificListenerIfTheListenerHasBeenSpecified()
+    {
+        $this->handler->attach('audio');
+        $this->handler->attach('dummy');
+        $this->handler->push('test', 'audio');
+        $this->assertEquals(1, $this->handler->count('audio'));
+    }
+
+}
+
+class Horde_Notification_Listener_Dummy extends Horde_Notification_Listener
+{
+    public $params;
+
+    public $notifications;
+
+    public function __construct($params)
+    {
+        $this->params = $params;
+        $this->_name = 'dummy';
+        $this->_handles = array(
+            'audio' => '',
+            'horde.error' => '',
+            'horde.message' => '',
+        );
+    }
+
+    public function notify(&$messageStacks, $options = array())
+    {
+        $this->notifications = $messageStacks;
+    }
+
+    public function getMessage($message, $options = array())
+    {
+    }
+}
\ No newline at end of file
diff --git a/framework/Notification/test/Horde/Notification/Class/Notification/Handler/HordelogTest.php b/framework/Notification/test/Horde/Notification/Class/Notification/Handler/HordelogTest.php
new file mode 100644 (file)
index 0000000..77bd66c
--- /dev/null
@@ -0,0 +1,134 @@
+<?php
+/**
+ * Test the notification handler class that logs to the horde log.
+ *
+ * PHP version 5
+ *
+ * @category Horde
+ * @package  Notification
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Notification
+ */
+
+/**
+ * Prepare the test setup.
+ */
+require_once dirname(__FILE__) . '/../../../Autoload.php';
+
+/**
+ * Test the notification handler class that logs to the horde log.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Horde
+ * @package  Notification
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Notification
+ */
+
+class Horde_Notification_Class_Notification_Handler_HordelogTest extends PHPUnit_Framework_TestCase
+{
+    public function setUp()
+    {
+        @include_once 'Log.php';
+        if (!defined('PEAR_LOG_DEBUG')) {
+            $this->markTestSkipped('The PEAR_LOG_DEBUG constant is not available!');
+        }
+
+        $this->handler = $this->getMock(
+            'Horde_Notification_Handler_Base', array(), array(), '', false, false
+        );
+        $this->logged_handler = new Horde_Notification_Handler_Hordelog(
+            $this->handler
+        );
+    }
+
+    public function testMethodPushHasPostconditionThattheEventGotLoggedIfTheEventWasAnError()
+    {
+        $exception = new Exception('test');
+        $this->handler->expects($this->once())
+            ->method('push')
+            ->with($exception);
+        $this->logged_handler->push($exception);
+    }
+
+    public function testMethodAttachGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('attach')
+            ->with('listener', array(), 'class')
+            ->will($this->returnValue('instance'));
+        $this->assertEquals(
+            'instance',
+            $this->logged_handler->attach('listener', array(), 'class')
+        );
+    }
+
+    public function testMethodDetachGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('detach')
+            ->with('listener');
+        $this->logged_handler->detach('listener');
+    }
+
+    public function testMethodReplaceGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('replace')
+            ->with('listener', array(), 'class')
+            ->will($this->returnValue('instance'));
+        $this->assertEquals(
+            'instance',
+            $this->logged_handler->replace('listener', array(), 'class')
+        );
+    }
+
+    public function testMethodPushGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('push')
+            ->with('event', 'type', array());
+        $this->logged_handler->push('event', 'type', array());
+    }
+
+    public function testMethodNotifyGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('notify')
+            ->with(array('listeners' => array('test')));
+        $this->logged_handler->notify(array('listeners' => array('test')));
+    }
+
+    public function testMethodSetnotificationlistenersGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('setNotificationListeners')
+            ->with(array());
+        $array = array();
+        $this->logged_handler->setNotificationListeners($array);
+    }
+
+    public function testMethodNotifylistenersGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('notifyListeners')
+            ->with(array());
+        $this->logged_handler->notifyListeners(array());
+    }
+
+    public function testMethodCountGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('count')
+            ->with('listener')
+            ->will($this->returnValue(1));
+        $this->assertEquals(1, $this->logged_handler->count('listener'));
+    }
+
+}
\ No newline at end of file
diff --git a/framework/Notification/test/Horde/Notification/Class/Notification/Handler/LoggedTest.php b/framework/Notification/test/Horde/Notification/Class/Notification/Handler/LoggedTest.php
new file mode 100644 (file)
index 0000000..2b56cd6
--- /dev/null
@@ -0,0 +1,133 @@
+<?php
+/**
+ * Test the logging notification handler class.
+ *
+ * PHP version 5
+ *
+ * @category Horde
+ * @package  Notification
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Notification
+ */
+
+/**
+ * Prepare the test setup.
+ */
+require_once dirname(__FILE__) . '/../../../Autoload.php';
+
+/**
+ * Test the logging notification handler class.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Horde
+ * @package  Notification
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Notification
+ */
+
+class Horde_Notification_Class_Notification_Handler_LoggedTest extends PHPUnit_Framework_TestCase
+{
+    public function setUp()
+    {
+        $this->handler = $this->getMock(
+            'Horde_Notification_Handler_Base', array(), array(), '', false, false
+        );
+        $this->logger   = $this->getMock('Horde_Log_Logger');
+        $this->logged_handler = new Horde_Notification_Handler_Logged(
+            $this->handler, $this->logger
+        );
+    }
+
+    public function testMethodPushHasPostconditionThattheEventGotLoggedIfTheEventWasAnError()
+    {
+        $exception = new Exception('test');
+        $this->logger->expects($this->once())
+            ->method('__call')
+            ->with('debug', $this->isType('array'));
+        $this->handler->expects($this->once())
+            ->method('push')
+            ->with($exception);
+        $this->logged_handler->push($exception);
+    }
+
+    public function testMethodAttachGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('attach')
+            ->with('listener', array(), 'class')
+            ->will($this->returnValue('instance'));
+        $this->assertEquals(
+            'instance',
+            $this->logged_handler->attach('listener', array(), 'class')
+        );
+    }
+
+    public function testMethodDetachGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('detach')
+            ->with('listener');
+        $this->logged_handler->detach('listener');
+    }
+
+    public function testMethodReplaceGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('replace')
+            ->with('listener', array(), 'class')
+            ->will($this->returnValue('instance'));
+        $this->assertEquals(
+            'instance',
+            $this->logged_handler->replace('listener', array(), 'class')
+        );
+    }
+
+    public function testMethodPushGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('push')
+            ->with('event', 'type', array());
+        $this->logged_handler->push('event', 'type', array());
+    }
+
+    public function testMethodNotifyGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('notify')
+            ->with(array('listeners' => array('test')));
+        $this->logged_handler->notify(array('listeners' => array('test')));
+    }
+
+    public function testMethodSetnotificationlistenersGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('setNotificationListeners')
+            ->with(array());
+        $array = array();
+        $this->logged_handler->setNotificationListeners($array);
+    }
+
+    public function testMethodNotifylistenersGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('notifyListeners')
+            ->with(array());
+        $this->logged_handler->notifyListeners(array());
+    }
+
+    public function testMethodCountGetsDelegated()
+    {
+        $this->handler->expects($this->once())
+            ->method('count')
+            ->with('listener')
+            ->will($this->returnValue(1));
+        $this->assertEquals(1, $this->logged_handler->count('listener'));
+    }
+
+}
\ No newline at end of file
index 346269b..2a8c592 100644 (file)
@@ -33,188 +33,29 @@ require_once dirname(__FILE__) . '/../Autoload.php';
 
 class Horde_Notification_Class_NotificationTest extends PHPUnit_Framework_TestCase
 {
-    public function setUp()
-    {
-        @include_once 'Log.php';
-        if (!defined('PEAR_LOG_DEBUG')) {
-            $this->markTestSkipped('The PEAR_LOG_DEBUG constant is not available!');
-        }
-    }
-
-    public function testMethodSingletonAlwaysReturnsTheSameInstanceForTheSameStackName()
+    public function testMethodSingletonReturnsAlwaysTheSameInstanceForTheSameStackName()
     {
         $notification1 = Horde_Notification::singleton('test');
         $notification2 = Horde_Notification::singleton('test');
         $this->assertSame($notification1, $notification2);
     }
 
-    public function testMethodConstructHasPostconditionThatTheSessionStackGotInitializedAsArray()
+    public function testMethodSingletonReturnsAlarmhandlerIfTheAlarmSystemisConfigured()
     {
-        $notification = Horde_Notification_Instance::newInstance('test');
-        $this->assertEquals(array(), $_SESSION['test']);
-    }
+        global $conf;
+        $conf['alarms']['driver'] = 'Mock';
 
-    public function testMethodAttachHasResultNotificationlistener()
-    {
-        $notification = Horde_Notification_Instance::newInstance('test');
         $this->assertType(
-            'Horde_Notification_Listener_Audio',
-            $notification->attach('audio')
+            'Horde_Notification_Handler_Alarm',
+            Horde_Notification::singleton('alarm')
         );
     }
 
-    public function testMethodAttachHasResultNotificationlistenerClassAsSpecifiedInParameterClass()
-    {
-        $notification = Horde_Notification_Instance::newInstance('test');
-        $this->assertType(
-            'Horde_Notification_Listener_Audio',
-            $notification->attach(
-                'MyAudio', array(), 'Horde_Notification_Listener_Audio'
-            )
-        );
-    }
-
-    public function testMethodAttachHasPostconditionThatTheListenerGotInitializedWithTheProvidedParmeters()
-    {
-        $notification = Horde_Notification_Instance::newInstance('test');
-        $listener = $notification->attach('dummy', array('test'));
-        $this->assertEquals(array('test'), $listener->params);
-    }
-
-    public function testMethodAttachHasPostconditionThatTheListenerStackGotInitializedAsArray()
-    {
-        $notification = Horde_Notification_Instance::newInstance('test');
-        $notification->attach('audio');
-        $this->assertEquals(array(), $_SESSION['test']['audio']);
-    }
-
-    public function testMethodAttachThrowsExceptionIfTheListenerTypeIsUnkown()
-    {
-        $notification = Horde_Notification_Instance::newInstance('test');
-        try {
-            $notification->attach('MyAudio');
-            $this->fail('No exception!');
-        } catch (Horde_Exception $e) {
-            $this->assertEquals(
-                'Notification listener Horde_Notification_Listener_Myaudio not found.',
-                $e->getMessage()
-            );
-        }
-    }
-
-    public function testMethodReplaceHasResultNotificationlistener()
-    {
-        $notification = Horde_Notification_Instance::newInstance('test');
-        $notification->attach(
-            'test', array(), 'Horde_Notification_Listener_Audio'
-        );
-        $this->assertType(
-            'Horde_Notification_Listener_Dummy',
-            $notification->replace(
-                'test', array(), 'Horde_Notification_Listener_Dummy'
-            )
-        );
-    }
-
-    public function testMethodDetachHasPostconditionThatTheListenerStackGotUnset()
-    {
-        $notification = Horde_Notification_Instance::newInstance('test');
-        $notification->attach('audio');
-        $notification->detach('audio');
-        $this->assertFalse(isset($_SESSION['test']['audio']));
-    }
-
-    public function testMethodDetachThrowsExceptionIfTheListenerIsUnset()
-    {
-        $notification = Horde_Notification_Instance::newInstance('test');
-        try {
-            $notification->detach('MyAudio');
-            $this->fail('No exception!');
-        } catch (Horde_Exception $e) {
-            $this->assertEquals(
-                'Notification listener myaudio not found.',
-                $e->getMessage()
-            );
-        }
-    }
-
-    public function testMethodPushHasPostconditionThatTheEventGotSavedInAllAttachedListenerStacksHandlingTheEvent()
-    {
-        $notification = Horde_Notification_Instance::newInstance('test');
-        $event = new Horde_Notification_Event('test');
-        $flags= array();
-        $notification->attach('audio');
-        $notification->push('test', 'audio');
-        $result = array_shift($_SESSION['test']['audio']);
-        $this->assertEquals('Horde_Notification_Event', $result['class']);
-        $this->assertEquals(serialize($event), $result['event']);
-        $this->assertEquals(serialize($flags), $result['flags']);
-        $this->assertEquals('audio', $result['type']);
-    }
-
-    public function testMethodPushHasPostconditionThatAnExceptionGetsMarkedAsTypeErrorIfTheTypeWasUnset()
-    {
-        $notification = Horde_Notification_Instance::newInstance('test');
-        $notification->attach('dummy');
-        $notification->push(new Exception('test'));
-        $result = array_shift($_SESSION['test']['dummy']);
-        $this->assertEquals('horde.error', $result['type']);
-    }
-
-    public function testMethodPushHasPostconditionThatEventsWithoutTypeGetMarkedAsTypeMessage()
-    {
-        $notification = Horde_Notification_Instance::newInstance('test');
-        $notification->attach('dummy');
-        $notification->push('test');
-        $result = array_shift($_SESSION['test']['dummy']);
-        $this->assertEquals('horde.message', $result['type']);
-    }
-
-    public function testMethodNotifyHasPostconditionThatAllListenersWereNotified()
-    {
-        $notification = Horde_Notification_Instance::newInstance('test');
-        $event = new Horde_Notification_Event('test');
-        $dummy = $notification->attach('dummy');
-        $flags= array();
-        $notification->push('test');
-        $notification->notify();
-        $result = array_shift($dummy->notifications);
-        $this->assertEquals('Horde_Notification_Event', $result['class']);
-        $this->assertEquals(serialize($event), $result['event']);
-        $this->assertEquals(serialize($flags), $result['flags']);
-        $this->assertEquals('horde.message', $result['type']);
-    }
-
-    public function testMethodNotifyHasPostconditionThatTheSpecifiedListenersWereNotified()
-    {
-        $notification = Horde_Notification_Instance::newInstance('test');
-        $event = new Horde_Notification_Event('test');
-        $dummy = $notification->attach('dummy');
-        $flags= array();
-        $notification->push('test');
-        $notification->notify(array('listeners' => 'dummy'));
-        $result = array_shift($dummy->notifications);
-        $this->assertEquals(serialize($event), $result['event']);
-    }
-
-    public function testMethodCountHasResultTheTotalNumberOfEventsInTheStack()
-    {
-        $notification = Horde_Notification_Instance::newInstance('test');
-        $notification->attach('audio');
-        $notification->attach('dummy');
-        $notification->push('test', 'audio');
-        $this->assertEquals(2, $notification->count());
-    }
-
-    public function testMethodCountHasResultTheEventNumberForASpecificListenerIfTheListenerHasBeenSpecified()
+    public function testMethodConstructHasPostconditionThatTheSessionStackGotInitializedAsArray()
     {
         $notification = Horde_Notification_Instance::newInstance('test');
-        $notification->attach('audio');
-        $notification->attach('dummy');
-        $notification->push('test', 'audio');
-        $this->assertEquals(1, $notification->count('audio'));
+        $this->assertEquals(array(), $_SESSION['test']);
     }
-
 }
 
 class Horde_Notification_Instance extends Horde_Notification
@@ -222,34 +63,7 @@ class Horde_Notification_Instance extends Horde_Notification
     static public function newInstance($stack)
     {
         $storage = new Horde_Notification_Storage_Session($stack);
-        $instance = new Horde_Notification($storage);
+        $instance = new Horde_Notification_Handler_Base($storage);
         return $instance;
     }
 }
-
-class Horde_Notification_Listener_Dummy extends Horde_Notification_Listener
-{
-    public $params;
-
-    public $notifications;
-
-    public function __construct($params)
-    {
-        $this->params = $params;
-        $this->_name = 'dummy';
-        $this->_handles = array(
-            'audio' => '',
-            'horde.error' => '',
-            'horde.message' => '',
-        );
-    }
-
-    public function notify(&$messageStacks, $options = array())
-    {
-        $this->notifications = $messageStacks;
-    }
-
-    public function getMessage($message, $options = array())
-    {
-    }
-}
\ No newline at end of file