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

Thomas Brüderli bruederli at kolabsys.com
Thu May 15 15:55:43 CEST 2014


 plugins/calendar/calendar.php                          |    2 -
 plugins/calendar/calendar_ui.js                        |   18 ++++++++--
 plugins/calendar/drivers/kolab/kolab_calendar.php      |   14 -------
 plugins/calendar/drivers/kolab/kolab_driver.php        |   15 ++++++--
 plugins/calendar/drivers/kolab/kolab_user_calendar.php |    1 
 plugins/calendar/lib/calendar_ui.php                   |    9 +++--
 plugins/calendar/localization/en_US.inc                |    1 
 plugins/calendar/skins/larry/calendar.css              |   25 +++++++++++++-
 plugins/calendar/skins/larry/images/calendars.png      |binary
 plugins/libkolab/config.inc.php.dist                   |   17 +++++++++
 plugins/libkolab/js/folderlist.js                      |   30 ++++++++++++++---
 plugins/libkolab/lib/kolab_storage.php                 |   21 ++++++-----
 plugins/libkolab/lib/kolab_storage_folder_api.php      |    2 -
 plugins/libkolab/lib/kolab_storage_folder_virtual.php  |    3 -
 14 files changed, 118 insertions(+), 40 deletions(-)

New commits:
commit 857078428b952de8aa8537ec1e2238198ab50f12
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Thu May 15 15:53:35 2014 +0200

    Toggle IMAP subscriptions directly from the calendars/folders list (#3042)

diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index fc0069d..f910b2b 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -725,7 +725,7 @@ class calendar extends rcube_plugin
           $this->rc->output->command('plugin.destroy_source', array('id' => $cal['id']));
         break;
       case "subscribe":
-        if (!$this->driver->subscribe_calendar($cal, intval(get_input_value('perm', RCUBE_INPUT_GPC))))
+        if (!$this->driver->subscribe_calendar($cal))
           $this->rc->output->show_message($this->gettext('errorsaving'), 'error');
         return;
       case "search":
diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index 38a32a8..68ae94f 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -2697,9 +2697,14 @@ function rcube_calendar_ui(settings)
         me.calendars[id].color = color;
       }
 
-      if (fc && cal.active) {
-        fc.fullCalendar('addEventSource', me.calendars[id]);
-        rcmail.http_post('calendar', { action:'subscribe', c:{ id:id, active:cal.active?1:0 } });
+      if (fc && (cal.active || cal.subscribed)) {
+        if (cal.active)
+          fc.fullCalendar('addEventSource', me.calendars[id]);
+
+        var submit = { id: id, active: cal.active ? 1 : 0 };
+        if (cal.subscribed !== undefined)
+            submit.permanent = cal.subscribed ? 1 : 0;
+        rcmail.http_post('calendar', { action:'subscribe', c:submit });
       }
 
       // insert to #calendar-select options if writeable
@@ -2761,6 +2766,13 @@ function rcube_calendar_ui(settings)
         }
       }
     });
