3 commits - plugins/kolab_notes plugins/libkolab plugins/tasklist

Thomas Brüderli bruederli at kolabsys.com
Tue Aug 26 12:34:31 CEST 2014


 plugins/kolab_notes/kolab_notes.php                            |   12 +-
 plugins/libkolab/lib/kolab_storage_cache.php                   |    6 -
 plugins/libkolab/lib/kolab_storage_cache_configuration.php     |   22 ++++
 plugins/libkolab/lib/kolab_storage_config.php                  |   15 +-
 plugins/tasklist/drivers/database/tasklist_database_driver.php |   15 ++
 plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php       |   51 ++++++----
 plugins/tasklist/drivers/tasklist_driver.php                   |    7 +
 plugins/tasklist/tasklist.php                                  |   28 ++---
 8 files changed, 112 insertions(+), 44 deletions(-)

New commits:
commit 44bf23bbc1d5fae1234f11209058169fea751662
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Tue Aug 26 12:33:37 2014 +0200

    Avoid endless recursion when loading kolab config objects (also triggers 'mail_message_load' hook)

diff --git a/plugins/kolab_notes/kolab_notes.php b/plugins/kolab_notes/kolab_notes.php
index a5723a1..28ad6c9 100644
--- a/plugins/kolab_notes/kolab_notes.php
+++ b/plugins/kolab_notes/kolab_notes.php
@@ -81,9 +81,12 @@ class kolab_notes extends rcube_plugin
         }
         else if ($args['task'] == 'mail') {
             $this->add_hook('storage_init', array($this, 'storage_init'));
-            $this->add_hook('message_load', array($this, 'mail_message_load'));
             $this->add_hook('message_compose', array($this, 'mail_message_compose'));
-            $this->add_hook('template_object_messagebody', array($this, 'mail_messagebody_html'));
+
+            if ($args['action'] == 'show' || $args['action'] == 'preview') {
+                $this->add_hook('message_load', array($this, 'mail_message_load'));
+                $this->add_hook('template_object_messagebody', array($this, 'mail_messagebody_html'));
+            }
 
             // add 'Append note' item to message menu
             if ($this->api->output->type == 'html' && $_REQUEST['_rel'] != 'note') {
@@ -906,8 +909,9 @@ class kolab_notes extends rcube_plugin
      */
     public function mail_message_load($p)
     {
-        $this->message       = $p['object'];
-        $this->message_notes = $this->get_message_notes($this->message->headers, $this->message->folder);
+        if (!$p['object']->headers->others['x-kolab-type']) {
+            $this->message_notes = $this->get_message_notes($p['object']->headers, $p['object']->folder);
+        }
     }
 
     /**


commit 68b7e05fa35e6818b234334997cc8f7635530b5c
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Tue Aug 26 12:12:03 2014 +0200

    Refactor tag handling in task list: don't migrate kolab objects on read but only when changed (#3395); let drivers provide the full list of available tags

diff --git a/plugins/tasklist/drivers/database/tasklist_database_driver.php b/plugins/tasklist/drivers/database/tasklist_database_driver.php
index bd6bd1b..9ec930a 100644
--- a/plugins/tasklist/drivers/database/tasklist_database_driver.php
+++ b/plugins/tasklist/drivers/database/tasklist_database_driver.php
@@ -34,6 +34,7 @@ class tasklist_database_driver extends tasklist_driver
     private $plugin;
     private $lists = array();
     private $list_ids = '';
+    private $tags = array();
 
     private $db_tasks = 'tasks';
     private $db_lists = 'tasklists';
@@ -214,6 +215,16 @@ class tasklist_database_driver extends tasklist_driver
     }
 
     /**
+     * Get a list of tags to assign tasks to
+     *
+     * @return array List of tags
+     */
+    public function get_tags()
+    {
+        return array_values(array_unique($this->tags, SORT_STRING));
+    }
+
+    /**
      * Get number of tasks matching the given filter
      *
      * @param array List of lists to count tasks of
@@ -518,6 +529,10 @@ class tasklist_database_driver extends tasklist_driver
             $rec['recurrence'] = $this->unserialize_recurrence($rec['recurrence']);
         }
 
+        if (!empty($rec['tags'])) {
+            $this->tags = array_merge($this->tags, (array)$rec['tags']);
+        }
+
         unset($rec['task_id'], $rec['tasklist_id'], $rec['created']);
         return $rec;
     }
diff --git a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
index 1c8a8c7..f340b42 100644
--- a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
+++ b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
@@ -36,6 +36,7 @@ class tasklist_kolab_driver extends tasklist_driver
     private $lists;
     private $folders = array();
     private $tasks   = array();
+    private $tags    = array();
 
 
     /**
@@ -441,6 +442,20 @@ class tasklist_kolab_driver extends tasklist_driver
     }
 
     /**
+     * Get a list of tags to assign tasks to
+     *
+     * @return array List of tags
+     */
+    public function get_tags()
+    {
+        $config = kolab_storage_config::get_instance();
+        $tags   = $config->get_tags();
+        $backend_tags = array_map(function($v) { return $v['name']; }, $tags);
+
+        return array_values(array_unique(array_merge($this->tags, $backend_tags)));
+    }
+
+    /**
      * Get number of tasks matching the given filter
      *
      * @param array List of lists to count tasks of
@@ -530,11 +545,15 @@ class tasklist_kolab_driver extends tasklist_driver
             $query[] = array('changed', '>=', $filter['since']);
         }
 
+        // load all tags into memory first
+        kolab_storage_config::get_instance()->get_tags();
+
         foreach ($lists as $list_id) {
             if (!$folder = $this->get_folder($list_id)) {
                 continue;
             }
             foreach ($folder->select($query) as $record) {
+                $this->load_tags($record);
                 $task = $this->_to_rcube_task($record);
                 $task['list'] = $list_id;
 
@@ -567,17 +586,13 @@ class tasklist_kolab_driver extends tasklist_driver
             if (is_numeric($list_id) || !$folder)
                 continue;
             if (!$this->tasks[$id] && ($object = $folder->get_object($id))) {
+                $this->load_tags($object);
                 $this->tasks[$id] = $this->_to_rcube_task($object);
                 $this->tasks[$id]['list'] = $list_id;
                 break;
             }
         }
 
-        // assign tags
-        if ($this->tasks[$id]) {
-            $this->tasks[$id]['tags'] = $this->get_tags($this->tasks[$id]['uid']);
-        }
-
         return $this->tasks[$id];
     }
 
@@ -767,13 +782,21 @@ class tasklist_kolab_driver extends tasklist_driver
     /**
      * Get task tags
      */
-    private function get_tags($uid)
+    private function load_tags(&$object)
     {
-        $config = kolab_storage_config::get_instance();
-        $tags   = $config->get_tags($uid);
-        $tags   = array_map(function($v) { return $v['name']; }, $tags);
-
-        return $tags;
+        // this task hasn't been migrated yet
+        if (!empty($object['categories'])) {
+            // OPTIONAL: call kolab_storage_config::apply_tags() to migrate the object
+            $object['tags'] = (array)$object['categories'];
+            if (!empty($object['tags'])) {
+                $this->tags = array_merge($this->tags, $object['tags']);
+            }
+        }
+        else {
+            $config = kolab_storage_config::get_instance();
+            $tags   = $config->get_tags($object['uid']);
+            $object['tags'] = array_map(function($v) { return $v['name']; }, $tags);
+        }
     }
 
     /**
@@ -804,11 +827,7 @@ class tasklist_kolab_driver extends tasklist_driver
             'attendees' => $record['attendees'],
             'organizer' => $record['organizer'],
             'sequence' => $record['sequence'],
-            // old categories will be replaced by tags
-            'categories' => $record['categories'],
-            // keep mailbox which is needed to convert
-            // categories to tags in kolab_storage_config::apply_tags()
-            '_mailbox' => $record['_mailbox'],
+            'tags' => $record['tags'],
         );
 
         // convert from DateTime to internal date format
diff --git a/plugins/tasklist/drivers/tasklist_driver.php b/plugins/tasklist/drivers/tasklist_driver.php
index dd2e415..2775539 100644
--- a/plugins/tasklist/drivers/tasklist_driver.php
+++ b/plugins/tasklist/drivers/tasklist_driver.php
@@ -157,6 +157,13 @@ abstract class tasklist_driver
     abstract function list_tasks($filter, $lists = null);
 
     /**
+     * Get a list of tags to assign tasks to
+     *
+     * @return array List of tags
+     */
+    abstract function get_tags();
+
+    /**
      * Get a list of pending alarms to be displayed to the user
      *
      * @param  integer Current time (unix timestamp)
diff --git a/plugins/tasklist/tasklist.php b/plugins/tasklist/tasklist.php
index 4004a9b..fe8c5c3 100644
--- a/plugins/tasklist/tasklist.php
+++ b/plugins/tasklist/tasklist.php
@@ -63,7 +63,6 @@ class tasklist extends rcube_plugin
     private $collapsed_tasks = array();
     private $itip;
     private $ical;
-    private $driver_name;
 
 
     /**
@@ -189,8 +188,6 @@ class tasklist extends rcube_plugin
             break;
         }
 
-        $this->driver_name = $driver_name;
-
         $this->rc->output->set_env('tasklist_driver', $driver_name);
     }
 
@@ -942,21 +939,22 @@ class tasklist extends rcube_plugin
 
         }
 */
-        $data = $this->tasks_data($this->driver->list_tasks($filter, $lists), $f, $tags);
-        $this->rc->output->command('plugin.data_ready', array('filter' => $f, 'lists' => $lists, 'search' => $search, 'data' => $data, 'tags' => array_values(array_unique($tags))));
+        $data = $this->tasks_data($this->driver->list_tasks($filter, $lists), $f);
+        $this->rc->output->command('plugin.data_ready', array(
+            'filter' => $f,
+            'lists' => $lists,
+            'search' => $search,
+            'data' => $data,
+            'tags' => $this->driver->get_tags(),
+        ));
     }
 
     /**
      * Prepare and sort the given task records to be sent to the client
      */
-    private function tasks_data($records, $f, &$tags)
+    private function tasks_data($records, $f)
     {
-        $data = $tags = $this->task_tree = $this->task_titles = array();
-
-        if ($this->driver_name == 'kolab') {
-            $config = kolab_storage_config::get_instance();
-            $tags   = $config->apply_tags($records);
-        }
+        $data = $this->task_tree = $this->task_titles = array();
 
         foreach ($records as $rec) {
             if ($rec['parent_id']) {
@@ -965,10 +963,6 @@ class tasklist extends rcube_plugin
 
             $this->encode_task($rec);
 
-            if ($this->driver_name != 'kolab' && !empty($rec['tags'])) {
-                $tags = array_merge($tags, (array)$rec['tags']);
-            }
-
             // apply filter; don't trust the driver on this :-)
             if ((!$f && !$this->driver->is_complete($rec)) || ($rec['mask'] & $f))
                 $data[] = $rec;
@@ -1221,7 +1215,7 @@ class tasklist extends rcube_plugin
 
         $updates = $this->driver->list_tasks($filter, $lists);
         if (!empty($updates)) {
-            $this->rc->output->command('plugin.refresh_tasks', $this->tasks_data($updates, 255, $tags), true);
+            $this->rc->output->command('plugin.refresh_tasks', $this->tasks_data($updates, 255), true);
 
             // update counts
             $counts = $this->driver->count_tasks($lists);


commit 54b6eb66decf1828c8217db6e2b90bcf16c49eb9
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date:   Tue Aug 26 12:03:11 2014 +0200

    Post-filter all tag objects (in case caching is disabled); improve kolab_storage_cache for the case caching is off

diff --git a/plugins/libkolab/lib/kolab_storage_cache.php b/plugins/libkolab/lib/kolab_storage_cache.php
index d56f04d..eec058d 100644
--- a/plugins/libkolab/lib/kolab_storage_cache.php
+++ b/plugins/libkolab/lib/kolab_storage_cache.php
@@ -265,8 +265,10 @@ class kolab_storage_cache
 
             // fetch from IMAP if not present in cache
             if (empty($this->objects[$msguid])) {
-                $result = $this->_fetch(array($msguid), $type, $foldername);
-                $this->objects = array($msguid => $result[0]);  // store only this object in memory (#2827)
+                if ($object = $this->folder->read_object($msguid, $type ?: '*', $foldername)) {
+                    $this->objects = array($msguid => $object);
+                    $this->set($msguid, $object);
+                }
             }
         }
 
diff --git a/plugins/libkolab/lib/kolab_storage_cache_configuration.php b/plugins/libkolab/lib/kolab_storage_cache_configuration.php
index ec015dd..c3c7ac4 100644
--- a/plugins/libkolab/lib/kolab_storage_cache_configuration.php
+++ b/plugins/libkolab/lib/kolab_storage_cache_configuration.php
@@ -39,6 +39,28 @@ class kolab_storage_cache_configuration extends kolab_storage_cache
     }
 
     /**
+     * Select Kolab objects filtered by the given query
+     *
+     * @param array Pseudo-SQL query as list of filter parameter triplets
+     * @param boolean Set true to only return UIDs instead of complete objects
+     * @return array List of Kolab data objects (each represented as hash array) or UIDs
+     */
+    public function select($query = array(), $uids = false)
+    {
+        // modify query for IMAP search: query param 'type' is actually a subtype
+        if (!$this->ready) {
+            foreach ($query as $i => $tuple) {
+                if ($tuple[0] == 'type') {
+                    $tuple[2] = 'configuration.' . $tuple[2];
+                    $query[$i] = $tuple;
+                }
+            }
+        }
+
+        return parent::select($query, $uids);
+    }
+
+    /**
      * Helper method to compose a valid SQL query from pseudo filter triplets
      */
     protected function _sql_where($query)
diff --git a/plugins/libkolab/lib/kolab_storage_config.php b/plugins/libkolab/lib/kolab_storage_config.php
index 9bc5d50..8a0fab5 100644
--- a/plugins/libkolab/lib/kolab_storage_config.php
+++ b/plugins/libkolab/lib/kolab_storage_config.php
@@ -125,6 +125,7 @@ class kolab_storage_config
             }
 
             foreach ($folder->select($filter) as $object) {
+                unset($object['_formatobj']);
                 $list[] = $object;
             }
         }
@@ -626,20 +627,24 @@ class kolab_storage_config
             // use faster method
             if ($uid && $uid != '*') {
                 $filter[] = array('member', '=', $uid);
-                return $this->get_objects($filter, $default);
+                $tags = $this->get_objects($filter, $default);
             }
-
-            $this->tags = $this->get_objects($filter, $default);
+            else {
+                $this->tags = $tags = $this->get_objects($filter, $default);
+            }
+        }
+        else {
+            $tags = $this->tags;
         }
 
         if ($uid === '*') {
-            return $this->tags;
+            return $tags;
         }
 
         $result = array();
         $search = self::build_member_url($uid);
 
-        foreach ($this->tags as $tag) {
+        foreach ($tags as $tag) {
             if (in_array($search, (array) $tag['members'])) {
                 $result[] = $tag;
             }




More information about the commits mailing list