Use unique identifiers (folder + uid) for task records (#3533)
This commit is contained in:
parent
5dbd509af5
commit
ef166c2479
3 changed files with 93 additions and 32 deletions
|
@ -492,7 +492,7 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
continue;
|
||||
}
|
||||
foreach ($folder->select(array(array('tags','!~','x-complete'))) as $record) {
|
||||
$rec = $this->_to_rcube_task($record);
|
||||
$rec = $this->_to_rcube_task($record, $list_id);
|
||||
|
||||
if ($this->is_complete($rec)) // don't count complete tasks
|
||||
continue;
|
||||
|
@ -567,8 +567,7 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
}
|
||||
foreach ($folder->select($query) as $record) {
|
||||
$this->load_tags($record);
|
||||
$task = $this->_to_rcube_task($record);
|
||||
$task['list'] = $list_id;
|
||||
$task = $this->_to_rcube_task($record, $list_id);
|
||||
|
||||
// TODO: post-filter tasks returned from storage
|
||||
|
||||
|
@ -590,8 +589,9 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
*/
|
||||
public function get_task($prop)
|
||||
{
|
||||
$id = is_array($prop) ? ($prop['uid'] ?: $prop['id']) : $prop;
|
||||
$list_id = is_array($prop) ? $prop['list'] : null;
|
||||
$this->_parse_id($prop);
|
||||
$id = $prop['uid'];
|
||||
$list_id = $prop['list'];
|
||||
$folders = $list_id ? array($list_id => $this->get_folder($list_id)) : $this->folders;
|
||||
|
||||
// find task in the available folders
|
||||
|
@ -600,8 +600,7 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
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;
|
||||
$this->tasks[$id] = $this->_to_rcube_task($object, $list_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -620,12 +619,15 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
{
|
||||
if (is_string($prop)) {
|
||||
$task = $this->get_task($prop);
|
||||
$prop = array('id' => $task['id'], 'list' => $task['list']);
|
||||
$prop = array('uid' => $task['uid'], 'list' => $task['list']);
|
||||
}
|
||||
else {
|
||||
$this->_parse_id($prop);
|
||||
}
|
||||
|
||||
$childs = array();
|
||||
$list_id = $prop['list'];
|
||||
$task_ids = array($prop['id']);
|
||||
$task_ids = array($prop['uid']);
|
||||
$folder = $this->get_folder($list_id);
|
||||
|
||||
// query for childs (recursively)
|
||||
|
@ -636,7 +638,7 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
foreach ($folder->select($query) as $record) {
|
||||
// don't rely on kolab_storage_folder filtering
|
||||
if ($record['parent_id'] == $task_id) {
|
||||
$childs[] = $record['uid'];
|
||||
$childs[] = $list_id . ':' . $record['uid'];
|
||||
$query_ids[] = $record['uid'];
|
||||
}
|
||||
}
|
||||
|
@ -691,7 +693,7 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
if (!($record['valarms'] || $record['alarms']) || $record['status'] == 'COMPLETED' || $record['complete'] == 100) // don't trust query :-)
|
||||
continue;
|
||||
|
||||
$task = $this->_to_rcube_task($record);
|
||||
$task = $this->_to_rcube_task($record, $lid);
|
||||
|
||||
// add to list if alarm is set
|
||||
$alarm = libcalendaring::get_next_alarm($task, 'task');
|
||||
|
@ -872,13 +874,62 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract uid + list identifiers from the given input
|
||||
*
|
||||
* @param mixed array or string with task identifier(s)
|
||||
*/
|
||||
private function _parse_id(&$prop)
|
||||
{
|
||||
$id_ = null;
|
||||
if (is_array($prop)) {
|
||||
// 'uid' + 'list' available, nothing to be done
|
||||
if (!empty($prop['uid']) && !empty($prop['list'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 'id' is given
|
||||
if (!empty($prop['id'])) {
|
||||
if (!empty($prop['list'])) {
|
||||
$list_id = $prop['_fromlist'] ?: $prop['list'];
|
||||
if (strpos($prop['id'], $list_id.':') === 0) {
|
||||
$prop['uid'] = substr($prop['id'], strlen($list_id)+1);
|
||||
}
|
||||
else {
|
||||
$prop['uid'] = $prop['id'];
|
||||
}
|
||||
}
|
||||
else {
|
||||
$id_ = $prop['id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$id_ = strval($prop);
|
||||
$prop = array();
|
||||
}
|
||||
|
||||
// split 'id' into list + uid
|
||||
if (!empty($id_)) {
|
||||
list($list, $uid) = explode(':', $id_, 2);
|
||||
if (!empty($uid)) {
|
||||
$prop['uid'] = $uid;
|
||||
$prop['list'] = $list;
|
||||
}
|
||||
else {
|
||||
$prop['uid'] = $id_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from Kolab_Format to internal representation
|
||||
*/
|
||||
private function _to_rcube_task($record)
|
||||
private function _to_rcube_task($record, $list_id)
|
||||
{
|
||||
$id_prefix = $list_id . ':';
|
||||
$task = array(
|
||||
'id' => $record['uid'],
|
||||
'id' => $id_prefix . $record['uid'],
|
||||
'uid' => $record['uid'],
|
||||
'title' => $record['title'],
|
||||
// 'location' => $record['location'],
|
||||
|
@ -886,13 +937,14 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
'flagged' => $record['priority'] == 1,
|
||||
'complete' => floatval($record['complete'] / 100),
|
||||
'status' => $record['status'],
|
||||
'parent_id' => $record['parent_id'],
|
||||
'parent_id' => $record['parent_id'] ? $id_prefix . $record['parent_id'] : null,
|
||||
'recurrence' => $record['recurrence'],
|
||||
'attendees' => $record['attendees'],
|
||||
'organizer' => $record['organizer'],
|
||||
'sequence' => $record['sequence'],
|
||||
'tags' => $record['tags'],
|
||||
'links' => $this->get_links($record['uid']),
|
||||
'list' => $list_id,
|
||||
);
|
||||
|
||||
// convert from DateTime to internal date format
|
||||
|
@ -956,6 +1008,7 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
private function _from_rcube_task($task, $old = array())
|
||||
{
|
||||
$object = $task;
|
||||
$id_prefix = $task['list'] . ':';
|
||||
|
||||
if (!empty($task['date'])) {
|
||||
$object['due'] = rcube_utils::anytodatetime($task['date'].' '.$task['time'], $this->plugin->timezone);
|
||||
|
@ -980,6 +1033,11 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
else
|
||||
$object['priority'] = $old['priority'] > 1 ? $old['priority'] : 0;
|
||||
|
||||
// remove list: prefix from parent_id
|
||||
if (!empty($task['parent_id']) && strpos($task['parent_id'], $id_prefix) === 0) {
|
||||
$object['parent_id'] = substr($task['parent_id'], strlen($id_prefix));
|
||||
}
|
||||
|
||||
// copy meta data (starting with _) from old object
|
||||
foreach ((array)$old as $key => $val) {
|
||||
if (!isset($object[$key]) && $key[0] == '_')
|
||||
|
@ -1063,6 +1121,7 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
*/
|
||||
public function edit_task($task)
|
||||
{
|
||||
$this->_parse_id($task);
|
||||
$list_id = $task['list'];
|
||||
if (!$list_id || !($folder = $this->get_folder($list_id)))
|
||||
return false;
|
||||
|
@ -1074,7 +1133,7 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
|
||||
// moved from another folder
|
||||
if ($task['_fromlist'] && ($fromfolder = $this->get_folder($task['_fromlist']))) {
|
||||
if (!$fromfolder->move($task['id'], $folder))
|
||||
if (!$fromfolder->move($task['uid'], $folder))
|
||||
return false;
|
||||
|
||||
unset($task['_fromlist']);
|
||||
|
@ -1082,18 +1141,18 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
|
||||
// load previous version of this task to merge
|
||||
if ($task['id']) {
|
||||
$old = $folder->get_object($task['id']);
|
||||
$old = $folder->get_object($task['uid']);
|
||||
if (!$old || PEAR::isError($old))
|
||||
return false;
|
||||
|
||||
// merge existing properties if the update isn't complete
|
||||
if (!isset($task['title']) || !isset($task['complete']))
|
||||
$task += $this->_to_rcube_task($old);
|
||||
$task += $this->_to_rcube_task($old, $list_id);
|
||||
}
|
||||
|
||||
// generate new task object from RC input
|
||||
$object = $this->_from_rcube_task($task, $old);
|
||||
$saved = $folder->save($object, 'task', $task['id']);
|
||||
$saved = $folder->save($object, 'task', $task['uid']);
|
||||
|
||||
if (!$saved) {
|
||||
raise_error(array(
|
||||
|
@ -1109,10 +1168,9 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
// save tags in configuration.relation object
|
||||
$this->save_tags($object['uid'], $tags);
|
||||
|
||||
$task = $this->_to_rcube_task($object);
|
||||
$task['list'] = $list_id;
|
||||
$task = $this->_to_rcube_task($object, $list_id);
|
||||
$task['tags'] = (array) $tags;
|
||||
$this->tasks[$task['id']] = $task;
|
||||
$this->tasks[$task['uid']] = $task;
|
||||
}
|
||||
|
||||
return $saved;
|
||||
|
@ -1127,13 +1185,14 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
*/
|
||||
public function move_task($task)
|
||||
{
|
||||
$this->_parse_id($task);
|
||||
$list_id = $task['list'];
|
||||
if (!$list_id || !($folder = $this->get_folder($list_id)))
|
||||
return false;
|
||||
|
||||
// execute move command
|
||||
if ($task['_fromlist'] && ($fromfolder = $this->get_folder($task['_fromlist']))) {
|
||||
return $fromfolder->move($task['id'], $folder);
|
||||
return $fromfolder->move($task['uid'], $folder);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -1149,16 +1208,17 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
*/
|
||||
public function delete_task($task, $force = true)
|
||||
{
|
||||
$this->_parse_id($task);
|
||||
$list_id = $task['list'];
|
||||
if (!$list_id || !($folder = $this->get_folder($list_id)))
|
||||
return false;
|
||||
|
||||
$status = $folder->delete($task['id']);
|
||||
$status = $folder->delete($task['uid']);
|
||||
|
||||
if ($status) {
|
||||
// remove tag assignments
|
||||
// @TODO: don't do this when undelete feature will be implemented
|
||||
$this->save_tags($task['id'], null);
|
||||
$this->save_tags($task['uid'], null);
|
||||
}
|
||||
|
||||
return $status;
|
||||
|
@ -1194,7 +1254,6 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
*/
|
||||
public function get_attachment($id, $task)
|
||||
{
|
||||
$task['uid'] = $task['id'];
|
||||
$task = $this->get_task($task);
|
||||
|
||||
if ($task && !empty($task['attachments'])) {
|
||||
|
@ -1219,8 +1278,9 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
*/
|
||||
public function get_attachment_body($id, $task)
|
||||
{
|
||||
$this->_parse_id($task);
|
||||
if ($storage = $this->get_folder($task['list'])) {
|
||||
return $storage->get_attachment($task['id'], $id);
|
||||
return $storage->get_attachment($task['uid'], $id);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -1248,9 +1308,7 @@ class tasklist_kolab_driver extends tasklist_driver
|
|||
$result = $config->get_message_relations($headers, $folder, 'task');
|
||||
|
||||
foreach ($result as $idx => $rec) {
|
||||
$task = $this->_to_rcube_task($rec);
|
||||
$task['list'] = kolab_storage::folder_id($rec['_mailbox']);
|
||||
$result[$idx] = $task;
|
||||
$result[$idx] = $this->_to_rcube_task($rec, kolab_storage::folder_id($rec['_mailbox']));
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
|
|
@ -1873,7 +1873,7 @@ function rcube_tasklist_ui(settings)
|
|||
.html(Q(rcmail.gettext('itip' + mystatus, 'libcalendaring')));
|
||||
}
|
||||
*/
|
||||
var show_rsvp = rsvp && !is_organizer(rec) && rec.status != 'CANCELLED';
|
||||
var show_rsvp = rsvp && list.editable && !is_organizer(rec) && rec.status != 'CANCELLED';
|
||||
$('#task-rsvp')[(show_rsvp ? 'show' : 'hide')]();
|
||||
$('#task-rsvp .rsvp-buttons input').prop('disabled', false).filter('input[rel='+mystatus+']').prop('disabled', true);
|
||||
|
||||
|
|
|
@ -277,16 +277,19 @@ class tasklist extends rcube_plugin
|
|||
$r = $rec;
|
||||
$r['id'] = $id;
|
||||
if ($this->driver->move_task($r)) {
|
||||
$refresh[] = $this->driver->get_task($r);
|
||||
$new_task = $this->driver->get_task($r);
|
||||
$new_task['tempid'] = $id;
|
||||
$refresh[] = $new_task;
|
||||
$success = true;
|
||||
|
||||
// move all childs, too
|
||||
foreach ($this->driver->get_childs(array('id' => $rec['id'], 'list' => $rec['_fromlist']), true) as $cid) {
|
||||
foreach ($this->driver->get_childs(array('id' => $id, 'list' => $rec['_fromlist']), true) as $cid) {
|
||||
$child = $rec;
|
||||
$child['id'] = $cid;
|
||||
if ($this->driver->move_task($child)) {
|
||||
$r = $this->driver->get_task($child);
|
||||
if ((bool)($filter & self::FILTER_MASK_COMPLETE) == $this->driver->is_complete($r)) {
|
||||
$r['tempid'] = $cid;
|
||||
$refresh[] = $r;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue