3 commits - plugins/calendar

Thomas Brüderli bruederli at kolabsys.com
Tue Jan 28 11:55:17 CET 2014


 plugins/calendar/calendar.php                         |  105 +++++++++++++++++-
 plugins/calendar/drivers/calendar_driver.php          |   54 ++++++---
 plugins/calendar/drivers/database/database_driver.php |   10 -
 plugins/calendar/drivers/kolab/kolab_driver.php       |    7 -
 plugins/calendar/localization/en_US.inc               |    3 
 5 files changed, 156 insertions(+), 23 deletions(-)

New commits:
commit b79179b9c373d88a68cb1b48ad925062da0bbb09
Author: Thomas Bruederli <thomas at roundcube.net>
Date:   Tue Jan 28 11:55:06 2014 +0100

    Display alarms for birthday events

diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index 9880da5..b2e79ab 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -595,6 +595,24 @@ class calendar extends rcube_plugin
         'title'   => rcube::Q($this->gettext('birthdayscalendarsources')),
         'content' => join(html::br(), $sources),
       );
+
+      $field_id = 'rcmfd_birthdays_alarm';
+      $select_type = new html_select(array('name' => '_birthdays_alarm_type', 'id' => $field_id));
+      $select_type->add($this->gettext('none'), '');
+      foreach ($this->driver->alarm_types as $type) {
+        $select_type->add(rcube_label(strtolower("alarm{$type}option"), 'libcalendaring'), $type);
+      }
+
+      $input_value = new html_inputfield(array('name' => '_birthdays_alarm_value', 'id' => $field_id . 'value', 'size' => 3));
+      $select_offset = new html_select(array('name' => '_birthdays_alarm_offset', 'id' => $field_id . 'offset'));
+      foreach (array('-M','-H','-D') as $trigger)
+        $select_offset->add(rcube_label('trigger' . $trigger, 'libcalendaring'), $trigger);
+
+      $preset = libcalendaring::parse_alaram_value($this->rc->config->get('calendar_birthdays_alarm_offset', '-1D'));
+      $p['blocks']['birthdays']['options']['birthdays_alarmoffset'] = array(
+        'title' => html::label($field_id . 'value', rcube::Q($this->gettext('showalarms'))),
+        'content' => $select_type->show($this->rc->config->get('calendar_birthdays_alarm_type', '')) . ' ' . $input_value->show($preset[0]) . ' ' . $select_offset->show($preset[1]),
+      );
     }
 
     return $p;
@@ -616,6 +634,9 @@ class calendar extends rcube_plugin
       $alarm_offset = get_input_value('_alarm_offset', RCUBE_INPUT_POST);
       $default_alarm = $alarm_offset[0] . intval(get_input_value('_alarm_value', RCUBE_INPUT_POST)) . $alarm_offset[1];
 
+      $birthdays_alarm_offset = get_input_value('_birthdays_alarm_offset', RCUBE_INPUT_POST);
+      $birthdays_alarm_value = $birthdays_alarm_offset[0] . intval(get_input_value('_birthdays_alarm_value', RCUBE_INPUT_POST)) . $birthdays_alarm_offset[1];
+
       $p['prefs'] = array(
         'calendar_default_view' => get_input_value('_default_view', RCUBE_INPUT_POST),
         'calendar_timeslots'    => intval(get_input_value('_timeslots', RCUBE_INPUT_POST)),
@@ -631,6 +652,8 @@ class calendar extends rcube_plugin
         'calendar_time_format' => null,
         'calendar_contact_birthdays'    => get_input_value('_contact_birthdays', RCUBE_INPUT_POST) ? true : false,
         'calendar_birthday_adressbooks' => array_filter((array)get_input_value('_birthday_adressbooks', RCUBE_INPUT_POST)),
+        'calendar_birthdays_alarm_type'   => get_input_value('_birthdays_alarm_type', RCUBE_INPUT_POST),
+        'calendar_birthdays_alarm_offset' => $birthdays_alarm_value,
       );
 
       // categories
