plugins/calendar plugins/libkolab plugins/tasklist

Aleksander Machniak machniak at kolabsys.com
Thu Nov 21 11:00:23 CET 2013


 plugins/calendar/drivers/kolab/kolab_driver.php          |   64 --------
 plugins/libkolab/lib/kolab_storage.php                   |  120 ++++++++++++---
 plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php |   57 -------
 3 files changed, 100 insertions(+), 141 deletions(-)

New commits:
commit 43b287c470a9ce67cd10a80b8080cf6b6681dc06
Author: Aleksander Machniak <machniak at kolabsys.com>
Date:   Thu Nov 21 10:58:16 2013 +0100

    Fix folders sorting issues (Bug #2210)
    - move some shared code to kolab_storage
    - this requires recent Roundcube Framework (f13ae32a)

diff --git a/plugins/calendar/drivers/kolab/kolab_driver.php b/plugins/calendar/drivers/kolab/kolab_driver.php
index d68d177..f673f6c 100644
--- a/plugins/calendar/drivers/kolab/kolab_driver.php
+++ b/plugins/calendar/drivers/kolab/kolab_driver.php
@@ -110,7 +110,7 @@ class kolab_driver extends calendar_driver
 
     // include virtual folders for a full folder tree
     if (!$active && !$personal && !$this->rc->output->ajax_call && in_array($this->rc->action, array('index','')))
-      $folders = $this->_folder_hierarchy($folders, $this->rc->get_storage()->get_hierarchy_delimiter());
+      $folders = kolab_storage::folder_hierarchy($folders);
 
     foreach ($folders as $id => $cal) {
       $fullname = $cal->get_name();
@@ -149,39 +149,6 @@ class kolab_driver extends calendar_driver
   }
 
   /**
-   * Check the folder tree and add the missing parents as virtual folders
-   */
-  private function _folder_hierarchy($folders, $delim)
-  {
-    $parents = array();
-    $existing = array_map(function($folder){ return $folder->get_name(); }, $folders);
-    foreach ($folders as $id => $folder) {
-      $path = explode($delim, $folder->name);
-      array_pop($path);
-
-      // skip top folders or ones with a custom displayname
-      if (count($path) <= 1 || kolab_storage::custom_displayname($folder->name))
-        continue;
-
-      while (count($path) > 1 && ($parent = join($delim, $path))) {
-        if (!in_array($parent, $existing) && !$parents[$parent]) {
-          $name = kolab_storage::object_name($parent, $folder->get_namespace());
-          $parents[$parent] = new virtual_kolab_calendar($name, $folder->get_namespace());
-          $parents[$parent]->id = kolab_storage::folder_id($parent);
-        }
-        array_pop($path);
-      }
-    }
-
-    // add virtual parents to the list and sort again
-    if (count($parents)) {
-      $folders = kolab_storage::sort_folders(array_merge($folders, array_values($parents)));
-    }
-
-    return $folders;
-  }
-
-  /**
    * Get list of calendars according to specified filters
    *
    * @param bool $writeable Return only writeable calendars
@@ -1281,32 +1248,3 @@ class kolab_driver extends calendar_driver
   }
 
 }
-
-
-/**
- * Helper class that represents a virtual IMAP folder
- * with a subset of the kolab_calendar API.
- */
-class virtual_kolab_calendar
-{
-    public $name;
-    public $namespace;
-    public $virtual = true;
-
-    public function __construct($name, $ns)
-    {
-        $this->name = $name;
-        $this->namespace = $ns;
-    }
-
-    public function get_name()
-    {
-        return $this->name;
-    }
-
-    public function get_namespace()
-    {
-        return $this->namespace;
-    }
-}
-
diff --git a/plugins/libkolab/lib/kolab_storage.php b/plugins/libkolab/lib/kolab_storage.php
index 5f8b9c6..a95a59e 100644
--- a/plugins/libkolab/lib/kolab_storage.php
+++ b/plugins/libkolab/lib/kolab_storage.php
@@ -433,7 +433,7 @@ class kolab_storage
                     // get username
                     $pos    = strpos($folder, $delim);
                     if ($pos) {
-                        $prefix = '('.substr($folder, 0, $pos).') ';
+                        $prefix = '('.substr($folder, 0, $pos).')';
                         $folder = substr($folder, $pos+1);
                     }
                     else {
@@ -525,8 +525,8 @@ class kolab_storage
      */
     public static function folder_selector($type, $attrs, $current = '')
     {
-        // get all folders of specified type
-        $folders = self::get_folders($type, false);
+        // get all folders of specified type (sorted)
+        $folders = self::get_folders($type, true);
 
         $delim = self::$imap->get_hierarchy_delimiter();
         $names = array();
@@ -540,13 +540,15 @@ class kolab_storage
         // Filter folders list
         foreach ($folders as $c_folder) {
             $name = $c_folder->name;
+
             // skip current folder and it's subfolders
             if ($len && ($name == $current || strpos($name, $current.$delim) === 0)) {
                 continue;
             }
 
             // always show the parent of current folder
-            if ($p_len && $name == $parent) { }
+            if ($p_len && $name == $parent) {
+            }
             // skip folders where user have no rights to create subfolders
             else if ($c_folder->get_owner() != $_SESSION['username']) {
                 $rights = $c_folder->get_myrights();
@@ -555,17 +557,14 @@ class kolab_storage
                 }
             }
 
-            $names[$name] = self::object_name($name);
-        }
+            // Make sure parent folder is listed (might be skipped e.g. if it's namespace root)
+            if ($p_len && !isset($names[$parent]) && strpos($name, $parent.$delim) === 0) {
+                $names[$parent] = self::object_name($parent);
+            }
 
-        // Make sure parent folder is listed (might be skipped e.g. if it's namespace root)
-        if ($p_len && !isset($names[$parent])) {
-            $names[$parent] = self::object_name($parent);
+            $names[$name] = self::object_name($name);
         }
 
-        // Sort folders list
-        asort($names, SORT_LOCALE_STRING);
-
         // Build SELECT field of parent folder
         $attrs['is_escaped'] = true;
         $select = new html_select($attrs);
@@ -643,7 +642,8 @@ class kolab_storage
                     unset($folderdata[$folder]);
                 }
             }
