From 17f9589a20e88a506eaee659773825eac0f43d1f Mon Sep 17 00:00:00 2001 From: Michael M Slusarz Date: Sun, 21 Jun 2009 18:48:32 -0600 Subject: [PATCH] Notification:: (CVS HEAD) -> Horde_Notification:: --- framework/Notification/lib/Horde/Notification.php | 240 +++++++++++++++++++++ .../Notification/lib/Horde/Notification/Event.php | 55 +++++ .../lib/Horde/Notification/Listener.php | 145 +++++++++++++ .../lib/Horde/Notification/Listener/Audio.php | 52 +++++ .../lib/Horde/Notification/Listener/Javascript.php | 64 ++++++ .../lib/Horde/Notification/Listener/Mobile.php | 85 ++++++++ .../lib/Horde/Notification/Listener/Status.php | 67 ++++++ framework/Notification/package.xml | 113 ++++++++++ 8 files changed, 821 insertions(+) create mode 100644 framework/Notification/lib/Horde/Notification.php create mode 100644 framework/Notification/lib/Horde/Notification/Event.php create mode 100644 framework/Notification/lib/Horde/Notification/Listener.php create mode 100644 framework/Notification/lib/Horde/Notification/Listener/Audio.php create mode 100644 framework/Notification/lib/Horde/Notification/Listener/Javascript.php create mode 100644 framework/Notification/lib/Horde/Notification/Listener/Mobile.php create mode 100644 framework/Notification/lib/Horde/Notification/Listener/Status.php create mode 100644 framework/Notification/package.xml diff --git a/framework/Notification/lib/Horde/Notification.php b/framework/Notification/lib/Horde/Notification.php new file mode 100644 index 000000000..f4ed48d9f --- /dev/null +++ b/framework/Notification/lib/Horde/Notification.php @@ -0,0 +1,240 @@ + + * @package Horde_Notification + */ +class Horde_Notification +{ + /** + * Horde_Notification instances. + * + * @var Horde_Notification + */ + protected $_instances = array(); + + /** + * Hash containing all attached listener objects. + * + * @var array + */ + protected $_listeners = array(); + + /** + * The name of the session variable where we store the messages. + * + * @var string + */ + protected $_stack; + + /** + * A Horde_Alarm instance. + * + * @var Horde_Alarm + */ + protected $_alarm; + + /** + * Returns a reference to the global Notification object, only + * creating it if it doesn't already exist. + * + * This method must be invoked as: + * $notification = Horde_Notification::singleton() + * + * @param string $stack The name of the message stack to use. + * + * return Notification The Horde Notification instance. + */ + static public function singleton($stack = 'horde_notification_stacks') + { + if (!isset(self::$_instances[$stack])) { + self::$_instances[$stack] = new Horde_Notification($stack); + } + + return self::$_instances[$stack]; + } + + /** + * Initialize the notification system, set up any needed session + * variables, etc. + * + * @param string $stack The name of the message stack to use. + */ + protected function __construct($stack) + { + $this->_stack = $stack; + + /* Make sure the message stack is registered in the session, + * and obtain a global-scope reference to it. */ + if (!isset($_SESSION[$this->_stack])) { + $_SESSION[$this->_stack] = array(); + } + + 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 TODO + * @throws Horde_Exception + */ + public function attach($listener, $params = array(), $class = null) + { + $listener = 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($_SESSION[$this->_stack][$listener])) { + $_SESSION[$this->_stack][$listener] = array(); + } + return $this->_listeners[$listener]; + } + + throw new Horde_Exception(sprintf('Notification listener %s not found.', $listener)); + } + + /** + * Remove a listener from the notification list. + * + * @param string $listner The name of the listener to detach. + * + * @throws Horde_Exception + */ + public function detach($listener) + { + $listener = 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], $_SESSION[$this->_stack][$list->getName()]); + } + + /** + * 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) { + /* Transparently create a Horde_Notification_Event object and + * set the message attribute. */ + $event = new Horde_Notification_Event($event); + } + + if ($event instanceof PEAR_Error) { + 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)) { + $_SESSION[$this->_stack][$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($options = array()) + { + if (!isset($options['listeners'])) { + $options['listeners'] = array_keys($this->_listeners); + } elseif (!is_array($options['listeners'])) { + $options['listeners'] = array($options['listeners']); + } + + if ($this->_alarm && in_array('status', $options['listeners'])) { + $this->_alarm->notify(Auth::getAuth()); + } + + foreach ($options['listeners'] as $listener) { + if (isset($this->_listeners[$listener])) { + $this->_listeners[$listener]->notify($_SESSION[$this->_stack][$this->_listeners[$listener]->getName()], $options); + } + } + } + + /** + * Return the number of notification messages in the stack. + * + * @author David Ulevitch + * + * @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($_SESSION[$this->_stack][$listener->getName()])) { + $count += count($_SESSION[$this->_stack][$listener->getName()]); + } + } + return $count; + } else { + return @count($_SESSION[$this->_stack][$this->_listeners[$my_listener]->getName()]); + } + } + +} diff --git a/framework/Notification/lib/Horde/Notification/Event.php b/framework/Notification/lib/Horde/Notification/Event.php new file mode 100644 index 000000000..331379233 --- /dev/null +++ b/framework/Notification/lib/Horde/Notification/Event.php @@ -0,0 +1,55 @@ + + * @package Horde_Notification + */ +class Horde_Notification_Event +{ + /** + * The message being passed. + * + * @var string + */ + protected $_message = ''; + + /** + * If passed, sets the message for this event. + * + * @param string $message The text message for this event. + */ + public function __construct($message = null) + { + if (!is_null($message)) { + $this->setMessage($message); + } + } + + /** + * Sets the text message for this event. + * + * @param string $message The text message to display. + */ + public function setMessage($message) + { + $this->_message = $message; + } + + /** + * Gets the text message for this event. + * + * @return string The text message to display. + */ + public function getMessage() + { + return $this->_message; + } + +} diff --git a/framework/Notification/lib/Horde/Notification/Listener.php b/framework/Notification/lib/Horde/Notification/Listener.php new file mode 100644 index 000000000..679f3c543 --- /dev/null +++ b/framework/Notification/lib/Horde/Notification/Listener.php @@ -0,0 +1,145 @@ + + * @package Horde_Notification + */ +class Horde_Notification_Listener +{ + /** + * Array of message types that this listener handles. + * + * @var array + */ + protected $_handles = array(); + + /** + * Does this listener handle a certain type of message? + * + * @param string $type The message type in question. + * + * @return boolean Whether this listener handles the type. + */ + public function handles($type) + { + return isset($this->_handles[$type]); + } + + /** + * Return a unique identifier for this listener. + * + * @return string Unique id. + */ + public function getName() + { + return get_class($this); + } + + /** + * Outputs the status line, sends emails, pages, etc., if there + * are any messages on this listener's message stack. + * + * @param array &$messageStack The stack of messages. + * @param array $options An array of options. + */ + public function notify(&$messageStacks, $options = array()) + { + } + + /** + * Processes one message from the message stack. + * + * @param array $message One message hash from the stack. + */ + public function getMessage($message) + { + } + + /** + * Unserialize an event from the message stack, checking to see if the + * appropriate class exists and kludging it into a base Notification_Event + * object if not. + */ + public function getEvent($message) + { + $ob = false; + if (class_exists($message['class'])) { + $ob = @unserialize($message['event']); + } else { + $ob = @unserialize($message['event']); + if (!is_callable(array($ob, 'getMessage'))) { + if (isset($ob->_message)) { + $ob = new Horde_Notification_Event($ob->_message); + } + } + } + + /* If we've failed to create a valid Notification_Event object + * (or subclass object) so far, return a PEAR_Error. */ + if (!is_callable(array($ob, 'getMessage'))) { + $ob = PEAR::raiseError('Unable to decode message event: ' . $message['event']); + } + + /* Specially handle PEAR_Error objects and add userinfo if + * it's there. */ + if (is_callable(array($ob, 'getUserInfo'))) { + $userinfo = $ob->getUserInfo(); + if ($userinfo) { + if (is_array($userinfo)) { + $userinfo_elts = array(); + foreach ($userinfo as $userinfo_elt) { + if (is_scalar($userinfo_elt)) { + $userinfo_elts[] = $userinfo_elt; + } elseif (is_object($userinfo_elt)) { + if (is_callable(array($userinfo_elt, '__toString'))) { + $userinfo_elts[] = $userinfo_elt->__toString(); + } elseif (is_callable(array($userinfo_elt, 'getMessage'))) { + $userinfo_elts[] = $userinfo_elt->getMessage(); + } + } + } + $userinfo = implode(', ', $userinfo_elts); + } + + $ob->_message = $ob->getMessage() . ' : ' . $userinfo; + } + } + + return $ob; + } + + /** + * Unserialize an array of event flags from the message stack. If this + * event has no flags, or the flags array could not be unserialized, an + * empty array is returned. + * + * @return array An array of flags. + */ + public function getFlags($message) + { + /* If this message doesn't have any flags, return an empty + * array. */ + if (empty($message['flags'])) { + return array(); + } + + /* Unserialize the flags array from the message. */ + $flags = @unserialize($message['flags']); + + /* If we couldn't unserialize the flags array, return an empty + * array. */ + if (!is_array($flags)) { + return array(); + } + + return $flags; + } + +} diff --git a/framework/Notification/lib/Horde/Notification/Listener/Audio.php b/framework/Notification/lib/Horde/Notification/Listener/Audio.php new file mode 100644 index 000000000..30ca2986a --- /dev/null +++ b/framework/Notification/lib/Horde/Notification/Listener/Audio.php @@ -0,0 +1,52 @@ + + * @package Horde_Notification + */ +class Horde_Notification_Listener_Audio extends Horde_Notification_Listener +{ + /** + * Constructor. + */ + public function __construct() + { + $this->_handles = array('audio' => ''); + } + + /** + * Outputs the embedded audio code if there are any messages on the + * 'audio' message stack. + * + * @param array &$messageStack The stack of messages. + * @param array $options An array of options. + */ + public function notify(&$messageStack, $options = array()) + { + if (count($messageStack)) { + while ($message = array_shift($messageStack)) { + $this->getMessage($message); + } + } + } + + /** + * Outputs one message. + * + * @param array $message One message hash from the stack. + */ + public function getMessage($message) + { + $event = $this->getEvent($message); + echo ''; + } + +} diff --git a/framework/Notification/lib/Horde/Notification/Listener/Javascript.php b/framework/Notification/lib/Horde/Notification/Listener/Javascript.php new file mode 100644 index 000000000..6c18449ca --- /dev/null +++ b/framework/Notification/lib/Horde/Notification/Listener/Javascript.php @@ -0,0 +1,64 @@ + + * @package Horde_Notification + */ +class Horde_Notification_Listener_Javascript extends Horde_Notification_Listener +{ + /** + * Constructor. + */ + public function __construct() + { + $this->_handles = array( + 'javascript' => '', + 'javascript-file' => '' + ); + } + + /** + * Outputs the javascript code if there are any messages on the + * 'javascript' message stack and if the 'notify_javascript' option is set. + * + * @param array &$messageStack The stack of messages. + * @param array $options An array of options. Options: 'noscript' + */ + public function notify(&$messageStack, $options = array()) + { + if (!count($messageStack)) { + return; + } + + if (empty($options['noscript'])) { + echo '\n"; + if (count($files)) { + foreach ($files as $file) { + echo '' . "\n"; + } + } + } + } + +} diff --git a/framework/Notification/lib/Horde/Notification/Listener/Mobile.php b/framework/Notification/lib/Horde/Notification/Listener/Mobile.php new file mode 100644 index 000000000..890114260 --- /dev/null +++ b/framework/Notification/lib/Horde/Notification/Listener/Mobile.php @@ -0,0 +1,85 @@ + + * @package Horde_Notification + */ +class Horde_Notification_Listener_Mobile extends Horde_Notification_Listener_Status +{ + /** + * The Horde_Mobile:: object that status lines should be added to. + * + * @var Horde_Mobile + */ + protected $_mobile; + + /** + * Constructor. + */ + public function __construct() + { + $this->_handles = array( + 'horde.error' => _("ERR"), + 'horde.success' => _("SUCCESS"), + 'horde.warning' => _("WARN"), + 'horde.message' => _("MSG") + ); + } + + /** + * Associate a Horde_Mobile:: object with the listener. + * + * @param Horde_Mobile The Horde_Mobile:: object to send status lines to. + */ + public function setMobileObject(&$mobile) + { + $this->_mobile = &$mobile; + } + + /** + * Outputs the status line if there are any messages on the 'mobile' + * message stack. + * + * @param array &$messageStack The stack of messages. + * @param array $options An array of options. Options: 'nospace' + */ + public function notify(&$messageStack, $options = array()) + { + if (!$this->_mobile) { + $p = new Horde_Notification_Listener_Status(); + return $p->notify($messageStack, $options); + } + + if (count($messageStack)) { + while ($message = array_shift($messageStack)) { + $this->getMessage($message); + } + $t = &$this->_mobile->add(new Horde_Mobile_text("\n")); + $t->set('linebreaks', true); + } + } + + /** + * Outputs one message. + * + * @param array $message One message hash from the stack. + */ + public function getMessage($message) + { + if (!$this->_mobile) { + $p = new Horde_Notification_Listener_Status(); + return $p->notify($messageStack, $options); + } + + $event = $this->getEvent($message); + $this->_mobile->add(new Horde_Mobile_text($this->_handles[$message['type']] . ': ' . strip_tags($event->getMessage()))); + } + +} diff --git a/framework/Notification/lib/Horde/Notification/Listener/Status.php b/framework/Notification/lib/Horde/Notification/Listener/Status.php new file mode 100644 index 000000000..4a4b5ca4f --- /dev/null +++ b/framework/Notification/lib/Horde/Notification/Listener/Status.php @@ -0,0 +1,67 @@ + + * @package Horde_Notification + */ +class Horde_Notification_Listener_Status extends Horde_Notification_Listener +{ + /** + * Constructor. + */ + public function __construct() + { + $this->_handles = array( + 'horde.error' => array('alerts/error.png', _("Error")), + 'horde.success' => array('alerts/success.png', _("Success")), + 'horde.warning' => array('alerts/warning.png', _("Warning")), + 'horde.message' => array('alerts/message.png', _("Message")), + 'horde.alarm' => array('alerts/alarm.png', _("Alarm")) + ); + } + + /** + * Outputs the status line if there are any messages on the 'status' + * message stack. + * + * @param array &$messageStack The stack of messages. + * @param array $options An array of options. + */ + public function notify(&$messageStack, $options = array()) + { + if (count($messageStack)) { + echo ''; + } + } + + /** + * Outputs one message. + * + * @param array $message One message hash from the stack. + */ + public function getMessage($message) + { + $event = $this->getEvent($message); + $text = $event->getMessage(); + + if (!in_array('content.raw', $this->getFlags($message))) { + $text = htmlspecialchars($text); + } + + return '
  • ' . Horde::img($this->_handles[$message['type']][0], $this->_handles[$message['type']][1], '', $GLOBALS['registry']->getImageDir('horde')) . $text . '
  • '; + } + +} diff --git a/framework/Notification/package.xml b/framework/Notification/package.xml new file mode 100644 index 000000000..07ee71d21 --- /dev/null +++ b/framework/Notification/package.xml @@ -0,0 +1,113 @@ + + + Notification + pear.horde.org + Horde Notification System + The Horde_Notification:: class provides a subject-observer pattern for raising and showing messages of different types and to different listeners. + + + Jan Schneider + jan + jan@horde.org + yes + + 2009-06-24 + + 0.1.0 + 0.1.0 + + + beta + beta + + LGPL + * Initial Horde 4 package. + + + + + + + + + + + + + + + + + + + + + + + + 5.2.0 + + + 1.5.4 + + + gettext + + + + + Alarm + pear.horde.org + + + Auth + pear.horde.org + + + + + + + + + + + + + + + + + 2006-05-08 + + + 0.0.2 + 0.0.2 + + + alpha + alpha + + LGPL + Converted to package.xml 2.0 for pear.horde.org + + + + + 0.0.1 + 0.0.1 + + + alpha + alpha + + 2003-07-05 + LGPL + Initial release as a PEAR package + + + + -- 2.11.0