Branch 'dev/new-foldernav' - 2 commits - plugins/calendar plugins/libcalendaring plugins/libkolab

Thomas Brüderli bruederli at kolabsys.com
Mon May 19 12:19:01 CEST 2014


 plugins/calendar/drivers/kolab/kolab_user_calendar.php |  156 ++++++++++++++++-
 plugins/libcalendaring/libvcalendar.php                |    5 
 plugins/libkolab/lib/kolab_storage.php                 |    4 
 3 files changed, 159 insertions(+), 6 deletions(-)

New commits:
commit 073a6bb3737e1f4c70593c7ce0f4b4f98699fdc0
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Mon May 19 12:18:39 2014 +0200

    Aggregate shared but unsubscribed calendar folders and free/busy data into a 'user calendar'

diff --git a/plugins/calendar/drivers/kolab/kolab_user_calendar.php b/plugins/calendar/drivers/kolab/kolab_user_calendar.php
index 4cf3dab..7fd74ee 100644
--- a/plugins/calendar/drivers/kolab/kolab_user_calendar.php
+++ b/plugins/calendar/drivers/kolab/kolab_user_calendar.php
@@ -30,6 +30,7 @@ class kolab_user_calendar extends kolab_calendar
   public $subscriptions = false;
 
   protected $userdata = array();
+  protected $timeindex = array();
 
 
   /**
@@ -165,9 +166,158 @@ class kolab_user_calendar extends kolab_calendar
    */
   public function list_events($start, $end, $search = null, $virtual = 1, $query = array())
   {
-    // TODO: implement this
-    console('kolab_user_calendar::list_events()');
-    return array();
+    // convert to DateTime for comparisons
+    try {
+      $start_dt = new DateTime('@'.$start);
+    }
+    catch (Exception $e) {
+      $start_dt = new DateTime('@0');
+    }
+    try {
+      $end_dt = new DateTime('@'.$end);
+    }
+    catch (Exception $e) {
+      $end_dt = new DateTime('today +10 years');
+    }
+
+    $limit_changed = null;
+    if (!empty($query)) {
+      foreach ($query as $q) {
+        if ($q[0] == 'changed' && $q[1] == '>=') {
+          try { $limit_changed = new DateTime('@'.$q[2]); }
+          catch (Exception $e) { /* ignore */ }
+        }
+      }
+    }
+
+    // aggregate all calendar folders the user shares (but are not subscribed)
+    foreach (kolab_storage::list_user_folders($this->userdata, 'event', false) as $foldername) {
+      if (!kolab_storage::folder_is_subscribed($foldername, true)) {
+        $cal = new kolab_calendar($foldername, $this->cal);
+        foreach ($cal->list_events($start, $end, $search, 1) as $event) {
+          $this->events[$event['id']] = $event;
+          $this->timeindex[$this->time_key($event)] = $event['id'];
+        }
+      }
+    }
+
+    // get events from the user's free/busy feed
+    $this->fetch_freebusy($limit_changed);
+
+    $events = array();
+    foreach ($this->events as $id => $event) {
+      // list events in requested time window
+      if ($event['start'] <= $end_dt && $event['end'] >= $start_dt &&
+           (!$limit_changed || !$event['changed'] || $event['changed'] >= $limit_changed)) {
+        $events[] = $event;
+      }
+    }
+
+    return $events;
+  }
+
+  /**
+   * Helper method to fetch free/busy data for the user and turn it into calendar data
+   */
+  private function fetch_freebusy($limit_changed = null)
+  {
+    // ask kolab server first
+    try {
+      $request_config = array(
+        'store_body'       => true,
+        'follow_redirects' => true,
+      );
+      $request  = libkolab::http_request(kolab_storage::get_freebusy_url($this->userdata['mail']), 'GET', $request_config);
+      $response = $request->send();
+
+      // authentication required
+      if ($response->getStatus() == 401) {
+        $request->setAuth($this->rc->user->get_username(), $this->rc->decrypt($_SESSION['password']));
+        $response = $request->send();
+      }
+
+      if ($response->getStatus() == 200)
+        $fbdata = $response->getBody();
+
+      unset($request, $response);
+    }
+    catch (Exception $e) {
+      rcube::raise_error(array(
+        'code' => 900,
+        'type' => 'php',
+        'file' => __FILE__,
+        'line' => __LINE__,
+        'message' => "Error fetching free/busy information: " . $e->getMessage()),
+        true, false);
+
+      return false;
+    }
+
+    $statusmap = array(
+      'FREE' => 'free',
+      'BUSY' => 'busy',
+      'BUSY-TENTATIVE' => 'tentative',
+      'X-OUT-OF-OFFICE' => 'outofoffice',
+      'OOF' => 'outofoffice',
+    );
+    $titlemap = array(
+      'FREE' => $this->cal->gettext('availfree'),
+      'BUSY' => $this->cal->gettext('availbusy'),
+      'BUSY-TENTATIVE' => $this->cal->gettext('availtentative'),
+      'X-OUT-OF-OFFICE' => $this->cal->gettext('availoutofoffice'),
+    );
+
+    // console('_fetch_freebusy', kolab_storage::get_freebusy_url($this->userdata['mail']), $fbdata);
+
+    // parse free-busy information using Horde classes
+    $count = 0;
+    if ($fbdata) {
+      $ical = $this->cal->get_ical();
+      $ical->import($fbdata);
+      if ($fb = $ical->freebusy) {
+        $result = array();
+
+        // consider 'changed >= X' queries
+        if ($limit_changed && $fb['created'] && $fb['created'] < $limit_changed) {
+          return 0;
+        }
+
+        foreach ($fb['periods'] as $tuple) {
+          list($from, $to, $type) = $tuple;
+          $event = array(
+            'id'        => md5($this->id . $from->format('U') . '/' . $to->format('U')),
+            'calendar'  => $this->id,
+            'changed'   => $fb['created'] ?: new DateTime(),
+            'title'     => $titlemap[$type] ?: $type,
+            'start'     => $from,
+            'end'       => $to,
+            'free_busy' => $statusmap[$type] ?: 'busy',
+            'organizer' => array(
+              'email' => $this->userdata['mail'],
+              'name'  => $this->userdata['displayname'],
+            ),
+          );
+
+          // avoid duplicate entries
+          $key = $this->time_key($event);
+          if (!$this->timeindex[$key]) {
+            $this->events[$event['id']] = $event;
+            $this->timeindex[$key] = $event['id'];
+            $count++;
+          }
+        }
+      }
+    }
+
+    return $count;
+  }
+
+  /**
+   * Helper to build a key for the absolute time slot the given event convers
+   */
+  private function time_key($event)
+  {
+    return sprintf('%s/%s', $event['start']->format('U'), is_object($event['end']->format('U')) ?: '0');
   }
 
 
