5 commits - plugins/calendar plugins/libcalendaring plugins/libkolab

Thomas Brüderli bruederli at kolabsys.com
Thu Feb 12 12:09:07 CET 2015


 plugins/calendar/calendar.php                   |    3 -
 plugins/calendar/calendar_ui.js                 |   14 ++++-
 plugins/calendar/drivers/kolab/kolab_driver.php |   61 +++++++++++++++++++++++-
 plugins/libcalendaring/libcalendaring.js        |    1 
 plugins/libkolab/config.inc.php.dist            |    8 +++
 plugins/libkolab/lib/kolab_format_event.php     |    5 +
 plugins/libkolab/lib/kolab_format_task.php      |    2 
 plugins/libkolab/lib/kolab_format_xcal.php      |    5 -
 plugins/libkolab/lib/kolab_storage.php          |    9 +++
 9 files changed, 98 insertions(+), 10 deletions(-)

New commits:
commit 747f2d5a2625543b0d0f0600ef17439ef71c092e
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Thu Feb 12 12:08:56 2015 +0100

    Avoid JS errors on organizer check

diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index 57a5ce5..c1e3d55 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -784,7 +784,7 @@ function rcube_calendar_ui(settings)
         // select the correct organizer identity
         var identity_id = 0;
         $.each(settings.identities, function(i,v){
-          if (organizer && v == organizer.email) {
+          if (organizer && typeof organizer == 'object' && v == organizer.email) {
             identity_id = i;
             return false;
           }


commit bef20a0e8d447323843bf8184187c9e1e0ff78f5
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Thu Feb 12 12:08:17 2015 +0100

    Reset attendee partstat when event is rescheduled by the organizer (#4360)

diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index a4d3f48..51381cb 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -1836,6 +1836,7 @@ class calendar extends rcube_plugin
     // convert dates into DateTime objects in user's current timezone
     $event['start'] = new DateTime($event['start'], $this->timezone);
     $event['end'] = new DateTime($event['end'], $this->timezone);
+    $event['allday'] = (bool)$event['allday'];
 
     // start/end is all we need for 'move' action (#1480)
     if ($action == 'move') {
@@ -2211,7 +2212,7 @@ class calendar extends rcube_plugin
   public static function event_diff($a, $b)
   {
     $diff = array();
-    $ignore = array('changed' => 1, 'attachments' => 1);
+    $ignore = array('changed' => 1, 'attachments' => 1, 'recurrence' => 1, '_notify' => 1, '_owner' => 1);
     foreach (array_unique(array_merge(array_keys($a), array_keys($b))) as $key) {
       if (!$ignore[$key] && $a[$key] != $b[$key])
         $diff[] = $key;
diff --git a/plugins/calendar/drivers/kolab/kolab_driver.php b/plugins/calendar/drivers/kolab/kolab_driver.php
index 0d5b9ab..98318f2 100644
--- a/plugins/calendar/drivers/kolab/kolab_driver.php
+++ b/plugins/calendar/drivers/kolab/kolab_driver.php
@@ -883,6 +883,9 @@ class kolab_driver extends calendar_driver
       $savemode = $event['_savemode'];
     }
 
+    // check if update affects scheduling and update attendee status accordingly
+    $reschedule = $this->check_scheduling($event, $old, true);
+
     // keep saved exceptions (not submitted by the client)
     if ($old['recurrence']['EXDATE'] && !isset($event['recurrence']['EXDATE']))
       $event['recurrence']['EXDATE'] = $old['recurrence']['EXDATE'];
@@ -914,7 +917,10 @@ class kolab_driver extends calendar_driver
         $event['recurrence'] = array();
         $event['thisandfuture'] = $savemode == 'future';
 
-        // TODO: increment sequence if scheduling is affected
+        // increment sequence of this instance if scheduling is affected
+        if ($reschedule) {
+          $event['sequence'] = $old['sequence'] + 1;
+        }
 
         // remove some internal properties which should not be saved
         unset($event['id'], $event['_savemode'], $event['_fromcalendar'], $event['_identity'], $event['_notify']);
@@ -991,7 +997,8 @@ class kolab_driver extends calendar_driver
         }
 
         // adjust recurrence-id when start changed and therefore the entire recurrence chain changes
-        if (($old_start_date != $new_start_date || $old_start_time != $new_start_time) && is_array($event['recurrence']['EXCEPTIONS']) && !$with_exceptions) {
+        if (($old_start_date != $new_start_date || $old_start_time != $new_start_time) &&
+              is_array($event['recurrence']) && is_array($event['recurrence']['EXCEPTIONS']) && !$with_exceptions) {
           $recurrence_id_format = $event['allday'] ? 'Ymd' : 'Ymd\THis';
           foreach ($event['recurrence']['EXCEPTIONS'] as $i => $exception) {
             $recurrence_id = is_a($exception['recurrence_date'], 'DateTime') ? $exception['recurrence_date'] :
@@ -1018,6 +1025,56 @@ class kolab_driver extends calendar_driver
   }
 
   /**
+   * Determine whether the current change affects scheduling and reset attendee status accordingly
+   */
+  public function check_scheduling(&$event, $old, $update = true)
+  {
+    $reschedule = false;
+
+    // skip this check when importing iCal/iTip events
+    if (isset($event['sequence']) || !empty($event['_method'])) {
+      return $reschedule;
+    }
+
+    // iterate through the list of properties considered 'significant' for scheduling
+    foreach (kolab_format_event::$scheduling_properties as $prop) {
+      $a = $old[$prop];
+      $b = $event[$prop];
+      if ($event['allday'] && ($prop == 'start' || $prop == 'end') && $a instanceof DateTime && $b instanceof DateTime) {
+        $a = $a->format('Y-m-d');
+        $b = $b->format('Y-m-d');
+      }
+      if ($a != $b) {
+        $reschedule = true;
+        break;
+      }
+    }
+
+    // reset all attendee status to needs-action (#4360)
+    if ($update && $reschedule && is_array($event['attendees'])) {
+      $is_organizer = false;
+      $emails = $this->cal->get_user_emails();
+      $attendees = $event['attendees'];
+      foreach ($attendees as $i => $attendee) {
+        if ($attendee['role'] == 'ORGANIZER' && $attendee['email'] && in_array(strtolower($attendee['email']), $emails)) {
+          $is_organizer = true;
+        }
+        else if ($attendee['role'] != 'ORGANIZER' && $attendee['role'] != 'NON-PARTICIPANT' && $attendee['status'] != 'DELEGATED') {
+          $attendees[$i]['status'] = 'NEEDS-ACTION';
+          $attendees[$i]['rsvp'] = true;
+        }
+      }
+
+      // update attendees only if I'm the organizer
+      if ($is_organizer || ($event['organizer'] && in_array(strtolower($event['organizer']['email']), $emails))) {
+        $event['attendees'] = $attendees;
+      }
+    }
+
+    return $reschedule;
+  }
+
+  /**
    * Get events from source.
    *
    * @param  integer Event's new start (unix timestamp)


commit 314501fdb20e2d8cd5a3ee0fbba66153f0287a05
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Thu Feb 12 11:54:51 2015 +0100

    Make the list of properties considered 'significant' for scheduling configurable

diff --git a/plugins/libkolab/config.inc.php.dist b/plugins/libkolab/config.inc.php.dist
index 5973d33..6e4b613 100644
--- a/plugins/libkolab/config.inc.php.dist
+++ b/plugins/libkolab/config.inc.php.dist
@@ -39,6 +39,14 @@ $config['kolab_http_request'] = array();
 // 1 - bypass only messages, but use index cache
 $config['kolab_messages_cache_bypass'] = 0;
 
+// These event properties contribute to a significant revision to the calendar component
+// and if changed will increment the sequence number relevant for scheduling according to RFC 5545
+$config['kolab_event_scheduling_properties'] = array('start', 'end', 'allday', 'location', 'status', 'cancelled');
+
+// These task properties contribute to a significant revision to the calendar component
+// and if changed will increment the sequence number relevant for scheduling according to RFC 5545
+$config['kolab_task_scheduling_properties'] = array('start', 'due', 'summary', 'status');
+
 // LDAP directory to find avilable users for folder sharing.
 // Either contains an array with LDAP addressbook configuration or refers to entry in $config['ldap_public'].
 // If not specified, the configuraton from 'kolab_auth_addressbook' will be used.
diff --git a/plugins/libkolab/lib/kolab_format_event.php b/plugins/libkolab/lib/kolab_format_event.php
index 03b5dde..075c517 100644
--- a/plugins/libkolab/lib/kolab_format_event.php
+++ b/plugins/libkolab/lib/kolab_format_event.php
@@ -26,7 +26,7 @@ class kolab_format_event extends kolab_format_xcal
 {
     public $CTYPEv2 = 'application/x-vnd.kolab.event';
 
-    public $scheduling_properties = array('start', 'end', 'allday', 'location', 'status', 'cancelled');
+    public static $scheduling_properties = array('start', 'end', 'allday', 'location', 'status', 'cancelled');
 
     protected $objclass = 'Event';
     protected $read_func = 'readEvent';
@@ -250,6 +250,9 @@ class kolab_format_event extends kolab_format_xcal
             }
         }
 
+        // preserve this property for date serialization
+        $exception['allday'] = $master['allday'];
+
         return $exception;
     }
 
diff --git a/plugins/libkolab/lib/kolab_format_task.php b/plugins/libkolab/lib/kolab_format_task.php
index 52744d4..ee0ca6a 100644
--- a/plugins/libkolab/lib/kolab_format_task.php
+++ b/plugins/libkolab/lib/kolab_format_task.php
@@ -26,7 +26,7 @@ class kolab_format_task extends kolab_format_xcal
 {
     public $CTYPEv2 = 'application/x-vnd.kolab.task';
 
-    public $scheduling_properties = array('start', 'due', 'summary', 'status');
+    public static $scheduling_properties = array('start', 'due', 'summary', 'status');
 
     protected $objclass = 'Todo';
     protected $read_func = 'readTodo';
diff --git a/plugins/libkolab/lib/kolab_format_xcal.php b/plugins/libkolab/lib/kolab_format_xcal.php
index 33ada93..d0f89b6 100644
--- a/plugins/libkolab/lib/kolab_format_xcal.php
+++ b/plugins/libkolab/lib/kolab_format_xcal.php
@@ -30,7 +30,7 @@ abstract class kolab_format_xcal extends kolab_format
 
     public static $fulltext_cols = array('title', 'description', 'location', 'attendees:name', 'attendees:email', 'categories');
 
-    public $scheduling_properties = array('start', 'end', 'location');
+    public static $scheduling_properties = array('start', 'end', 'location');
 
     protected $sensitivity_map = array(
         'public'       => kolabformat::ClassPublic,
@@ -321,8 +321,7 @@ abstract class kolab_format_xcal extends kolab_format
 
                 // increment sequence when updating properties relevant for scheduling.
                 // RFC 5545: "It is incremented [...] each time the Organizer makes a significant revision to the calendar component."
-                // TODO: make the list of properties considered 'significant' for scheduling configurable
-                foreach ($this->scheduling_properties as $prop) {
+                foreach (self::$scheduling_properties as $prop) {
                     $a = $old[$prop];
                     $b = $object[$prop];
                     if ($object['allday'] && ($prop == 'start' || $prop == 'end') && $a instanceof DateTime && $b instanceof DateTime) {
diff --git a/plugins/libkolab/lib/kolab_storage.php b/plugins/libkolab/lib/kolab_storage.php
index 47c1e4b..bc38adc 100644
--- a/plugins/libkolab/lib/kolab_storage.php
+++ b/plugins/libkolab/lib/kolab_storage.php
@@ -106,6 +106,15 @@ class kolab_storage
             ), true);
         }
 
+        // adjust some configurable settings
+        if ($event_scheduling_prop = $rcmail->config->get('kolab_event_scheduling_properties', null)) {
+            kolab_format_event::$scheduling_properties = (array)$event_scheduling_prop;
+        }
+        // adjust some configurable settings
+        if ($task_scheduling_prop = $rcmail->config->get('kolab_task_scheduling_properties', null)) {
+            kolab_format_task::$scheduling_properties = (array)$task_scheduling_prop;
+        }
+
         return self::$ready;
     }
 


commit 5990d292e91d1c979c19223855eda346ba3a248f
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Thu Feb 12 10:34:40 2015 +0100

    Suppress default link action

diff --git a/plugins/libcalendaring/libcalendaring.js b/plugins/libcalendaring/libcalendaring.js
index a959b9a..0a2949d 100644
--- a/plugins/libcalendaring/libcalendaring.js
+++ b/plugins/libcalendaring/libcalendaring.js
@@ -1139,6 +1139,7 @@ window.rcmail && rcmail.addEventListener('init', function(evt) {
 
   $('.rsvp-buttons').on('click', 'a.reply-comment-toggle', function(e){
     $(this).hide().parent().find('textarea').show().focus();
+    return false;
   });
 
   if (rcmail.env.action == 'get-attachment' && rcmail.gui_objects['attachmentframe']) {


commit 26ef4c64f8474a2fff869e4f5645cbca5de65aca
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Thu Feb 12 10:34:08 2015 +0100

    Shift end time according to the current duration when changing start time (for convenience)

diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index a8c01ac..57a5ce5 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -4032,7 +4032,7 @@ function rcube_calendar_ui(settings)
           open: autocomplete_open,
           change: event_times_changed,
           select: function(event, ui) {
-            $(this).val(ui.item[0]);
+            $(this).val(ui.item[0]).change();
             return false;
           }
         })
@@ -4047,6 +4047,16 @@ function rcube_calendar_ui(settings)
             };
         });
 
+      // adjust end time when changing start
+      $('#edit-starttime').change(function(e) {
+        var dstart = $('#edit-startdate'),
+          newstart = parse_datetime(this.value, dstart.val()),
+          newend = new Date(newstart.getTime() + dstart.data('duration') * 1000);
+        $('#edit-endtime').val($.fullCalendar.formatDate(newend, me.settings['time_format']));
+        $('#edit-enddate').val($.fullCalendar.formatDate(newend, me.settings['date_format']));
+        event_times_changed();
+      });
+
       // register events on alarms and recurrence fields
       me.init_alarms_edit('#edit-alarms');
       me.init_recurrence_edit('#eventedit');




More information about the commits mailing list