-            return array_keys($folderdata);
+
+            return self::$imap->sort_folder_list(array_keys($folderdata), true);
         }
 
         // Get folders list
@@ -683,26 +683,75 @@ class kolab_storage
      */
     public static function sort_folders($folders)
     {
-        $pad = '  ';
+        $pad     = '  ';
+        $out     = array();
         $nsnames = array('personal' => array(), 'shared' => array(), 'other' => array());
+
         foreach ($folders as $folder) {
             $folders[$folder->name] = $folder;
             $ns = $folder->get_namespace();
             $nsnames[$ns][$folder->name] = strtolower(html_entity_decode(self::object_name($folder->name, $ns), ENT_COMPAT, RCUBE_CHARSET)) . $pad;  // decode »
         }
 
-        $names = array();
-        foreach ($nsnames as $ns => $dummy) {
-            asort($nsnames[$ns], SORT_LOCALE_STRING);
-            $names += $nsnames[$ns];
+        // $folders is a result of get_folders() we can assume folders were already sorted
+        foreach (array_keys($nsnames) as $ns) {
+            // asort($nsnames[$ns], SORT_LOCALE_STRING);
+            foreach (array_keys($nsnames[$ns]) as $utf7name) {
+                $out[] = $folders[$utf7name];
+            }
         }
 
-        $out = array();
-        foreach ($names as $utf7name => $name) {
-            $out[] = $folders[$utf7name];
+        return $out;
+    }
+
+
+    /**
+     * Check the folder tree and add the missing parents as virtual folders
+     *
+     * @param array $folders Folders list
+     *
+     * @return array Folders list
+     */
+    public static function folder_hierarchy($folders)
+    {
+        $_folders = array();
+        $existing = array_map(function($folder){ return $folder->get_name(); }, $folders);
+        $delim    = rcube::get_instance()->get_storage()->get_hierarchy_delimiter();
+
+        foreach ($folders as $idx => $folder) {
+            $path = explode($delim, $folder->name);
+            array_pop($path);
+
+            // skip top folders or ones with a custom displayname
+            if (count($path) <= 1 || kolab_storage::custom_displayname($folder->name)) {
+            }
+            else {
+                $parents = array();
+
+                while (count($path) > 1 && ($parent = join($delim, $path))) {
+                    $name = kolab_storage::object_name($parent, $folder->get_namespace());
+                    if (!in_array($name, $existing)) {
+                        $parents[$parent] = new virtual_kolab_storage_folder($name, $folder->get_namespace());
+                        $parents[$parent]->id = kolab_storage::folder_id($parent);
+                        $existing[] = $name;
+                    }
+
+                    array_pop($path);
+                }
+
+                if (!empty($parents)) {
+                    $parents = array_reverse(array_values($parents));
+                    foreach ($parents as $parent) {
+                        $_folders[] = $parent;
+                    }
+                }
+            }
+
+            $_folders[] = $folder;
+            unset($folders[$idx]);
         }
 
-        return $out;
+        return $_folders;
     }
 
 
@@ -1047,3 +1096,30 @@ class kolab_storage
     }
 
 }
