3 commits - plugins/calendar plugins/tasklist

Thomas Brüderli bruederli at kolabsys.com
Fri Aug 3 21:34:34 CEST 2012


 plugins/calendar/calendar.php                                  |   31 +++-
 plugins/calendar/calendar_base.js                              |   25 ++-
 plugins/calendar/calendar_ui.js                                |    2 
 plugins/calendar/skins/classic/templates/freebusylegend.html   |   10 -
 plugins/calendar/skins/larry/templates/freebusylegend.html     |   10 -
 plugins/tasklist/drivers/database/tasklist_database_driver.php |   68 +++++++++-
 plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php       |   25 +++
 plugins/tasklist/drivers/tasklist_driver.php                   |   23 +++
 plugins/tasklist/tasklist.php                                  |   41 ++++++
 9 files changed, 206 insertions(+), 29 deletions(-)

New commits:
commit 7b660767057374d6d509741d81705fcf7e2fa591
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Fri Aug 3 21:34:00 2012 +0200

    Hook into the alarms infrastructure of the calendar plugin. This is to be refactored into a libcalendaring plugin

diff --git a/plugins/tasklist/drivers/database/tasklist_database_driver.php b/plugins/tasklist/drivers/database/tasklist_database_driver.php
index 9bd0625..2b3ff90 100644
--- a/plugins/tasklist/drivers/database/tasklist_database_driver.php
+++ b/plugins/tasklist/drivers/database/tasklist_database_driver.php
@@ -338,6 +338,70 @@ class tasklist_database_driver extends tasklist_driver
     }
 
     /**
+     * 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"
      */
     private function _read_postprocess($rec)
@@ -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 25d4c08..03b9926 100644
--- a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
+++ b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
@@ -317,6 +317,31 @@ class tasklist_kolab_driver extends tasklist_driver
     }
 
     /**
+     * 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
      */
     private function _to_rcube_task($record)
diff --git a/plugins/tasklist/drivers/tasklist_driver.php b/plugins/tasklist/drivers/tasklist_driver.php
index 924da21..0d3a365 100644
--- a/plugins/tasklist/drivers/tasklist_driver.php
+++ b/plugins/tasklist/drivers/tasklist_driver.php
@@ -129,6 +129,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
      *
      * @param mixed  Hash array with task properties or task UID
diff --git a/plugins/tasklist/tasklist.php b/plugins/tasklist/tasklist.php
index 13635a7..9589354 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 ***/
 


commit c0fc38ab9c4585e29abd44d7bdf21ea95fcbeb81
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Fri Aug 3 21:29:10 2012 +0200

    Trigger plugin hooks to display and snooze/dismiss alarms

diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index 5061f20..e0c7126 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -772,8 +772,13 @@ class calendar extends rcube_plugin
         break;
 
       case "dismiss":
-        foreach (explode(',', $event['id']) as $id)
-          $success |= $this->driver->dismiss_alarm($id, $event['snooze']);
+        $event['ids'] = explode(',', $event['id']);
+        $plugin = $this->rc->plugins->exec_hook('dismiss_alarms', $event);
+        $success = $plugin['success'];
+        foreach ($event['ids'] as $id) {
+            if (strpos($id, 'cal:') === 0)
+                $success |= $this->driver->dismiss_alarm(substr($id, 4), $event['snooze']);
+        }
         break;
     }
     