@@ -1012,13 +1035,34 @@ class calendar extends rcube_plugin
   public function pending_alarms($p)
   {
     $this->load_driver();
-    if ($alarms = $this->driver->pending_alarms($p['time'] ?: time())) {
+    $time = $p['time'] ?: time();
+    if ($alarms = $this->driver->pending_alarms($time)) {
       foreach ($alarms as $alarm) {
         $alarm['id'] = 'cal:' . $alarm['id'];  // prefix ID with cal:
         $p['alarms'][] = $alarm;
       }
     }
 
+    // get alarms for birthdays calendar
+    if ($this->rc->config->get('calendar_contact_birthdays') && $this->rc->config->get('calendar_birthdays_alarm_type') == 'DISPLAY') {
+      $cache = $this->rc->get_cache('calendar.birthdayalarms', 'db');
+
+      foreach ($this->driver->load_birthday_events($time, $time + 86400 * 60) as $e) {
+        $alarm = libcalendaring::get_next_alarm($e);
+
+        // overwrite alarm time with snooze value (or null if dismissed)
+        if ($dismissed = $cache->get($e['id']))
+          $alarm['time'] = $dismissed['notifyat'];
+
+        // add to list if alarm is set
+        if ($alarm && $alarm['time'] && $alarm['time'] <= $time) {
+          $e['id'] = 'cal:bday:' . $e['id'];
+          $e['notifyat'] = $alarm['time'];
+          $p['alarms'][] = $e;
+        }
+      }
+    }
+
     return $p;
   }
 
@@ -1029,8 +1073,12 @@ class calendar extends rcube_plugin
   {
       $this->load_driver();
       foreach ((array)$p['ids'] as $id) {
-          if (strpos($id, 'cal:') === 0)
+          if (strpos($id, 'cal:bday:') === 0) {
+              $p['success'] |= $this->driver->dismiss_birthday_alarm(substr($id, 9), $p['snooze']);
+          }
+          else if (strpos($id, 'cal:') === 0) {
               $p['success'] |= $this->driver->dismiss_alarm(substr($id, 4), $p['snooze']);
+          }
       }
 
       return $p;
diff --git a/plugins/calendar/drivers/calendar_driver.php b/plugins/calendar/drivers/calendar_driver.php
index 1f6b258..a7ad0e5 100644
--- a/plugins/calendar/drivers/calendar_driver.php
+++ b/plugins/calendar/drivers/calendar_driver.php
@@ -429,6 +429,10 @@ abstract class calendar_driver
     $cache  = $rcmail->get_cache('calendar.birthdays', 'db', 3600);
     $cache->expunge();
 
+    $alarm_type = $rcmail->config->get('calendar_birthdays_alarm_type', '');
+    $alarm_offset = $rcmail->config->get('calendar_birthdays_alarm_offset', '-1D');
+    $alarms = $alarm_type ? $alarm_offset . ':' . $alarm_type : null;
+
     // let the user select the address books to consider in prefs
     $selected_sources = $rcmail->config->get('calendar_birthday_adressbooks');
     $sources = $selected_sources ?: array_keys($rcmail->get_address_sources(false, true));
@@ -493,14 +497,14 @@ abstract class calendar_driver
           if ($bday <= $end && $bday >= $start) {
             $age = $year - $birthyear;
             $event = array(
-              'id'          => md5('bday_' . $contact['id']),
+              'id'          => md5('bday_' . $contact['id'] . $year),
               'calendar'    => self::BIRTHDAY_CALENDAR_ID,
               'title'       => $event_title,
               'description' => $rcmail->gettext(array('name' => 'birthdayage', 'vars' => array('age' => $age)), 'calendar'),
               // Add more contact information to description block?
               'allday'      => true,
               'start'       => $bday,
-              // TODO: add alarms (configurable?)
+              'alarms'      => $alarms,
             );
             $event['end'] = clone $bday;
             $event['end']->add(new DateInterval('PT1H'));
@@ -519,4 +523,23 @@ abstract class calendar_driver
     return $events;
   }
 
+  /**
+   * Store alarm dismissal for birtual birthay events
+   *
+   * @param  string  Event identifier
+   * @param  integer Suspend the alarm for this number of seconds
+   */
+  public function dismiss_birthday_alarm($event_id, $snooze = 0)
+  {
+    $rcmail = rcmail::get_instance();
+    $cache  = $rcmail->get_cache('calendar.birthdayalarms', 'db', 86400 * 30);
+    $cache->remove($event_id);
+
+    // compute new notification time or disable if not snoozed
+    $notifyat = $snooze > 0 ? time() + $snooze : null;
+    $cache->set($event_id, array('snooze' => $snooze, 'notifyat' => $notifyat));
+
+    return true;
+  }
+
 }
diff --git a/plugins/calendar/drivers/database/database_driver.php b/plugins/calendar/drivers/database/database_driver.php
index 18fed04..0c2d030 100644
--- a/plugins/calendar/drivers/database/database_driver.php
+++ b/plugins/calendar/drivers/database/database_driver.php
@@ -139,7 +139,7 @@ class database_driver extends calendar_driver
           'name'       => $this->cal->gettext('birthdays'),
           'listname'   => $this->cal->gettext('birthdays'),
           'color'      => $prefs['color'],
-          'showalarms' => $prefs['showalarms'],
+          'showalarms' => (bool)$this->rc->config->get('calendar_birthdays_alarm_type'),
           'active'     => !in_array($id, $hidden),
           'class_name' => 'birthdays',
           'readonly'   => true,
@@ -187,12 +187,12 @@ class database_driver extends calendar_driver
   {
     // birthday calendar properties are saved in user prefs
     if ($prop['id'] == self::BIRTHDAY_CALENDAR_ID) {
-      $prefs = $this->rc->config->get('birthday_calendar', array('color' => '87CEFA'));
+      $prefs['birthday_calendar'] = $this->rc->config->get('birthday_calendar', array('color' => '87CEFA'));
       if (isset($prop['color']))
-        $prefs['color'] = $prop['color'];
+        $prefs['birthday_calendar']['color'] = $prop['color'];
       if (isset($prop['showalarms']))
-        $prefs['showalarms'] = $prop['showalarms'] ? true : false;
-      $this->rc->user->save_prefs(array('birthday_calendar' => $prefs));
+        $prefs['calendar_birthdays_alarm_type'] = $prop['showalarms'] ? $this->alarm_types[0] : '';
+      $this->rc->user->save_prefs($prefs);
       return true;
     }
 
diff --git a/plugins/calendar/drivers/kolab/kolab_driver.php b/plugins/calendar/drivers/kolab/kolab_driver.php
index 87a5f02..dd85ffc 100644
--- a/plugins/calendar/drivers/kolab/kolab_driver.php
+++ b/plugins/calendar/drivers/kolab/kolab_driver.php
@@ -155,8 +155,8 @@ class kolab_driver extends calendar_driver
           'name'       => $this->cal->gettext('birthdays'),
           'listname'   => $this->cal->gettext('birthdays'),
           'color'      => $prefs[$id]['color'],
-          'showalarms' => $prefs[$id]['showalarms'],
           'active'     => $prefs[$id]['active'],
+          'showalarms' => (bool)$this->rc->config->get('calendar_birthdays_alarm_type'),
           'class_name' => 'birthdays',
           'readonly'   => true,
           'default'    => false,
@@ -276,7 +276,10 @@ class kolab_driver extends calendar_driver
 
     if (isset($prop['color']))
       $prefs['kolab_calendars'][$id]['color'] = $prop['color'];
-    if (isset($prop['showalarms']))
+
+    if (isset($prop['showalarms']) && $id == self::BIRTHDAY_CALENDAR_ID)
+      $prefs['calendar_birthdays_alarm_type'] = $prop['showalarms'] ? $this->alarm_types[0] : '';
+    else if (isset($prop['showalarms']))
       $prefs['kolab_calendars'][$id]['showalarms'] = $prop['showalarms'] ? true : false;
 
     if (!empty($prefs['kolab_calendars'][$id]))


commit 92a6e5c28dca3aaf44c0594bf6aaa190eeba69e8
Author: Thomas Bruederli <thomas at roundcube.net>
Date:   Tue Jan 28 09:58:54 2014 +0100

    Add settings block for birthdays calendar settings

diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index 920462c..9880da5 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -564,6 +564,39 @@ class calendar extends rcube_plugin
         $this->rc->output->add_script('$("input.colors").miniColors({ colorValues:rcmail.env.mscolors })', 'docready');
     }
 
+    $p['blocks']['birthdays']['name'] = $this->gettext('birthdayscalendar');
+
+    if (!isset($no_override['calendar_contact_birthdays'])) {
+      if (!$p['current']) {
+        $p['blocks']['birthdays']['content'] = true;
+        return $p;
+      }
+
+      $field_id = 'rcmfd_contact_birthdays';
+      $input    = new html_checkbox(array('name' => '_contact_birthdays', 'id' => $field_id, 'value' => 1, 'onclick' => '$("input.calendar_birthday_props").prop("disabled",!this.checked)'));
+
+      $p['blocks']['birthdays']['options']['contact_birthdays'] = array(
+        'title'   => html::label($field_id, $this->gettext('displaybirthdayscalendar')),
+        'content' => $input->show($this->rc->config->get('calendar_contact_birthdays')?1:0),
+      );
+
+      $sources = array();
+      $checkbox = new html_checkbox(array(
+        'name' => '_birthday_adressbooks[]',
+        'class' => 'calendar_birthday_props',
+        'disabled' => !$this->rc->config->get('calendar_contact_birthdays'),
+      ));
+      foreach ($this->rc->get_address_sources(false, true) as $source) {
+        $active = in_array($source['id'], (array)$this->rc->config->get('calendar_birthday_adressbooks', array())) ? $source['id'] : '';
+        $sources[] = html::label(null, $checkbox->show($active, array('value' => $source['id'])) . ' ' . rcube::Q($source['realname'] ?: $source['name']));
+      }
+
+      $p['blocks']['birthdays']['options']['birthday_adressbooks'] = array(
+        'title'   => rcube::Q($this->gettext('birthdayscalendarsources')),
+        'content' => join(html::br(), $sources),
+      );
+    }
+
     return $p;
   }
 