+
+/**
+ * Helper class that represents a virtual IMAP folder
+ * with a subset of the kolab_storage_folder API.
+ */
+class virtual_kolab_storage_folder
+{
+    public $name;
+    public $namespace;
+    public $virtual = true;
+
+    public function __construct($name, $ns)
+    {
+        $this->name = $name;
+        $this->namespace = $ns;
+    }
+
+    public function get_namespace()
+    {
+        return $this->namespace;
+    }
+
+    public function get_name()
+    {
+        return $this->name;
+    }
+}
diff --git a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
index c92ca55..625ca38 100644
--- a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
+++ b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
@@ -85,7 +85,7 @@ class tasklist_kolab_driver extends tasklist_driver
 
         // include virtual folders for a full folder tree
         if (!$this->rc->output->ajax_call && in_array($this->rc->action, array('index','')))
-            $folders = $this->_folder_hierarchy($folders, $delim);
+            $folders = kolab_storage::folder_hierarchy($folders);
 
         foreach ($folders as $folder) {
             $utf7name = $folder->name;
@@ -149,38 +149,6 @@ class tasklist_kolab_driver extends tasklist_driver
     }
 
     /**
-     * Check the folder tree and add the missing parents as virtual folders
-     */
-    private function _folder_hierarchy($folders, $delim)
-    {
-        $parents = array();
-        $existing = array_map(function($folder){ return $folder->name; }, $folders);
-        foreach ($folders as $id => $folder) {
-            $path = explode($delim, $folder->name);
-            array_pop($path);
-
-            // skip top folders or ones with a custom displayname
-            if (count($path) <= 1 || kolab_storage::custom_displayname($folder->name))
-                continue;
-
-            while (count($path) > 1 && ($parent = join($delim, $path))) {
-                if (!in_array($parent, $existing) && !$parents[$parent]) {
-                    $parents[$parent] = new virtual_kolab_storage_folder($parent, $folder->get_namespace());
-                }
-                array_pop($path);
-            }
-        }
-
-        // add virtual parents to the list and sort again
-        if (count($parents)) {
-            $folders = kolab_storage::sort_folders(array_merge($folders, array_values($parents)));
-        }
-
-        return $folders;
-    }
-
-
-    /**
      * Get a list of available task lists from this source
      */
     public function get_lists()
@@ -906,26 +874,3 @@ class tasklist_kolab_driver extends tasklist_driver
     }
 
 }
-
-/**
- * Helper class that represents a virtual IMAP folder
- * with a subset of the kolab_storage_folder API.
- */
-class virtual_kolab_storage_folder
-{
-    public $name;
-    public $namespace;
-    public $virtual = true;
-
-    public function __construct($name, $ns)
-    {
-        $this->name = $name;
-        $this->namespace = $ns;
-    }
-
-    public function get_namespace()
-    {
-        return $this->namespace;
-    }
-}
-




More information about the commits mailing list