diff --git a/plugins/tasklist/drivers/database/tasklist_database_driver.php b/plugins/tasklist/drivers/database/tasklist_database_driver.php index 9bd06254..2b3ff90a 100644 --- a/plugins/tasklist/drivers/database/tasklist_database_driver.php +++ b/plugins/tasklist/drivers/database/tasklist_database_driver.php @@ -337,6 +337,70 @@ class tasklist_database_driver extends tasklist_driver return false; } + /** + * Get a list of pending alarms to be displayed to the user + * + * @param integer Current time (unix timestamp) + * @param mixed List of list IDs to show alarms for (either as array or comma-separated string) + * @return array A list of alarms, each encoded as hash array with task properties + * @see tasklist_driver::pending_alarms() + */ + public function pending_alarms($time, $lists = null) + { + if (empty($lists)) + $lists = array_keys($this->lists); + else if (is_string($lists)) + $lists = explode(',', $lists); + + // only allow to select from calendars with activated alarms + $list_ids = array(); + foreach ($lists as $lid) { + if ($this->lists[$lid] && $this->lists[$lid]['showalarms']) + $list_ids[] = $lid; + } + $list_ids = array_map(array($this->rc->db, 'quote'), $list_ids); + + $alarms = array(); + if (!empty($list_ids)) { + $result = $this->rc->db->query(sprintf( + "SELECT * FROM " . $this->db_tasks . " + WHERE tasklist_id IN (%s) + AND notify <= %s AND date > %s", + join(',', $list_ids), + $this->rc->db->fromunixtime($time), + $this->rc->db->fromunixtime($time) + )); + + while ($result && ($rec = $this->rc->db->fetch_assoc($result))) + $alarms[] = $this->_read_postprocess($rec); + } + + return $alarms; + } + + /** + * Feedback after showing/sending an alarm notification + * + * @see tasklist_driver::dismiss_alarm() + */ + public function dismiss_alarm($task_id, $snooze = 0) + { + // set new notifyat time or unset if not snoozed + $notify_at = $snooze > 0 ? date('Y-m-d H:i:s', time() + $snooze) : null; + + $query = $this->rc->db->query(sprintf( + "UPDATE " . $this->db_tasks . " + SET changed=%s, notify=? + WHERE task_id=? + AND tasklist_id IN (" . $this->list_ids . ")", + $this->rc->db->now()), + $notify_at, + $task_id + ); + + return $this->rc->db->affected_rows($query); + } + /** * Map some internal database values to match the generic "API" */ @@ -514,9 +578,9 @@ class tasklist_database_driver extends tasklist_driver // fake object properties to suit the expectations of calendar::get_next_alarm() // TODO: move all that to libcalendaring plugin if ($task['date']) - $task['start'] = new DateTime($task['date'] . ' ' . ($task['time'] ?: '23:00'), $this->plugin->timezone); + $task['start'] = new DateTime($task['date'] . ' ' . ($task['time'] ?: '12:00'), $this->plugin->timezone); if ($task['startdate']) - $task['end'] = new DateTime($task['startdate'] . ' ' . ($task['starttime'] ?: '06:00'), $this->plugin->timezone); + $task['end'] = new DateTime($task['startdate'] . ' ' . ($task['starttime'] ?: '12:00'), $this->plugin->timezone); else $task['end'] = $tast['start']; diff --git a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php index 25d4c087..03b9926e 100644 --- a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php +++ b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php @@ -316,6 +316,31 @@ class tasklist_kolab_driver extends tasklist_driver return $this->tasks[$id]; } + /** + * Get a list of pending alarms to be displayed to the user + * + * @param integer Current time (unix timestamp) + * @param mixed List of list IDs to show alarms for (either as array or comma-separated string) + * @return array A list of alarms, each encoded as hash array with task properties + * @see tasklist_driver::pending_alarms() + */ + public function pending_alarms($time, $lists = null) + { + // TODO: implement this + } + + /** + * (User) feedback after showing an alarm notification + * This should mark the alarm as 'shown' or snooze it for the given amount of time + * + * @param string Task identifier + * @param integer Suspend the alarm for this number of seconds + */ + public function dismiss_alarm($id, $snooze = 0) + { + // TODO: implement this + } + /** * Convert from Kolab_Format to internal representation */ diff --git a/plugins/tasklist/drivers/tasklist_driver.php b/plugins/tasklist/drivers/tasklist_driver.php index 924da21e..0d3a365d 100644 --- a/plugins/tasklist/drivers/tasklist_driver.php +++ b/plugins/tasklist/drivers/tasklist_driver.php @@ -128,6 +128,29 @@ abstract class tasklist_driver */ abstract function list_tasks($filter, $lists = null); + /** + * Get a list of pending alarms to be displayed to the user + * + * @param integer Current time (unix timestamp) + * @param mixed List of list IDs to show alarms for (either as array or comma-separated string) + * @return array A list of alarms, each encoded as hash array with task properties + * id: Task identifier + * uid: Unique identifier of this task + * date: Task due date + * time: Task due time + * title: Task title/summary + */ + abstract function pending_alarms($time, $lists = null); + + /** + * (User) feedback after showing an alarm notification + * This should mark the alarm as 'shown' or snooze it for the given amount of time + * + * @param string Task identifier + * @param integer Suspend the alarm for this number of seconds + */ + abstract function dismiss_alarm($id, $snooze = 0); + /** * Return data of a specific task * diff --git a/plugins/tasklist/tasklist.php b/plugins/tasklist/tasklist.php index 13635a70..9589354e 100644 --- a/plugins/tasklist/tasklist.php +++ b/plugins/tasklist/tasklist.php @@ -113,6 +113,10 @@ class tasklist extends rcube_plugin $this->ui = new tasklist_ui($this); $this->ui->init(); } + + // add hooks for alarms handling + $this->add_hook('pending_alarms', array($this, 'pending_alarms')); + $this->add_hook('dismiss_alarms', array($this, 'dismiss_alarms')); } @@ -619,6 +623,43 @@ class tasklist extends rcube_plugin } + /** + * Handler for pending_alarms plugin hook triggered by the calendar module on keep-alive requests. + * This will check for pending notifications and pass them to the client + */ + public function pending_alarms($p) + { + $this->load_driver(); + if ($alarms = $this->driver->pending_alarms($p['time'] ?: time())) { + foreach ($alarms as $alarm) { + // encode alarm object to suit the expectations of the calendaring code + if ($alarm['date']) + $alarm['start'] = new DateTime($alarm['date'].' '.$alarm['time'], $this->timezone); + + $alarm['id'] = 'task:' . $alarm['id']; // prefix ID with task: + $alarm['allday'] = empty($alarm['time']) ? 1 : 0; + $p['alarms'][] = $alarm; + } + } + + return $p; + } + + /** + * Handler for alarm dismiss hook triggered by the calendar module + */ + public function dismiss_alarms($p) + { + $this->load_driver(); + foreach ((array)$p['ids'] as $id) { + if (strpos($id, 'task:') === 0) + $p['success'] |= $this->driver->dismiss_alarm(substr($id, 5), $p['snooze']); + } + + return $p; + } + + /******* Attachment handling *******/ /*** pretty much the same as in plugins/calendar/calendar.php ***/