+    calendars_list.addEventListener('subscribe', function(p) {
+      var cal;
+      if ((cal = me.calendars[p.id])) {
+        cal.subscribed = p.subscribed || false;
+        rcmail.http_post('calendar', { action:'subscribe', c:{ id:p.id, active:cal.active?1:0, permanent:cal.subscribed?1:0 } });
+      }
+    });
 
     // init (delegate) event handler on calendar list checkboxes
     $(rcmail.gui_objects.calendarslist).on('click', 'input[type=checkbox]', function(e){
diff --git a/plugins/calendar/drivers/kolab/kolab_calendar.php b/plugins/calendar/drivers/kolab/kolab_calendar.php
index c4b7dbb..3f74f0f 100644
--- a/plugins/calendar/drivers/kolab/kolab_calendar.php
+++ b/plugins/calendar/drivers/kolab/kolab_calendar.php
@@ -30,6 +30,7 @@ class kolab_calendar extends kolab_storage_folder_api
   public $readonly = true;
   public $attachments = true;
   public $alarms = false;
+  public $subscriptions = true;
   public $categories = array();
   public $storage;
 
@@ -103,19 +104,6 @@ class kolab_calendar extends kolab_storage_folder_api
 
 
   /**
-   * Getter for a nice and human readable name for this calendar
-   * See http://wiki.kolab.org/UI-Concepts/Folder-Listing for reference
-   *
-   * @return string Name of this calendar
-   */
-  public function get_name()
-  {
-    $folder = kolab_storage::object_name($this->name, $this->namespace);
-    return $folder;
-  }
-
-
-  /**
    * Getter for the IMAP folder name
    *
    * @return string Name of the IMAP folder
diff --git a/plugins/calendar/drivers/kolab/kolab_driver.php b/plugins/calendar/drivers/kolab/kolab_driver.php
index d1bb655..ff8372b 100644
--- a/plugins/calendar/drivers/kolab/kolab_driver.php
+++ b/plugins/calendar/drivers/kolab/kolab_driver.php
@@ -180,6 +180,10 @@ class kolab_driver extends calendar_driver
           'caldavurl' => $cal->get_caldav_url(),
         );
       }
+
+      if ($cal->subscriptions) {
+        $calendars[$cal->id]['subscribed'] = (bool)$cal->is_subscribed();
+      }
     }
 
     // append the virtual birthdays calendar
@@ -258,7 +262,6 @@ class kolab_driver extends calendar_driver
     // create calendar object if necesary
     if (!$this->calendars[$id] && $id !== self::BIRTHDAY_CALENDAR_ID) {
       $calendar = kolab_calendar::factory($id, $this->cal);
-      console($id, $calendar->id, $calendar->ready);
       if ($calendar->ready)
         $this->calendars[$calendar->id] = $calendar;
     }
@@ -342,11 +345,15 @@ class kolab_driver extends calendar_driver
    *
    * @see calendar_driver::subscribe_calendar()
    */
-  public function subscribe_calendar($prop, $permanent = false)
+  public function subscribe_calendar($prop)
   {
     if ($prop['id'] && ($cal = $this->get_calendar($prop['id']))) {
-      if ($permanent) $cal->storage->subscribe($prop['active']);
-      return $cal->storage->activate($prop['active']);
+      $ret = false;
+      if (isset($prop['permanent']))
+        $ret |= $cal->storage->subscribe($prop['permanent']);
+      if (isset($prop['active']))
+        $ret |= $cal->storage->activate($prop['active']);
+      return $ret;
     }
     else {
       // save state in local prefs
diff --git a/plugins/calendar/drivers/kolab/kolab_user_calendar.php b/plugins/calendar/drivers/kolab/kolab_user_calendar.php
index 3add82a..a41e065 100644
--- a/plugins/calendar/drivers/kolab/kolab_user_calendar.php
+++ b/plugins/calendar/drivers/kolab/kolab_user_calendar.php
@@ -27,6 +27,7 @@ class kolab_user_calendar extends kolab_calendar
   public $ready = false;
   public $readonly = true;
   public $attachments = false;
+  public $subscriptions = false;
 
   protected $userdata = array();
 
diff --git a/plugins/calendar/lib/calendar_ui.php b/plugins/calendar/lib/calendar_ui.php
index 4584f19..4d41194 100644
--- a/plugins/calendar/lib/calendar_ui.php
+++ b/plugins/calendar/lib/calendar_ui.php
@@ -296,6 +296,8 @@ class calendar_ui
       $class = 'folder virtual';
     else if ($prop['readonly'])
       $class .= ' readonly';
+    if ($prop['subscribed'])
+      $class .= ' subscribed';
     if ($prop['class_name'])
       $class .= ' '.$prop['class_name'];
 
@@ -303,8 +305,11 @@ class calendar_ui
     if (!$attrib['activeonly'] || $prop['active']) {
       $content = html::div($class,
         html::span(array('class' => 'calname', 'title' => $title), $prop['editname'] ? Q($prop['editname']) : $prop['listname']) .
-        ($prop['virtual'] ? '' : html::tag('input', array('type' => 'checkbox', 'name' => '_cal[]', 'value' => $id, 'checked' => $prop['active']), '') .
-        html::span(array('class' => 'handle', 'style' => "background-color: #" . ($prop['color'] ?: 'f00')), ' '))
+        ($prop['virtual'] ? '' :
+          html::tag('input', array('type' => 'checkbox', 'name' => '_cal[]', 'value' => $id, 'checked' => $prop['active']), '') .
+          (isset($prop['subscribed']) ? html::a(array('href' => '#', 'class' => 'subscribed', 'title' => $this->cal->gettext('calendarsubscribe')), $this->cal->gettext('subscribed')) : '') .
+          html::span(array('class' => 'handle', 'style' => "background-color: #" . ($prop['color'] ?: 'f00')), ' ')
+        )
       );
     }
 
diff --git a/plugins/calendar/localization/en_US.inc b/plugins/calendar/localization/en_US.inc
index 92b4fb5..67675bf 100644
--- a/plugins/calendar/localization/en_US.inc
+++ b/plugins/calendar/localization/en_US.inc
@@ -87,6 +87,7 @@ $labels['showurl'] = 'Show calendar URL';
 $labels['showurldescription'] = 'Use the following address to access (read only) your calendar from other applications. You can copy and paste this into any calendar software that supports the iCal format.';
 $labels['caldavurldescription'] = 'Copy this address to a <a href="http://en.wikipedia.org/wiki/CalDAV" target="_blank">CalDAV</a> client application (e.g. Evolution or Mozilla Thunderbird) to fully synchronize this specific calendar with your computer or mobile device.';
 $labels['calsearchresults'] = 'Available Calendars';
+$labels['calendarsubscribe'] = 'Listed permanently';
 
 // agenda view
 $labels['listrange'] = 'Range to display:';
diff --git a/plugins/calendar/skins/larry/calendar.css b/plugins/calendar/skins/larry/calendar.css
index 71dd106..cca70e6 100644
--- a/plugins/calendar/skins/larry/calendar.css
+++ b/plugins/calendar/skins/larry/calendar.css
@@ -190,7 +190,7 @@ pre {
 	position: absolute;
 	top: 7px;
 	left: 38px;
-	right: 22px;
+	right: 40px;
 	cursor: default;
 	background: url(images/calendars.png) right 20px no-repeat;
 	overflow: hidden;
@@ -207,6 +207,7 @@ pre {
 
 #calendars .treelist.flat li span.calname {
 	left: 24px;
+	right: 22px;
 }
 
 #calendars .treelist li span.handle {
@@ -225,6 +226,28 @@ pre {
 	box-shadow: inset 0px 0 1px 1px rgba(0, 0, 0, 0.3);
 }
 
+#calendars .treelist li a.subscribed {
+	display: inline-block;
+	position: absolute;
+	top: 7px;
+	right: 24px;
+	height: 16px;
+	width: 16px;
+	padding: 0;
+	background: url(images/calendars.png) -100px 0 no-repeat;
+	overflow: hidden;
+	text-indent: -5000px;
+	cursor: pointer;
+}
+
+#calendars .treelist div:hover > a.subscribed {
+	background-position: 1px -110px;
+}
+
+#calendars .treelist div.subscribed a.subscribed {
+	background-position: -15px -110px;
+}
+
 #calendars .treelist li input {
 	position: absolute;
 	top: 5px;
diff --git a/plugins/calendar/skins/larry/images/calendars.png b/plugins/calendar/skins/larry/images/calendars.png
index c2de67d..1f97abc 100644
Binary files a/plugins/calendar/skins/larry/images/calendars.png and b/plugins/calendar/skins/larry/images/calendars.png differ
diff --git a/plugins/libkolab/js/folderlist.js b/plugins/libkolab/js/folderlist.js
index 3c35846..587fe56 100644
--- a/plugins/libkolab/js/folderlist.js
+++ b/plugins/libkolab/js/folderlist.js
@@ -57,20 +57,29 @@ function kolab_folderlist(node, p)
               // register click handler on search result's checkboxes to select the given item for listing
               search_results_widget.container
                   .appendTo(search_results_container)
-                  .on('click', 'input[type=checkbox]', function(e) {
-                      if (!this.checked)
-                          return;
-
+                  .on('click', 'input[type=checkbox], a.subscribed', function(e) {
                       var li = $(this).closest('li'),
                           id = li.attr('id').replace(new RegExp('^'+p.id_prefix), '')
                           node = search_results_widget.get_node(id),
                           has_children = node.children && node.children.length;
 
+                      // activate + subscribe
+                      if ($(e.target).hasClass('subscribed')) {
+                          search_results[id].subscribed = true;
+                          li.children().first()
+                              .toggleClass('subscribed')
+                              .find('input[type=checkbox]').get(0).checked = true;
+                      }
+                      else if (!this.checked) {
+                          return;
+                      }
+
                       // copy item to the main list
                       add_result2list(id, li, true);
 
                       if (has_children) {
                           li.find('input[type=checkbox]').first().prop('disabled', true).get(0).checked = true;
+                          li.find('a.subscribed').first().hide();
                       }
                       else {
                           li.remove();
@@ -93,6 +102,7 @@ function kolab_folderlist(node, p)
               // disable checkbox if item already exists in main list
               if (me.get_node(prop.id) && !me.get_node(prop.id).virtual) {
                   item.find('input[type=checkbox]').first().prop('disabled', true).get(0).checked = true;
+                  item.find('a.subscribed').hide();
               }
           }
 
@@ -168,6 +178,18 @@ function kolab_folderlist(node, p)
         }
     });
 
+    this.container.on('click', 'a.subscribed', function(e){
+        var li = $(this).closest('li'),
+            id = li.attr('id').replace(new RegExp('^'+p.id_prefix), ''),
+            div = li.children().first();
+
+        div.toggleClass('subscribed');
+        me.triggerEvent('subscribe', { id: id, subscribed: div.hasClass('subscribed'), item: li });
+
+        e.stopPropagation();
+        return false;
+    })
+
 }
 
 // link prototype from base class


commit 8d09b78eb1ee58ea19180804ff729000a82f6340
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Thu May 15 14:18:23 2014 +0200

    Provide sample config for new LDAP user search

diff --git a/plugins/libkolab/config.inc.php.dist b/plugins/libkolab/config.inc.php.dist
index e1ad0ff..3a3c287 100644
--- a/plugins/libkolab/config.inc.php.dist
+++ b/plugins/libkolab/config.inc.php.dist
@@ -31,3 +31,20 @@ $rcmail_config['kolab_http_request'] = array();
 // 1 - bypass only messages, but use index cache
 $rcmail_config['kolab_messages_cache_bypass'] = 0;
 
+// 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.
+$rcmail_config['kolab_users_directory'] = null;
+
+// Filter to be used for resolving user folders in LDAP.
+// Defaults to the 'kolab_auth_filter' configuration option.
+$rcmail_config['kolab_users_filter'] = '(&(objectclass=kolabInetOrgPerson)(|(uid=%u)(mail=%fu)))';
+
+// Which property of the LDAP user record to use for user folder mapping in IMAP.
+// Defaults to the 'kolab_auth_login' configuration option.
+$rcmail_config['kolab_users_id_attrib'] = null;
+
+// Use these attributes when searching users in LDAP
+$rcmail_config['kolab_users_search_attrib'] = array('cn','mail','alias');
+
+
diff --git a/plugins/libkolab/lib/kolab_storage.php b/plugins/libkolab/lib/kolab_storage.php
index f10b7fe..1cbdd76 100644
--- a/plugins/libkolab/lib/kolab_storage.php
+++ b/plugins/libkolab/lib/kolab_storage.php
@@ -111,11 +111,12 @@ class kolab_storage
             return self::$ldap;
         }
 
-        $rcmail = rcube::get_instance();
-        $config = $rcmail->config->get('kolab_users_directory', $rcmail->config->get('kolab_auth_addressbook'));
+        self::setup();
+
+        $config = self::$config->get('kolab_users_directory', self::$config->get('kolab_auth_addressbook'));
 
         if (!is_array($config)) {
-            $ldap_config = (array)$rcmail->config->get('ldap_public');
+            $ldap_config = (array)self::$config->get('ldap_public');
             $config = $ldap_config[$config];
         }
 
@@ -124,8 +125,8 @@ class kolab_storage
         }
 
         // overwrite filter option
