Overview

Packages

  • Notification

Classes

  • Horde_Notification
  • Horde_Notification_Event
  • Horde_Notification_Event_Status
  • Horde_Notification_Exception
  • Horde_Notification_Handler
  • Horde_Notification_Handler_Decorator_Alarm
  • Horde_Notification_Handler_Decorator_Base
  • Horde_Notification_Handler_Decorator_Log
  • Horde_Notification_Listener
  • Horde_Notification_Listener_Audio
  • Horde_Notification_Listener_Status
  • Horde_Notification_Storage_Object
  • Horde_Notification_Storage_Session

Interfaces

  • Horde_Notification_Storage_Interface
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * The Horde_Notification:: package provides a subject-observer pattern for
  4:  * raising and showing messages of different types and to different
  5:  * listeners.
  6:  *
  7:  * Copyright 2001-2012 Horde LLC (http://www.horde.org/)
  8:  *
  9:  * See the enclosed file COPYING for license information (LGPL). If you
 10:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
 11:  *
 12:  * @author   Jan Schneider <jan@horde.org>
 13:  * @category Horde
 14:  * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
 15:  * @package  Notification
 16:  */
 17: class Horde_Notification_Handler
 18: {
 19:     /**
 20:      * Decorators.
 21:      *
 22:      * @var array
 23:      */
 24:     protected $_decorators = array();
 25: 
 26:     /**
 27:      * Forces immediate attachment of a notification to a listener.
 28:      *
 29:      * @var boolean
 30:      */
 31:     protected $_forceAttach = false;
 32: 
 33:     /**
 34:      * Additional handle definitions.
 35:      *
 36:      * @var array
 37:      */
 38:     protected $_handles = array(
 39:         'default' => array(
 40:             '*' => 'Horde_Notification_Event'
 41:         )
 42:     );
 43: 
 44:     /**
 45:      * Hash containing all attached listener objects.
 46:      *
 47:      * @var array
 48:      */
 49:     protected $_listeners = array();
 50: 
 51:     /**
 52:      * The storage location where we store the messages.
 53:      *
 54:      * @var Horde_Notification_Storage
 55:      */
 56:     protected $_storage;
 57: 
 58:     /**
 59:      * Initialize the notification system.
 60:      *
 61:      * @param Horde_Notification_Storage $storage  The storage object to use.
 62:      */
 63:     public function __construct(Horde_Notification_Storage_Interface $storage)
 64:     {
 65:         $this->_storage = $storage;
 66:     }
 67: 
 68:     /**
 69:      * Registers a listener with the notification object and includes
 70:      * the necessary library file dynamically.
 71:      *
 72:      * @param string $listener  The name of the listener to attach. These
 73:      *                          names must be unique; further listeners with
 74:      *                          the same name will be ignored.
 75:      * @param array $params     A hash containing any additional configuration
 76:      *                          or connection parameters a listener driver
 77:      *                          might need.
 78:      * @param string $class     The class name from which the driver was
 79:      *                          instantiated if not the default one. If given
 80:      *                          you have to include the library file
 81:      *                          containing this class yourself. This is useful
 82:      *                          if you want the listener driver to be
 83:      *                          overriden by an application's implementation
 84:      *
 85:      * @return Horde_Notification_Listener  The listener object.
 86:      * @throws Horde_Exception
 87:      */
 88:     public function attach($listener, $params = null, $class = null)
 89:     {
 90:         if ($ob = $this->getListener($listener)) {
 91:             return $ob;
 92:         }
 93: 
 94:         if (is_null($class)) {
 95:             $class = 'Horde_Notification_Listener_' . Horde_String::ucfirst(Horde_String::lower($listener));
 96:         }
 97: 
 98:         if (class_exists($class)) {
 99:             $this->_listeners[$listener] = new $class($params);
100:             if (!$this->_storage->exists($listener)) {
101:                 $this->_storage->set($listener, array());
102:             }
103:             $this->_addTypes($listener);
104:             return $this->_listeners[$listener];
105:         }
106: 
107:         throw new Horde_Exception(sprintf('Notification listener %s not found.', $class));
108:     }
109: 
110:     /**
111:      * Remove a listener from the notification list.
112:      *
113:      * @param string $listner  The name of the listener to detach.
114:      *
115:      * @throws Horde_Exception
116:      */
117:     public function detach($listener)
118:     {
119:         if ($ob = $this->getListener($listener)) {
120:             unset($this->_listeners[$ob->getName()]);
121:             $this->_storage->clear($ob->getName());
122:         } else {
123:             throw new Horde_Exception(sprintf('Notification listener %s not found.', $listener));
124:         }
125:     }
126: 
127:     /**
128:      * Clear any notification events that may exist in a listener.
129:      *
130:      * @param string $listener  The name of the listener to flush. If null,
131:      *                          clears all unattached events.
132:      */
133:     public function clear($listener = null)
134:     {
135:         if (is_null($listener)) {
136:             $this->_storage->clear('_unattached');
137:         } elseif ($ob = $this->getListener($listener)) {
138:             $this->_storage->clear($ob->getName());
139:         }
140:     }
141: 
142:     /**
143:      * Returns the current Listener object for a given listener type.
144:      *
145:      * @param string $type  The listener type.
146:      *
147:      * @return mixed  A Horde_Notification_Listener object, or null if
148:      *                $type listener is not attached.
149:      */
150:     public function get($type)
151:     {
152:         foreach ($this->_listeners as $listener) {
153:             if ($listener->handles($type)) {
154:                 return $listener;
155:             }
156:         }
157: 
158:         return null;
159:     }
160: 
161:     /**
162:      * Returns a listener object given a listener name.
163:      *
164:      * @param string $listener  The listener name.
165:      *
166:      * @return mixed  Either a Horde_Notification_Listener or null.
167:      */
168:     public function getListener($listener)
169:     {
170:         $listener = Horde_String::lower(basename($listener));
171:         return empty($this->_listeners[$listener])
172:             ? null
173:             : $this->_listeners[$listener];
174:     }
175: 
176:     /**
177:      * Adds a type handler to a given Listener.
178:      * To change the default listener, use the following:
179:      * <pre>
180:      *   $ob->addType('default', '*', $classname);
181:      * </pre>
182:      *
183:      * @param string $listener  The listener name.
184:      * @param string $type      The listener type.
185:      * @param string $class     The Event class to use.
186:      */
187:     public function addType($listener, $type, $class)
188:     {
189:         $this->_handles[$listener][$type] = $class;
190: 
191:         if (isset($this->_listeners[$listener])) {
192:             $this->_addTypes($listener);
193:         }
194:     }
195: 
196:     /**
197:      * Adds any additional listener types to a given Listener.
198:      *
199:      * @param string $listener  The listener name.
200:      */
201:     protected function _addTypes($listener)
202:     {
203:         if (isset($this->_handles[$listener])) {
204:             foreach ($this->_handles[$listener] as $type => $class) {
205:                 $this->_listeners[$listener]->addType($type, $class);
206:             }
207:         }
208:     }
209: 
210:     /**
211:      * Add a decorator.
212:      *
213:      * @param Horde_Notification_Handler_Decorator_Base $decorator  The
214:      *                                                              Decorator
215:      *                                                              object.
216:      */
217:     public function addDecorator(Horde_Notification_Handler_Decorator_Base $decorator)
218:     {
219:         $this->_decorators[] = $decorator;
220:     }
221: 
222:     /**
223:      * Add an event to the Horde message stack.
224:      *
225:      * @param mixed $event    Horde_Notification_Event object or message
226:      *                        string.
227:      * @param integer $type   The type of message.
228:      * @param array $flags    Array of optional flags that will be passed to
229:      *                        the registered listeners.
230:      * @param array $options  Additional options:
231:      * <pre>
232:      * 'immediate' - (boolean) If true, immediately tries to attach to a
233:      *               listener. If no listener exists for this type, the
234:      *               message will be dropped.
235:      *               DEFAULT: false (message will be attached to available
236:      *               handler at the time notify() is called).
237:      * </pre>
238:      */
239:     public function push($event, $type = null, array $flags = array(),
240:                          $options = array())
241:     {
242:         if ($event instanceof Horde_Notification_Event) {
243:             $event->flags = $flags;
244:             $event->type = $type;
245:         } else {
246:             $class = (!is_null($type) && ($listener = $this->get($type)))
247:                 ? $listener->handles($type)
248:                 : $this->_handles['default']['*'];
249: 
250:             /* Transparently create a Horde_Notification_Event object. */
251:             $event = new $class($event, $type, $flags);
252:         }
253: 
254:         foreach ($this->_decorators as $decorator) {
255:             $decorator->push($event, $options);
256:         }
257: 
258:         if (!$this->_forceAttach && empty($options['immediate'])) {
259:             $this->_storage->push('_unattached', $event);
260:         } else {
261:             if ($listener = $this->get($event->type)) {
262:                 $this->_storage->push($listener->getName(), $event);
263:             }
264:         }
265:     }
266: 
267:     /**
268:      * Passes the message stack to all listeners and asks them to
269:      * handle their messages.
270:      *
271:      * @param array $options  An array containing display options for the
272:      *                        listeners. Any options not contained in this
273:      *                        list will be passed to the listeners.
274:      * <pre>
275:      * listeners - (array) The list of listeners to notify.
276:      * raw - (boolean) If true, does not call the listener's notify()
277:      *       function.
278:      * </pre>
279:      */
280:     public function notify(array $options = array())
281:     {
282:         /* Convert the 'listeners' option into the format expected by the
283:          * notification handler. */
284:         if (!isset($options['listeners'])) {
285:             $listeners = array_keys($this->_listeners);
286:         } elseif (!is_array($options['listeners'])) {
287:             $listeners = array($options['listeners']);
288:         } else {
289:             $listeners = $options['listeners'];
290:         }
291: 
292:         $events = array();
293:         $unattached = $this->_storage->exists('_unattached')
294:             ? $this->_storage->get('_unattached')
295:             : array();
296: 
297:         /* Pass the message stack to all listeners and asks them to handle
298:          * their messages. */
299:         foreach ($listeners as $listener) {
300:             $listener = Horde_String::lower($listener);
301: 
302:             if (isset($this->_listeners[$listener])) {
303:                 $instance = $this->_listeners[$listener];
304:                 $name = $instance->getName();
305: 
306:                 foreach (array_keys($unattached) as $val) {
307:                     if ($unattached[$val] instanceof Horde_Notification_Event
308:                         && $instance->handles($unattached[$val]->type)) {
309:                         $this->_storage->push($name, $unattached[$val]);
310:                         unset($unattached[$val]);
311:                     }
312:                 }
313: 
314:                 foreach ($this->_decorators as $decorator) {
315:                     $this->_forceAttach = true;
316:                     try {
317:                         $decorator->notify($this, $instance);
318:                     } catch (Horde_Notification_Exception $e) {
319:                         $this->push($e);
320:                     }
321:                     $this->_forceAttach = false;
322:                 }
323: 
324:                 if (!$this->_storage->exists($name)) {
325:                     continue;
326:                 }
327: 
328:                 $tmp = $this->_storage->get($name);
329:                 if (empty($options['raw'])) {
330:                     $instance->notify($tmp, $options);
331:                 }
332:                 $this->_storage->clear($name);
333: 
334:                 $events = array_merge($events, $tmp);
335:             }
336:         }
337: 
338:         if (empty($unattached)) {
339:             $this->_storage->clear('_unattached');
340:         } else {
341:             $this->_storage->set('_unattached', $unattached);
342:         }
343: 
344:         return $events;
345:     }
346: 
347:     /**
348:      * Return the number of notification messages in the stack.
349:      *
350:      * @author David Ulevitch <davidu@everydns.net>
351:      *
352:      * @param string $my_listener  The name of the listener.
353:      *
354:      * @return integer  The number of messages in the stack.
355:      */
356:     public function count($my_listener = null)
357:     {
358:         $count = 0;
359: 
360:         if (!is_null($my_listener)) {
361:             if ($ob = $this->get($my_listener)) {
362:                 $count = count($this->_storage->get($ob->getName()));
363: 
364:                 if ($this->_storage->exists('_unattached')) {
365:                     foreach ($this->_storage->get('_unattached') as $val) {
366:                         if ($ob->handles($val->type)) {
367:                             ++$count;
368:                         }
369:                     }
370:                 }
371:             }
372:         } else {
373:             if ($this->_storage->exists('_unattached')) {
374:                 $count = count($this->_storage->get('_unattached'));
375:             }
376: 
377:             foreach ($this->_listeners as $val) {
378:                 if ($this->_storage->exists($val->getName())) {
379:                     $count += count($this->_storage->get($val->getName()));
380:                 }
381:             }
382:         }
383: 
384:         return $count;
385:     }
386: 
387: }
388: 
API documentation generated by ApiGen