Overview

Packages

  • Alarm

Classes

  • Horde_Alarm
  • Horde_Alarm_Exception
  • Horde_Alarm_Handler
  • Horde_Alarm_Handler_Desktop
  • Horde_Alarm_Handler_Mail
  • Horde_Alarm_Handler_Notify
  • Horde_Alarm_Null
  • Horde_Alarm_Object
  • Horde_Alarm_Sql
  • Horde_Alarm_Translation
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * @package Alarm
  4:  *
  5:  * Copyright 2007-2012 Horde LLC (http://www.horde.org/)
  6:  *
  7:  * See the enclosed file COPYING for license information (LGPL). If you
  8:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
  9:  */
 10: 
 11: /**
 12:  * The Horde_Alarm:: class provides an interface to deal with reminders,
 13:  * alarms and notifications through a standardized API.
 14:  *
 15:  * @author  Jan Schneider <jan@horde.org>
 16:  * @package Alarm
 17:  */
 18: abstract class Horde_Alarm
 19: {
 20:     /**
 21:      * Logger.
 22:      *
 23:      * @var Horde_Log_Logger
 24:      */
 25:     protected $_logger;
 26: 
 27:     /**
 28:      * Alarm loader callback.
 29:      *
 30:      * @var mixed
 31:      */
 32:     protected $_loader;
 33: 
 34:     /**
 35:      * Hash containing connection parameters.
 36:      *
 37:      * @var array
 38:      */
 39:     protected $_params = array(
 40:         'ttl' => 300
 41:     );
 42: 
 43:     /**
 44:      * All registered notification handlers.
 45:      *
 46:      * @var array
 47:      */
 48:     protected $_handlers = array();
 49: 
 50:     /**
 51:      * Whether handler classes have been dynamically loaded already.
 52:      *
 53:      * @var boolean
 54:      */
 55:     protected $_handlersLoaded = false;
 56: 
 57:     /**
 58:      * Constructor.
 59:      *
 60:      * @param array $params  Configuration parameters:
 61:      * <pre>
 62:      * 'logger' - (Horde_Log_Logger) A logger instance.
 63:      * 'ttl' - (integer) Time to live value, in seconds.
 64:      * </pre>
 65:      */
 66:     public function __construct(array $params = array())
 67:     {
 68:         if (isset($params['logger'])) {
 69:             $this->_logger = $params['logger'];
 70:             unset($params['logger']);
 71:         }
 72:         if (isset($params['loader'])) {
 73:             $this->_loader = $params['loader'];
 74:             unset($params['loader']);
 75:         }
 76:         $this->_params = array_merge($this->_params, $params);
 77:     }
 78: 
 79:     /**
 80:      * Returns a list of alarms from the backend.
 81:      *
 82:      * @param string $user      Return alarms for this user, all users if
 83:      *                          null, or global alarms if empty.
 84:      * @param Horde_Date $time  The time when the alarms should be active.
 85:      *                          Defaults to now.
 86:      * @param boolean $load     Update active alarms from all applications?
 87:      * @param boolean $preload  Preload alarms that go off within the next
 88:      *                          ttl time span?
 89:      *
 90:      * @return array  A list of alarm hashes.
 91:      * @throws Horde_Alarm_Exception
 92:      */
 93:     public function listAlarms($user = null, Horde_Date $time = null,
 94:                                $load = false, $preload = true)
 95:     {
 96:         if (empty($time)) {
 97:             $time = new Horde_Date(time());
 98:         }
 99:         if ($load && is_callable($this->_loader)) {
100:             call_user_func($this->_loader, $user, $preload);
101:         }
102: 
103:         $alarms = $this->_list($user, $time);
104: 
105:         foreach (array_keys($alarms) as $alarm) {
106:             if (isset($alarms[$alarm]['mail']['body'])) {
107:                 $alarms[$alarm]['mail']['body'] = $this->_fromDriver($alarms[$alarm]['mail']['body']);
108:             }
109:         }
110:         return $alarms;
111:     }
112: 
113:     /**
114:      * Returns a list of alarms from the backend.
115:      *
116:      * @param Horde_Date $time  The time when the alarms should be active.
117:      * @param string $user      Return alarms for this user, all users if
118:      *                          null, or global alarms if empty.
119:      *
120:      * @return array  A list of alarm hashes.
121:      * @throws Horde_Alarm_Exception
122:      */
123:     abstract protected function _list($user, Horde_Date $time);
124: 
125:     /**
126:      * Returns a list of all global alarms from the backend.
127:      *
128:      * @return array  A list of alarm hashes.
129:      * @throws Horde_Alarm_Exception
130:      */
131:     public function globalAlarms()
132:     {
133:         $alarms = $this->_global();
134:         foreach (array_keys($alarms) as $alarm) {
135:             if (isset($alarms[$alarm]['mail']['body'])) {
136:                 $alarms[$alarm]['mail']['body'] = $this->_fromDriver($alarms[$alarm]['mail']['body']);
137:             }
138:         }
139:         return $alarms;
140:     }
141: 
142:     /**
143:      * Returns a list of all global alarms from the backend.
144:      *
145:      * @return array  A list of alarm hashes.
146:      */
147:     abstract protected function _global();
148: 
149:     /**
150:      * Returns an alarm hash from the backend.
151:      *
152:      * @param string $id    The alarm's unique id.
153:      * @param string $user  The alarm's user
154:      *
155:      * @return array  An alarm hash. Contains the following:
156:      * <pre>
157:      * id: Unique alarm id.
158:      * user: The alarm's user. Empty if a global alarm.
159:      * start: The alarm start as a Horde_Date.
160:      * end: The alarm end as a Horde_Date.
161:      * methods: The notification methods for this alarm.
162:      * params: The paramters for the notification methods.
163:      * title: The alarm title.
164:      * text: An optional alarm description.
165:      * snooze: The snooze time (next time) of the alarm as a Horde_Date.
166:      * internal: Holds internally used data.
167:      * </pre>
168:      * @throws Horde_Alarm_Exception
169:      */
170:     public function get($id, $user)
171:     {
172:         $alarm = $this->_get($id, $user);
173: 
174:         if (isset($alarm['mail']['body'])) {
175:             $alarm['mail']['body'] = $this->_fromDriver($alarm['mail']['body']);
176:         }
177: 
178:         return $alarm;
179:     }
180: 
181:     /**
182:      * Returns an alarm hash from the backend.
183:      *
184:      * @param string $id    The alarm's unique id.
185:      * @param string $user  The alarm's user
186:      *
187:      * @return array  An alarm hash.
188:      * @throws Horde_Alarm_Exception
189:      */
190:     abstract protected function _get($id, $user);
191: 
192:     /**
193:      * Stores an alarm hash in the backend.
194:      *
195:      * The alarm will be added if it doesn't exist, and updated otherwise.
196:      *
197:      * @param array $alarm   An alarm hash. See self::get() for format.
198:      * @param boolean $keep  Whether to keep the snooze value and notification
199:      *                       status unchanged. If true, the alarm will get
200:      *                       "un-snoozed", and notifications (like mails) are
201:      *                       sent again.
202:      *
203:      * @throws Horde_Alarm_Exception
204:      */
205:     public function set(array $alarm, $keep = false)
206:     {
207:         if (isset($alarm['mail']['body'])) {
208:             $alarm['mail']['body'] = $this->_toDriver($alarm['mail']['body']);
209:         }
210: 
211:         if ($this->exists($alarm['id'], isset($alarm['user']) ? $alarm['user'] : '')) {
212:             $this->_update($alarm, $keep);
213:             if (!$keep) {
214:                 foreach ($this->_handlers as &$handler) {
215:                     $handler->reset($alarm);
216:                 }
217:             }
218:         } else {
219:             $this->_add($alarm);
220:         }
221:     }
222: 
223:     /**
224:      * Adds an alarm hash to the backend.
225:      *
226:      * @param array $alarm  An alarm hash.
227:      *
228:      * @throws Horde_Alarm_Exception
229:      */
230:     abstract protected function _add(array $alarm);
231: 
232:     /**
233:      * Updates an alarm hash in the backend.
234:      *
235:      * @param array $alarm         An alarm hash.
236:      * @param boolean $keepsnooze  Whether to keep the snooze value unchanged.
237:      *
238:      * @throws Horde_Alarm_Exception
239:      */
240:     abstract protected function _update(array $alarm, $keepsnooze = false);
241: 
242:     /**
243:      * Updates internal alarm properties, i.e. properties not determined by
244:      * the application setting the alarm.
245:      *
246:      * @param string $id       The alarm's unique id.
247:      * @param string $user     The alarm's user
248:      * @param array $internal  A hash with the internal data.
249:      *
250:      * @throws Horde_Alarm_Exception
251:      */
252:     abstract public function internal($id, $user, array $internal);
253: 
254:     /**
255:      * Returns whether an alarm with the given id exists already.
256:      *
257:      * @param string $id    The alarm's unique id.
258:      * @param string $user  The alarm's user
259:      *
260:      * @return boolean  True if the specified alarm exists.
261:      */
262:     public function exists($id, $user)
263:     {
264:         try {
265:             return $this->_exists($id, $user);
266:         } catch (Horde_Alarm_Exception $e) {
267:             return false;
268:         }
269:     }
270: 
271:     /**
272:      * Returns whether an alarm with the given id exists already.
273:      *
274:      * @param string $id    The alarm's unique id.
275:      * @param string $user  The alarm's user
276:      *
277:      * @return boolean  True if the specified alarm exists.
278:      * @throws Horde_Alarm_Exception
279:      */
280:     abstract protected function _exists($id, $user);
281: 
282:     /**
283:      * Delays (snoozes) an alarm for a certain period.
284:      *
285:      * @param string $id        The alarm's unique id.
286:      * @param string $user      The notified user.
287:      * @param integer $minutes  The delay in minutes. A negative value
288:      *                          dismisses the alarm completely.
289:      *
290:      * @throws Horde_Alarm_Exception
291:      */
292:     public function snooze($id, $user, $minutes)
293:     {
294:         if (empty($user)) {
295:             throw new Horde_Alarm_Exception('This alarm cannot be snoozed.');
296:         }
297: 
298:         $alarm = $this->get($id, $user);
299: 
300:         if ($alarm) {
301:             if ($minutes > 0) {
302:                 $alarm['snooze'] = new Horde_Date(time());
303:                 $alarm['snooze']->min += $minutes;
304:                 $this->_snooze($id, $user, $alarm['snooze']);
305:                 return;
306:             }
307: 
308:             $this->_dismiss($id, $user);
309:         }
310:     }
311: 
312:     /**
313:      * Delays (snoozes) an alarm for a certain period.
314:      *
315:      * @param string $id          The alarm's unique id.
316:      * @param string $user        The alarm's user
317:      * @param Horde_Date $snooze  The snooze time.
318:      *
319:      * @throws Horde_Alarm_Exception
320:      */
321:     abstract protected function _snooze($id, $user, Horde_Date $snooze);
322: 
323:     /**
324:      * Returns whether an alarm is snoozed.
325:      *
326:      * @param string $id        The alarm's unique id.
327:      * @param string $user      The alarm's user
328:      * @param Horde_Date $time  The time when the alarm may be snoozed.
329:      *                          Defaults to now.
330:      *
331:      * @return boolean  True if the alarm is snoozed.
332:      *
333:      * @throws Horde_Alarm_Exception
334:      */
335:     public function isSnoozed($id, $user, Horde_Date $time = null)
336:     {
337:         if (is_null($time)) {
338:             $time = new Horde_Date(time());
339:         }
340:         return (bool)$this->_isSnoozed($id, $user, $time);
341:     }
342: 
343:     /**
344:      * Returns whether an alarm is snoozed.
345:      *
346:      * @param string $id        The alarm's unique id.
347:      * @param string $user      The alarm's user
348:      * @param Horde_Date $time  The time when the alarm may be snoozed.
349:      *
350:      * @return boolean  True if the alarm is snoozed.
351:      * @throws Horde_Alarm_Exception
352:      */
353:     abstract protected function _isSnoozed($id, $user, Horde_Date $time);
354: 
355:     /**
356:      * Dismisses an alarm.
357:      *
358:      * @param string $id          The alarm's unique id.
359:      * @param string $user        The alarm's user
360:      *
361:      * @throws Horde_Alarm_Exception
362:      */
363:     abstract protected function _dismiss($id, $user);
364: 
365:     /**
366:      * Deletes an alarm from the backend.
367:      *
368:      * @param string $id    The alarm's unique id.
369:      * @param string $user  The alarm's user. All users' alarms if null.
370:      *
371:      * @throws Horde_Alarm_Exception
372:      */
373:     function delete($id, $user = null)
374:     {
375:         $this->_delete($id, $user);
376:     }
377: 
378:     /**
379:      * Deletes an alarm from the backend.
380:      *
381:      * @param string $id    The alarm's unique id.
382:      * @param string $user  The alarm's user. All users' alarms if null.
383:      *
384:      * @throws Horde_Alarm_Exception
385:      */
386:     abstract protected function _delete($id, $user = null);
387: 
388:     /**
389:      * Notifies the user about any active alarms.
390:      *
391:      * @param string $user      Notify this user, all users if null, or guest
392:      *                          users if empty.
393:      * @param boolean $load     Update active alarms from all applications?
394:      * @param boolean $preload  Preload alarms that go off within the next
395:      *                          ttl time span?
396:      * @param array $exclude    Don't notify with these methods.
397:      *
398:      * @throws Horde_Alarm_Exception
399:      */
400:     public function notify($user = null, $load = true, $preload = true,
401:                            array $exclude = array())
402:     {
403:         try {
404:             $alarms = $this->listAlarms($user, null, $load, $preload);
405:         } catch (Horde_Alarm_Exception $e) {
406:             if ($this->_logger) {
407:                 $this->_logger->log($e, 'ERR');
408:             }
409:             throw $e;
410:         }
411: 
412:         if (empty($alarms)) {
413:             return;
414:         }
415: 
416:         $handlers = $this->handlers();
417:         foreach ($alarms as $alarm) {
418:             foreach ($alarm['methods'] as $alarm_method) {
419:                 if (isset($handlers[$alarm_method]) &&
420:                     !in_array($alarm_method, $exclude)) {
421:                     $handlers[$alarm_method]->notify($alarm);
422:                 }
423:             }
424:         }
425:     }
426: 
427:     /**
428:      * Registers a notification handler.
429:      *
430:      * @param string $name                  A handler name.
431:      * @param Horde_Alarm_Handler $handler  A notification handler.
432:      */
433:     public function addHandler($name, Horde_Alarm_Handler $handler)
434:     {
435:         $this->_handlers[$name] = $handler;
436:         $handler->alarm = $this;
437:     }
438: 
439:     /**
440:      * Returns a list of available notification handlers and parameters.
441:      *
442:      * The returned list is a hash with method names as the keys and
443:      * optionally associated parameters as values. The parameters are hashes
444:      * again with parameter names as keys and parameter information as
445:      * values. The parameter information is hash with the following keys:
446:      * 'desc' contains a parameter description; 'required' specifies whether
447:      * this parameter is required.
448:      *
449:      * @return array  List of methods and parameters.
450:      */
451:     public function handlers()
452:     {
453:         if (!$this->_handlersLoaded) {
454:             foreach (new DirectoryIterator(dirname(__FILE__) . '/Alarm/Handler') as $file) {
455:                 if (!$file->isFile() || substr($file->getFilename(), -4) != '.php') {
456:                     continue;
457:                 }
458:                 $handler = Horde_String::lower($file->getBasename('.php'));
459:                 if (isset($this->_handlers[$handler])) {
460:                     continue;
461:                 }
462:                 require_once $file->getPathname();
463:                 $class = 'Horde_Alarm_Handler_' . $file->getBasename('.php');
464:                 if (class_exists($class, false)) {
465:                     $this->addHandler($handler, new $class());
466:                 }
467:             }
468:             $this->_handlerLoaded = true;
469:         }
470: 
471:         return $this->_handlers;
472:     }
473: 
474:     /**
475:      * Garbage collects old alarms in the backend.
476:      *
477:      * @param boolean $force  Force garbace collection? If false, GC happens
478:      *                        with a 1% chance.
479:      *
480:      * @throws Horde_Alarm_Exception
481:      */
482:     public function gc($force = false)
483:     {
484:         /* A 1% chance we will run garbage collection during a call. */
485:         if ($force || rand(0, 99) == 0) {
486:             $this->_gc();
487:         }
488:     }
489: 
490:     /**
491:      * Garbage collects old alarms in the backend.
492:      *
493:      * @throws Horde_Alarm_Exception
494:      */
495:     abstract protected function _gc();
496: 
497:     /**
498:      * Attempts to initialize the backend.
499:      *
500:      * @throws Horde_Alarm_Exception
501:      */
502:     abstract public function initialize();
503: 
504:     /**
505:      * Converts a value from the driver's charset.
506:      *
507:      * @param mixed $value  Value to convert.
508:      *
509:      * @return mixed  Converted value.
510:      */
511:     abstract protected function _fromDriver($value);
512: 
513:     /**
514:      * Converts a value to the driver's charset.
515:      *
516:      * @param mixed $value  Value to convert.
517:      *
518:      * @return mixed  Converted value.
519:      */
520:     abstract protected function _toDriver($value);
521: 
522: }
523: 
API documentation generated by ApiGen