diff --git a/plugins/libcalendaring/libvcalendar.php b/plugins/libcalendaring/libvcalendar.php
index 1dda548..3b0f159 100644
--- a/plugins/libcalendaring/libvcalendar.php
+++ b/plugins/libcalendaring/libvcalendar.php
@@ -673,9 +673,12 @@ class libvcalendar implements Iterator
                 continue;
 
             switch ($prop->name) {
+            case 'CREATED':
+            case 'LAST-MODIFIED':
+            case 'DTSTAMP':
             case 'DTSTART':
             case 'DTEND':
-                $propmap = array('DTSTART' => 'start', 'DTEND' => 'end');
+                $propmap = array('DTSTART' => 'start', 'DTEND' => 'end', 'CREATED' => 'created', 'LAST-MODIFIED' => 'changed', 'DTSTAMP' => 'changed');
                 $this->freebusy[$propmap[$prop->name]] =  self::convert_datetime($prop);
                 break;
 


commit fd3f93d64eee2495783d434411247270e99a2e36
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Mon May 19 12:16:14 2014 +0200

    Use the dedicated config option

diff --git a/plugins/libkolab/lib/kolab_storage.php b/plugins/libkolab/lib/kolab_storage.php
index 74c0ed3..4266fb5 100644
--- a/plugins/libkolab/lib/kolab_storage.php
+++ b/plugins/libkolab/lib/kolab_storage.php
@@ -1340,7 +1340,7 @@ class kolab_storage
 
         // resolve to IMAP folder name
         $root = self::namespace_root('other');
-        $user_attrib = self::$config->get('kolab_auth_login', 'mail');
+        $user_attrib = self::$config->get('kolab_users_id_attrib', self::$config->get('kolab_auth_login', 'mail'));
 
         array_walk($results, function(&$user, $dn) use ($root, $user_attrib) {
             list($localpart, $domain) = explode('@', $user[$user_attrib]);
@@ -1368,7 +1368,7 @@ class kolab_storage
         $folders = array();
 
         // use localpart of user attribute as root for folder listing
-        $user_attrib = self::$config->get('kolab_auth_login', 'mail');
+        $user_attrib = self::$config->get('kolab_users_id_attrib', self::$config->get('kolab_auth_login', 'mail'));
         if (!empty($user[$user_attrib])) {
             list($mbox) = explode('@', $user[$user_attrib]);
 




More information about the commits mailing list