Branch 'roundcubemail-plugins-kolab-format2-horde5' - plugins/libkolab

Thomas Brüderli bruederli at kolabsys.com
Thu Nov 15 12:03:59 CET 2012


 plugins/libkolab/lib/kolab_format.php       |   62 ++++++++++++++++++++
 plugins/libkolab/lib/kolab_format_event.php |   83 +++++++---------------------
 2 files changed, 83 insertions(+), 62 deletions(-)

New commits:
commit 8dd320b63c4cea1269f8cdf871c126708d3046d7
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Thu Nov 15 12:03:43 2012 +0100

    Read and write event objects using the Horde 5 API

diff --git a/plugins/libkolab/lib/kolab_format.php b/plugins/libkolab/lib/kolab_format.php
index 76db15e..c57c463 100644
--- a/plugins/libkolab/lib/kolab_format.php
+++ b/plugins/libkolab/lib/kolab_format.php
@@ -86,6 +86,64 @@ abstract class kolab_format
     }
 
     /**
+     * Convert the given date/time value into a structure for Horde_Kolab_Format_Xml_Type_DateTime
+     *
+     * @param mixed         Date/Time value either as unix timestamp, date string or PHP DateTime object
+     * @param DateTimeZone  The timezone the date/time is in. Use global default if Null, local time if False
+     * @param boolean       True of the given date has no time component
+     * @return array        Hash array with date
+     */
+    public static function horde_datetime($datetime, $tz = null, $dateonly = false)
+    {
+        // use timezone information from datetime of global setting
+        if (!$tz && $tz !== false) {
+            if ($datetime instanceof DateTime)
+                $tz = $datetime->getTimezone();
+            if (!$tz)
+                $tz = self::$timezone;
+        }
+        $result = null;
+
+        // got a unix timestamp (in UTC)
+        if (is_numeric($datetime)) {
+            $datetime = new DateTime('@'.$datetime, new DateTimeZone('UTC'));
+            if ($tz) $datetime->setTimezone($tz);
+        }
+        else if (is_string($datetime) && strlen($datetime)) {
+            try { $datetime = new DateTime($datetime, $tz ?: null); }
+            catch (Exception $e) { }
+        }
+
+        if ($datetime instanceof DateTime) {
+            $result = array('date' => $datetime, 'date-only' => $dateonly || $datetime->_dateonly);
+        }
+
+        return $result;
+    }
+
+    /**
+     * Convert the given Horde_Kolab_Format_Xml_Type_DateTime structure into a simple PHP DateTime object
+     *
+     * @param arrry   Hash array with datetime properties
+     * @return object DateTime  PHP datetime instance
+     */
+    public static function php_datetime($data)
+    {
+        if (is_array($data)) {
+            $d = $data['date'];
+            if (is_a($d, 'DateTime')) {
+                if ($data['date-only'])
+                    $d->_dateonly = $data['date-only'];
+                return $d;
+            }
+        }
+        else if (is_object($data) && is_a($data, 'DateTime'))
+            return $data;
+
+        return null;
+    }
+
+    /**
      * Parse the X-Kolab-Type header from MIME messages and return the object type in short form
      *
      * @param string X-Kolab-Type header value
@@ -108,11 +166,11 @@ abstract class kolab_format
             return null;
 
         $alarm_unit = 'M';
-        if ($rec['alarm'] % 1440 == 0) {
+        if ($alarm_value % 1440 == 0) {
             $alarm_value /= 1440;
             $alarm_unit = 'D';
         }
-        else if ($rec['alarm'] % 60 == 0) {
+        else if ($alarm_value % 60 == 0) {
             $alarm_value /= 60;
             $alarm_unit = 'H';
         }
diff --git a/plugins/libkolab/lib/kolab_format_event.php b/plugins/libkolab/lib/kolab_format_event.php
index 7aedecc..88f2c80 100644
--- a/plugins/libkolab/lib/kolab_format_event.php
+++ b/plugins/libkolab/lib/kolab_format_event.php
@@ -79,40 +79,21 @@ class kolab_format_event extends kolab_format
         if ($object['uid'])
             $this->kolab_object['uid'] = $object['uid'];
 
-        $this->kolab_object['last-modification-date'] = time();
+        $this->kolab_object['last-modification-date'] = new DateTime();
 
         // map basic fields rcube => $kolab
         foreach ($this->kolab2_fieldmap as $kolab => $rcube) {
             $this->kolab_object[$kolab] = $object[$rcube];
         }
 
-        // all-day event
-        if (intval($object['allday'])) {
-            // shift times from user's timezone to server's timezone
-            // because Horde_Kolab_Format_Date::encodeDate() uses strftime() which operates in server tz
-            $server_tz = new DateTimeZone(date_default_timezone_get());
-            $start = clone $object['start'];
-            $end = clone $object['end'];
+        // make sure categories is an array
+        if (!is_array($this->kolab_object['categories']))
+            $this->kolab_object['categories'] = array_filter((array)$this->kolab_object['categories']);
 
-            $start->setTimezone($server_tz);
-            $end->setTimezone($server_tz);
-            $start->setTime(0,0,0);
-            $end->setTime(0,0,0);
-
-            // create timestamps at exactly 00:00. This is also needed for proper re-interpretation in _to_rcube_event() after updating an event
-            $this->kolab_object['start-date'] = mktime(0,0,0, $start->format('n'), $start->format('j'), $start->format('Y'));
-            $this->kolab_object['end-date']   = mktime(0,0,0, $end->format('n'),   $end->format('j'),   $end->format('Y')) + 86400;
-
-            // sanity check: end date is same or smaller than start
-            if (date('Y-m-d', $this->kolab_object['end-date']) <= date('Y-m-d', $this->kolab_object['start-date']))
-              $this->kolab_object['end-date'] = mktime(13,0,0, $start->format('n'), $start->format('j'), $start->format('Y')) + 86400;
-
-            $this->kolab_object['_is_all_day'] = 1;
-        }
-        else {
-            $this->kolab_object['start-date'] = $object['start']->format('U');
-            $this->kolab_object['end-date']   = $object['end']->format('U');
-        }
+        // convert dates into a structure Horde understands
+        $is_allday = intval($object['allday']);
+        $this->kolab_object['start-date'] = self::horde_datetime($object['start'], null, $is_allday);
+        $this->kolab_object['end-date']   = self::horde_datetime($object['end'], null, $is_allday);
 
         // handle alarms
         $this->kolab_object['alarm'] = self::to_kolab2_alarm($object['alarms']);
@@ -130,11 +111,11 @@ class kolab_format_event extends kolab_format
             // range Type
             if ($ra['UNTIL']) {
                 $this->kolab_object['recurrence']['range-type'] = 'date';
-                $this->kolab_object['recurrence']['range'] = $ra['UNTIL']->format('U');
+                $this->kolab_object['recurrence']['range'] = $ra['UNTIL'];
             }
             if ($ra['COUNT']) {
                 $this->kolab_object['recurrence']['range-type'] = 'number';
-                $this->kolab_object['recurrence']['range'] = $ra['COUNT'];
+                $this->kolab_object['recurrence']['range'] = intval($ra['COUNT']);
             }
 
             // WEEKLY
@@ -149,7 +130,7 @@ class kolab_format_event extends kolab_format
                 }
             }
 
-            // MONTHLY (temporary hack to follow Horde logic)
+            // MONTHLY (hack to follow Horde logic)
             if ($ra['FREQ'] == 'MONTHLY') {
                 if ($ra['BYDAY'] && preg_match('/(-?[1-4])([A-Z]+)/', $ra['BYDAY'], $m)) {
                     $this->kolab_object['recurrence']['daynumber'] = $m[1];
@@ -264,26 +245,6 @@ class kolab_format_event extends kolab_format
      */
     public function fromkolab2($rec)
     {
-        if (PEAR::isError($rec))
-            return;
-
-        $start_time = date('H:i:s', $rec['start-date']);
-        $allday = $rec['_is_all_day'] || ($start_time == '00:00:00' && $start_time == date('H:i:s', $rec['end-date']));
-
-        // in Roundcube all-day events go from 12:00 to 13:00
-        if ($allday) {
-            $now = new DateTime('now', self::$timezone);
-            $gmt_offset = $now->getOffset();
-
-            $rec['start-date'] += 12 * 3600;
-            $rec['end-date']   -= 11 * 3600;
-            $rec['end-date']   -= $gmt_offset - date('Z', $rec['end-date']);    // shift times from server's timezone to user's timezone
-            $rec['start-date'] -= $gmt_offset - date('Z', $rec['start-date']);  // because generated with mktime() in Horde_Kolab_Format_Date::decodeDate()
-            // sanity check
-            if ($rec['end-date'] <= $rec['start-date'])
-                $rec['end-date'] += 86400;
-        }
-
         // convert recurrence rules into internal pseudo-vcalendar format
         if ($recurrence = $rec['recurrence']) {
             $rrule = array(
@@ -291,10 +252,10 @@ class kolab_format_event extends kolab_format
                 'INTERVAL' => intval($recurrence['interval']),
             );
 
-            if ($recurrence['range-type'] == 'number')
+            if (is_object($recurrence['range']) && is_a($recurrence['range'], 'DateTime'))
+                $rrule['UNTIL'] = $recurrence['range'];
+            if (!empty($recurrence['range']) && is_numeric($recurrence['range']))
                 $rrule['COUNT'] = intval($recurrence['range']);
-            else if ($recurrence['range-type'] == 'date')
-                $rrule['UNTIL'] = date_create('@'.$recurrence['range']);
 
             if ($recurrence['day']) {
                 $byday = array();
@@ -316,7 +277,7 @@ class kolab_format_event extends kolab_format
 
             if ($recurrence['exclusion']) {
                 foreach ((array)$recurrence['exclusion'] as $excl)
-                    $rrule['EXDATE'][] = date_create($excl . date(' H:i:s', $rec['start-date']));  // use time of event start
+                    $rrule['EXDATE'][] = is_a($excl, 'DateTime') ? $excl : date_create($excl . date(' H:i:s', $rec['start-date']));  // use time of event start
             }
         }
 
@@ -344,12 +305,12 @@ class kolab_format_event extends kolab_format
 
         $this->data = array(
             'uid' => $rec['uid'],
+            'changed' => self::php_datetime($rec['last-modification-date']),
             'title' => $rec['summary'],
             'location' => $rec['location'],
             'description' => $rec['body'],
-            'start' => new DateTime('@'.$rec['start-date']),
-            'end'   => new DateTime('@'.$rec['end-date']),
-            'allday' => $allday,
+            'start' => self::php_datetime($rec['start-date']),
+            'end'   => self::php_datetime($rec['end-date']),
             'recurrence' => $rrule,
             'alarms' => self::from_kolab2_alarm($rec['alarm']),
             'categories' => $rec['categories'],
@@ -360,8 +321,10 @@ class kolab_format_event extends kolab_format
             'changed' => $rec['last-modification-date'],
         );
 
-        // assign current timezone to event start/end which are in UTC
-        $this->data['start']->setTimezone(self::$timezone);
-        $this->data['end']->setTimezone(self::$timezone);
+        $this->data['allday'] = $this->data['start']->_dateonly;
+
+        // assign current timezone to event start/end which are most likely in UTC
+        // $this->data['start']->setTimezone(self::$timezone);
+        // $this->data['end']->setTimezone(self::$timezone);
     }
 }





More information about the commits mailing list