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 $plugin;
private $lists = array(); private $lists = array();
private $list_ids = ''; private $list_ids = '';
private $tags = array();
private $db_tasks = 'tasks'; private $db_tasks = 'tasks';
private $db_lists = 'tasklists'; private $db_lists = 'tasklists';
@ -213,6 +214,16 @@ class tasklist_database_driver extends tasklist_driver
return array(); 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 * 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']); $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']); unset($rec['task_id'], $rec['tasklist_id'], $rec['created']);
return $rec; return $rec;
} }

View file

@ -36,6 +36,7 @@ class tasklist_kolab_driver extends tasklist_driver
private $lists; private $lists;
private $folders = array(); private $folders = array();
private $tasks = array(); private $tasks = array();
private $tags = array();
/** /**
@ -440,6 +441,20 @@ class tasklist_kolab_driver extends tasklist_driver
return $this->get_lists(); 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 * Get number of tasks matching the given filter
* *
@ -530,11 +545,15 @@ class tasklist_kolab_driver extends tasklist_driver
$query[] = array('changed', '>=', $filter['since']); $query[] = array('changed', '>=', $filter['since']);
} }
// load all tags into memory first
kolab_storage_config::get_instance()->get_tags();
foreach ($lists as $list_id) { foreach ($lists as $list_id) {
if (!$folder = $this->get_folder($list_id)) { if (!$folder = $this->get_folder($list_id)) {
continue; continue;
} }
foreach ($folder->select($query) as $record) { foreach ($folder->select($query) as $record) {
$this->load_tags($record);
$task = $this->_to_rcube_task($record); $task = $this->_to_rcube_task($record);
$task['list'] = $list_id; $task['list'] = $list_id;
@ -567,17 +586,13 @@ class tasklist_kolab_driver extends tasklist_driver
if (is_numeric($list_id) || !$folder) if (is_numeric($list_id) || !$folder)
continue; continue;
if (!$this->tasks[$id] && ($object = $folder->get_object($id))) { if (!$this->tasks[$id] && ($object = $folder->get_object($id))) {
$this->load_tags($object);
$this->tasks[$id] = $this->_to_rcube_task($object); $this->tasks[$id] = $this->_to_rcube_task($object);
$this->tasks[$id]['list'] = $list_id; $this->tasks[$id]['list'] = $list_id;
break; break;
} }
} }
// assign tags
if ($this->tasks[$id]) {
$this->tasks[$id]['tags'] = $this->get_tags($this->tasks[$id]['uid']);
}
return $this->tasks[$id]; return $this->tasks[$id];
} }
@ -767,13 +782,21 @@ class tasklist_kolab_driver extends tasklist_driver
/** /**
* Get task tags * Get task tags
*/ */
private function get_tags($uid) private function load_tags(&$object)
{ {
$config = kolab_storage_config::get_instance(); // this task hasn't been migrated yet
$tags = $config->get_tags($uid); if (!empty($object['categories'])) {
$tags = array_map(function($v) { return $v['name']; }, $tags); // OPTIONAL: call kolab_storage_config::apply_tags() to migrate the object
$object['tags'] = (array)$object['categories'];
return $tags; 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'], 'attendees' => $record['attendees'],
'organizer' => $record['organizer'], 'organizer' => $record['organizer'],
'sequence' => $record['sequence'], 'sequence' => $record['sequence'],
// old categories will be replaced by tags 'tags' => $record['tags'],
'categories' => $record['categories'],
// keep mailbox which is needed to convert
// categories to tags in kolab_storage_config::apply_tags()
'_mailbox' => $record['_mailbox'],
); );
// convert from DateTime to internal date format // convert from DateTime to internal date format

View file

@ -156,6 +156,13 @@ abstract class tasklist_driver
*/ */
abstract function list_tasks($filter, $lists = null); 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 * 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 $collapsed_tasks = array();
private $itip; private $itip;
private $ical; private $ical;
private $driver_name;
/** /**
@ -189,8 +188,6 @@ class tasklist extends rcube_plugin
break; break;
} }
$this->driver_name = $driver_name;
$this->rc->output->set_env('tasklist_driver', $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); $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' => array_values(array_unique($tags)))); $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 * 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(); $data = $this->task_tree = $this->task_titles = array();
if ($this->driver_name == 'kolab') {
$config = kolab_storage_config::get_instance();
$tags = $config->apply_tags($records);
}
foreach ($records as $rec) { foreach ($records as $rec) {
if ($rec['parent_id']) { if ($rec['parent_id']) {
@ -965,10 +963,6 @@ class tasklist extends rcube_plugin
$this->encode_task($rec); $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 :-) // apply filter; don't trust the driver on this :-)
if ((!$f && !$this->driver->is_complete($rec)) || ($rec['mask'] & $f)) if ((!$f && !$this->driver->is_complete($rec)) || ($rec['mask'] & $f))
$data[] = $rec; $data[] = $rec;
@ -1221,7 +1215,7 @@ class tasklist extends rcube_plugin
$updates = $this->driver->list_tasks($filter, $lists); $updates = $this->driver->list_tasks($filter, $lists);
if (!empty($updates)) { 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 // update counts
$counts = $this->driver->count_tasks($lists); $counts = $this->driver->count_tasks($lists);