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

This commit is contained in:
Thomas Bruederli 2014-08-26 12:12:03 +02:00
parent 54b6eb66de
commit 68b7e05fa3
4 changed files with 68 additions and 33 deletions

View file

@ -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';
@ -213,6 +214,16 @@ class tasklist_database_driver extends tasklist_driver
return array();
}
/**
* 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
*
@ -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;
}

View file

@ -36,6 +36,7 @@ class tasklist_kolab_driver extends tasklist_driver
private $lists;
private $folders = array();
private $tasks = array();
private $tags = array();
/**
@ -440,6 +441,20 @@ class tasklist_kolab_driver extends tasklist_driver
return $this->get_lists();
}
/**
* 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
*
@ -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

View file

@ -156,6 +156,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
*

View file

@ -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);