-        if ($filter = $rcmail->config->get('kolab_users_filter')) {
-            $rcmail->config->set('kolab_auth_filter', $filter);
+        if ($filter = self::$config->get('kolab_users_filter')) {
+            self::$config->set('kolab_auth_filter', $filter);
         }
 
         // re-use the LDAP wrapper class from kolab_auth plugin
@@ -1328,12 +1329,12 @@ class kolab_storage
             return array();
         }
 
-        // FIXME: make search attributes configurable
-        $results = self::$ldap->search(array('cn','mail','alias'), $query, $mode, $required, $limit);
+        // search users using the configured attributes
+        $results = self::$ldap->search(self::$config->get('kolab_users_search_attrib', array('cn','mail','alias')), $query, $mode, $required, $limit);
 
         // resolve to IMAP folder name
         $root = self::namespace_root('other');
-        $user_attrib = rcube::get_instance()->config->get('kolab_auth_login', 'mail');
+        $user_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]);
@@ -1356,10 +1357,12 @@ class kolab_storage
      */
     public static function list_user_folders($user, $type, $subscribed = null, &$folderdata = array())
     {
+        self::setup();
+
         $folders = array();
 
         // use localpart of user attribute as root for folder listing
-        $user_attrib = rcube::get_instance()->config->get('kolab_auth_login', 'mail');
+        $user_attrib = self::$config->get('kolab_auth_login', 'mail');
         if (!empty($user[$user_attrib])) {
             list($mbox) = explode('@', $user[$user_attrib]);
 
diff --git a/plugins/libkolab/lib/kolab_storage_folder_api.php b/plugins/libkolab/lib/kolab_storage_folder_api.php
index a2d40b1..5af8c34 100644
--- a/plugins/libkolab/lib/kolab_storage_folder_api.php
+++ b/plugins/libkolab/lib/kolab_storage_folder_api.php
@@ -134,7 +134,7 @@ abstract class kolab_storage_folder_api
      */
     public function get_name()
     {
-        return kolab_storage::object_name($this->name, $this->namespace);
+        return kolab_storage::object_name($this->name, $this->get_namespace());
     }
 
 
diff --git a/plugins/libkolab/lib/kolab_storage_folder_virtual.php b/plugins/libkolab/lib/kolab_storage_folder_virtual.php
index 8b85ad5..e419ced 100644
--- a/plugins/libkolab/lib/kolab_storage_folder_virtual.php
+++ b/plugins/libkolab/lib/kolab_storage_folder_virtual.php
@@ -43,8 +43,7 @@ class kolab_storage_folder_virtual extends kolab_storage_folder_api
      */
     public function get_name()
     {
-        // this is already kolab_storage::object_name() result
-        return $this->displayname;
+        return $this->displayname ?: parent::get_name();
     }
 
     /**




More information about the commits mailing list