2 commits - plugins/calendar plugins/tasklist
Thomas Brüderli
bruederli at kolabsys.com
Tue Nov 4 10:57:08 CET 2014
plugins/calendar/drivers/database/database_driver.php | 4
plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php | 116 +++++++++++----
plugins/tasklist/tasklist.js | 2
plugins/tasklist/tasklist.php | 7
4 files changed, 95 insertions(+), 34 deletions(-)
New commits:
commit ef166c2479f197b47425e808ea5e9698f52c613c
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Tue Nov 4 10:56:19 2014 +0100
Use unique identifiers (folder + uid) for task records (#3533)
diff --git a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
index 3ee1100..be51d23 100644
--- a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
+++ b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
@@ -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');
@@ -873,12 +875,61 @@ class tasklist_kolab_driver extends tasklist_driver
}
/**
+ * 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;
diff --git a/plugins/tasklist/tasklist.js b/plugins/tasklist/tasklist.js
index 5ec467d..5bed07f 100644
--- a/plugins/tasklist/tasklist.js
+++ b/plugins/tasklist/tasklist.js
@@ -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);
diff --git a/plugins/tasklist/tasklist.php b/plugins/tasklist/tasklist.php
index dc01f3c..5f34e86 100644
--- a/plugins/tasklist/tasklist.php
+++ b/plugins/tasklist/tasklist.php
@@ -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;
}
}
commit 5dbd509af5dcb443839d1f41307e56c5071558dc
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Tue Nov 4 08:34:20 2014 +0100
Fix input check to work with numeric calendar IDs from database (#3835)
diff --git a/plugins/calendar/drivers/database/database_driver.php b/plugins/calendar/drivers/database/database_driver.php
index c1e37da..891e7b8 100644
--- a/plugins/calendar/drivers/database/database_driver.php
+++ b/plugins/calendar/drivers/database/database_driver.php
@@ -795,8 +795,8 @@ class database_driver extends calendar_driver
{
if (empty($calendars))
$calendars = array_keys($this->calendars);
- else if (is_string($calendars))
- $calendars = explode(',', $calendars);
+ else if (!is_array($calendars))
+ $calendars = explode(',', strval($calendars));
// only allow to select from calendars of this use
$calendar_ids = array_map(array($this->rc->db, 'quote'), array_intersect($calendars, array_keys($this->calendars)));
More information about the commits
mailing list