@@ -596,6 +629,8 @@ class calendar extends rcube_plugin
         'calendar_default_calendar'     => get_input_value('_default_calendar', RCUBE_INPUT_POST),
         'calendar_date_format' => null,  // clear previously saved values
         'calendar_time_format' => null,
+        'calendar_contact_birthdays'    => get_input_value('_contact_birthdays', RCUBE_INPUT_POST) ? true : false,
+        'calendar_birthday_adressbooks' => array_filter((array)get_input_value('_birthday_adressbooks', RCUBE_INPUT_POST)),
       );
 
       // categories
diff --git a/plugins/calendar/drivers/calendar_driver.php b/plugins/calendar/drivers/calendar_driver.php
index af8cb2f..1f6b258 100644
--- a/plugins/calendar/drivers/calendar_driver.php
+++ b/plugins/calendar/drivers/calendar_driver.php
@@ -429,19 +429,22 @@ abstract class calendar_driver
     $cache  = $rcmail->get_cache('calendar.birthdays', 'db', 3600);
     $cache->expunge();
 
-    // TODO: let the user select the address books to consider in prefs
-    foreach ($rcmail->get_address_sources(false, true) as $source) {
-      $abook = $rcmail->get_address_book($source['id']);
-      $abook->set_pagesize(10000);
-
-      // skip LDAP address books (really?)
-      if ($abook instanceof rcube_ldap) {
+    // let the user select the address books to consider in prefs
+    $selected_sources = $rcmail->config->get('calendar_birthday_adressbooks');
+    $sources = $selected_sources ?: array_keys($rcmail->get_address_sources(false, true));
+    foreach ($sources as $source) {
+      $abook = $rcmail->get_address_book($source);
+
+      // skip LDAP address books unless selected by the user
+      if (!$abook || ($abook instanceof rcube_ldap && empty($selected_sources))) {
         continue;
       }
 
+      $abook->set_pagesize(10000);
+
       // check for cached results
       $cache_records = array();
-      $cached = $cache->get($source['id']);
+      $cached = $cache->get($source);
 
       // iterate over (cached) contacts
       foreach (($cached ?: $abook->list_records()) as $contact) {
@@ -509,7 +512,7 @@ abstract class calendar_driver
 
       // store collected contacts in cache
       if (empty($cached)) {
-        $cache->write($source['id'], $cache_records);
+        $cache->write($source, $cache_records);
       }
     }
 
diff --git a/plugins/calendar/localization/en_US.inc b/plugins/calendar/localization/en_US.inc
index c582db9..e6cbceb 100644
--- a/plugins/calendar/localization/en_US.inc
+++ b/plugins/calendar/localization/en_US.inc
@@ -240,6 +240,9 @@ $labels['saveasnew'] = 'Save as new';
 
 // birthdays calendar
 $labels['birthdays'] = 'Birthdays';
+$labels['birthdayscalendar'] = 'Birthdays Calendar';
+$labels['displaybirthdayscalendar'] = 'Display birthdays calendar';
+$labels['birthdayscalendarsources'] = 'From these address books';
 $labels['birthdayeventtitle'] = '$name\'s Birthday';
 $labels['birthdayage'] = 'Age $age';
 


commit b9ed08ce789aa7943287e7aa3bcd3d01f6473c4b
Author: Thomas Bruederli <thomas at roundcube.net>
Date:   Mon Jan 27 19:50:17 2014 +0100

    Clear birthdays calendar cache when contact is updated

diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index a5caaa8..920462c 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -182,6 +182,12 @@ class calendar extends rcube_plugin
         $this->api->output->add_label('calendar.createfrommail');
       }
     }
+    else if ($args['task'] == 'addressbook') {
+      if ($this->rc->config->get('calendar_contact_birthdays')) {
+        $this->add_hook('contact_update', array($this, 'contact_update'));
+        $this->add_hook('contact_create', array($this, 'contact_update'));
+      }
+    }
 
     // add hooks to display alarms
     $this->add_hook('pending_alarms', array($this, 'pending_alarms'));
@@ -1005,6 +1011,18 @@ class calendar extends rcube_plugin
   }
 
   /**
+   * Hook triggered when a contact is saved
+   */
+  function contact_update($p)
+  {
+    // clear birthdays calendar cache
+    if (!empty($p['record']['birthday'])) {
+      $cache = $this->rc->get_cache('calendar.birthdays', 'db');
+      $cache->remove();
+    }
+  }
+
+  /**
    *
    */
   function import_events()
diff --git a/plugins/calendar/drivers/calendar_driver.php b/plugins/calendar/drivers/calendar_driver.php
index 0eedf7f..af8cb2f 100644
--- a/plugins/calendar/drivers/calendar_driver.php
+++ b/plugins/calendar/drivers/calendar_driver.php
@@ -444,8 +444,8 @@ abstract class calendar_driver
       $cached = $cache->get($source['id']);
 
       // iterate over (cached) contacts
-      foreach ((array)($cached ?: $abook->list_records()) as $contact) {
-        if (!empty($contact['birthday'])) {
+      foreach (($cached ?: $abook->list_records()) as $contact) {
+        if (is_array($contact) && !empty($contact['birthday'])) {
           try {
             if (is_array($contact['birthday']))
               $contact['birthday'] = reset($contact['birthday']);
@@ -455,7 +455,7 @@ abstract class calendar_driver
             $birthyear = $bday->format('Y');
           }
           catch (Exception $e) {
-            // console('BIRTHDAY PARSE ERROR: ' . $e);
+            console('BIRTHDAY PARSE ERROR: ' . $e);
             continue;
           }
 




More information about the commits mailing list