@@ -833,15 +838,25 @@ class calendar extends rcube_plugin
    */
   function keep_alive($attr)
   {
+    $timestamp = time();
     $this->load_driver();
-    $alarms = $this->driver->pending_alarms(time());
-    if ($alarms) {
+    $alarms = $this->driver->pending_alarms($timestamp);
+    foreach ($alarms as $i => $alarm) {
+        $alarms[$i]['id'] = 'cal:' . $alarm['id'];  // prefix ID with cal:
+    }
+
+    $plugin = $this->rc->plugins->exec_hook('pending_alarms', array(
+      'time' => $timestamp,
+      'alarms' => $alarms,
+    ));
+
+    if (!$plugin['abort'] && $plugin['alarms']) {
       // make sure texts and env vars are available on client
       if ($this->rc->task != 'calendar') {
         $this->add_texts('localization/', true);
         $this->rc->output->set_env('snooze_select', $this->ui->snooze_select());
       }
-      $this->rc->output->command('plugin.display_alarms', $this->_alarms_output($alarms));
+      $this->rc->output->command('plugin.display_alarms', $this->_alarms_output($plugin['alarms']));
     }
   }
   
@@ -1181,9 +1196,9 @@ class calendar extends rcube_plugin
     foreach ($alarms as $alarm) {
       $out[] = array(
         'id'       => $alarm['id'],
-        'start'    => $this->adjust_timezone($alarm['start'])->format('c'),
-        'end'      => $this->adjust_timezone($alarm['end'])->format('c'),
-        'allDay'   => ($event['allday'] == 1)?true:false,
+        'start'    => $alarm['start'] ? $this->adjust_timezone($alarm['start'])->format('c') : '',
+        'end'      => $alarm['end']   ? $this->adjust_timezone($alarm['end'])->format('c') : '',
+        'allDay'   => ($alarm['allday'] == 1)?true:false,
         'title'    => $alarm['title'],
         'location' => $alarm['location'],
         'calendar' => $alarm['calendar'],
diff --git a/plugins/calendar/calendar_base.js b/plugins/calendar/calendar_base.js
index a77af01..d0a4a58 100644
--- a/plugins/calendar/calendar_base.js
+++ b/plugins/calendar/calendar_base.js
@@ -46,15 +46,24 @@ function rcube_calendar(settings)
     // create a nice human-readable string for the date/time range
     this.event_date_text = function(event)
     {
+      if (!event.start)
+        return '';
+      if (!event.end)
+        event.end = event.start;
+
       var fromto, duration = event.end.getTime() / 1000 - event.start.getTime() / 1000;
-      if (event.allDay)
-        fromto = $.fullCalendar.formatDate(event.start, settings['date_format']) + (duration > 86400 || event.start.getDay() != event.end.getDay() ? ' — ' + $.fullCalendar.formatDate(event.end, settings['date_format']) : '');
-      else if (duration < 86400 && event.start.getDay() == event.end.getDay())
-        fromto = $.fullCalendar.formatDate(event.start, settings['date_format']) + ' ' + $.fullCalendar.formatDate(event.start, settings['time_format']) +  ' — '
-          + $.fullCalendar.formatDate(event.end, settings['time_format']);
-      else
-        fromto = $.fullCalendar.formatDate(event.start, settings['date_format']) + ' ' + $.fullCalendar.formatDate(event.start, settings['time_format']) +  ' — '
-          + $.fullCalendar.formatDate(event.end, settings['date_format']) + ' ' + $.fullCalendar.formatDate(event.end, settings['time_format']);
+      if (event.allDay) {
+        fromto = $.fullCalendar.formatDate(event.start, settings['date_format'])
+          + (duration > 86400 || event.start.getDay() != event.end.getDay() ? ' — ' + $.fullCalendar.formatDate(event.end, settings['date_format']) : '');
+      }
+      else if (duration < 86400 && event.start.getDay() == event.end.getDay()) {
+        fromto = $.fullCalendar.formatDate(event.start, settings['date_format']) + ' ' + $.fullCalendar.formatDate(event.start, settings['time_format'])
+          + (duration > 0 ? ' — ' + $.fullCalendar.formatDate(event.end, settings['time_format']) : '');
+      }
+      else {
+        fromto = $.fullCalendar.formatDate(event.start, settings['date_format']) + ' ' + $.fullCalendar.formatDate(event.start, settings['time_format'])
+          + (duration > 0 ? ' — ' + $.fullCalendar.formatDate(event.end, settings['date_format']) + ' ' + $.fullCalendar.formatDate(event.end, settings['time_format']) : '');
+      }
 
       return fromto;
     };


commit 370b60e3eefdbc0189963b1e1a0fb1b52544d4a2
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Fri Aug 3 21:25:38 2012 +0200

    Change location to blank.gif which has changed in Roundcube core

diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index 2c27590..56725db 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -1464,7 +1464,7 @@ function rcube_calendar_ui(settings)
       
       var html = '<td class="role">' + select + '</td>' +
         '<td class="name">' + dispname + '</td>' +
-        '<td class="availability"><img src="./program/blank.gif" class="availabilityicon ' + avail + '" /></td>' +
+        '<td class="availability"><img src="./program/resources/blank.gif" class="availabilityicon ' + avail + '" /></td>' +
         '<td class="confirmstate"><span class="' + String(data.status).toLowerCase() + '">' + Q(data.status) + '</span></td>' +
         '<td class="options">' + (organizer || readonly ? '' : dellink) + '</td>';
       
diff --git a/plugins/calendar/skins/classic/templates/freebusylegend.html b/plugins/calendar/skins/classic/templates/freebusylegend.html
index 5cc01a1..85a565c 100644
--- a/plugins/calendar/skins/classic/templates/freebusylegend.html
+++ b/plugins/calendar/skins/classic/templates/freebusylegend.html
@@ -1,7 +1,7 @@
   <div id="edit-attendees-legend" class="availability">
-    <span class="legend"><img class="availabilityicon free" src="./program/blank.gif" /> <roundcube:label name="calendar.availfree" /></span>
-    <span class="legend"><img class="availabilityicon busy" src="./program/blank.gif" /> <roundcube:label name="calendar.availbusy" /></span>
-    <span class="legend"><img class="availabilityicon tentative" src="./program/blank.gif" /> <roundcube:label name="calendar.availtentative" /></span>
-    <span class="legend"><img class="availabilityicon out-of-office" src="./program/blank.gif" /> <roundcube:label name="calendar.availoutofoffice" /></span>
-    <span class="legend"><img class="availabilityicon unknown" src="./program/blank.gif" /> <roundcube:label name="calendar.availunknown" /></span>
+    <span class="legend"><img class="availabilityicon free" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availfree" /></span>
+    <span class="legend"><img class="availabilityicon busy" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availbusy" /></span>
+    <span class="legend"><img class="availabilityicon tentative" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availtentative" /></span>
+    <span class="legend"><img class="availabilityicon out-of-office" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availoutofoffice" /></span>
+    <span class="legend"><img class="availabilityicon unknown" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availunknown" /></span>
   </div>
diff --git a/plugins/calendar/skins/larry/templates/freebusylegend.html b/plugins/calendar/skins/larry/templates/freebusylegend.html
index 51e5ddc..45f627a 100644
--- a/plugins/calendar/skins/larry/templates/freebusylegend.html
+++ b/plugins/calendar/skins/larry/templates/freebusylegend.html
@@ -1,7 +1,7 @@
 	<div id="edit-attendees-legend" class="availability">
-		<span class="legend"><img class="availabilityicon free" src="./program/blank.gif" /> <roundcube:label name="calendar.availfree" /></span>
-		<span class="legend"><img class="availabilityicon busy" src="./program/blank.gif" /> <roundcube:label name="calendar.availbusy" /></span>
-		<span class="legend"><img class="availabilityicon tentative" src="./program/blank.gif" /> <roundcube:label name="calendar.availtentative" /></span>
-		<span class="legend"><img class="availabilityicon out-of-office" src="./program/blank.gif" /> <roundcube:label name="calendar.availoutofoffice" /></span>
-		<span class="legend"><img class="availabilityicon unknown" src="./program/blank.gif" /> <roundcube:label name="calendar.availunknown" /></span>
+		<span class="legend"><img class="availabilityicon free" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availfree" /></span>
+		<span class="legend"><img class="availabilityicon busy" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availbusy" /></span>
+		<span class="legend"><img class="availabilityicon tentative" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availtentative" /></span>
+		<span class="legend"><img class="availabilityicon out-of-office" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availoutofoffice" /></span>
+		<span class="legend"><img class="availabilityicon unknown" src="./program/resources/blank.gif" /> <roundcube:label name="calendar.availunknown" /></span>
 	</div>





More information about the commits mailing list