6 commits - plugins/kolab_notes plugins/libkolab plugins/tasklist
Thomas Brüderli
bruederli at kolabsys.com
Mon Oct 13 15:34:19 CEST 2014
plugins/kolab_notes/kolab_notes.php | 79 -----------
plugins/kolab_notes/kolab_notes_ui.php | 2
plugins/kolab_notes/localization/en_US.inc | 1
plugins/kolab_notes/notes.js | 34 +++-
plugins/kolab_notes/skins/larry/notes.css | 12 +
plugins/libkolab/lib/kolab_format_configuration.php | 4
plugins/libkolab/lib/kolab_storage_config.php | 106 ++++++++++++++-
plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php | 72 +++++++++-
plugins/tasklist/drivers/tasklist_driver.php | 14 +
plugins/tasklist/localization/en_US.inc | 2
plugins/tasklist/skins/larry/sprites.png |binary
plugins/tasklist/skins/larry/tasklist.css | 50 +++++++
plugins/tasklist/skins/larry/templates/mainview.html | 4
plugins/tasklist/skins/larry/templates/taskedit.html | 5
plugins/tasklist/tasklist.js | 68 +++++++++
plugins/tasklist/tasklist.php | 61 ++++++++
16 files changed, 427 insertions(+), 87 deletions(-)
New commits:
commit ff139fe6627102033dc54c2ab7894b85e028e452
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Mon Oct 13 15:34:10 2014 +0200
Allow to delete email message links from notes
diff --git a/plugins/kolab_notes/kolab_notes.php b/plugins/kolab_notes/kolab_notes.php
index 369f1c5..4def121 100644
--- a/plugins/kolab_notes/kolab_notes.php
+++ b/plugins/kolab_notes/kolab_notes.php
@@ -998,6 +998,9 @@ class kolab_notes extends rcube_plugin
private function save_links($uid, $links)
{
+ if (empty($links)) {
+ $links = array();
+ }
$config = kolab_storage_config::get_instance();
$remove = array_diff($config->get_object_links($uid), $links);
return $config->save_object_links($uid, $links, $remove);
diff --git a/plugins/kolab_notes/kolab_notes_ui.php b/plugins/kolab_notes/kolab_notes_ui.php
index 1726980..bb13813 100644
--- a/plugins/kolab_notes/kolab_notes_ui.php
+++ b/plugins/kolab_notes/kolab_notes_ui.php
@@ -102,7 +102,7 @@ class kolab_notes_ui
$this->rc->output->set_env('kolab_notes_settings', $settings);
- $this->rc->output->add_label('save','cancel');
+ $this->rc->output->add_label('save','cancel','delete');
}
public function folders($attrib)
diff --git a/plugins/kolab_notes/localization/en_US.inc b/plugins/kolab_notes/localization/en_US.inc
index 939946c..19d4139 100644
--- a/plugins/kolab_notes/localization/en_US.inc
+++ b/plugins/kolab_notes/localization/en_US.inc
@@ -34,6 +34,7 @@ $labels['listsearchresults'] = 'Additional notebooks';
$labels['nrnotebooksfound'] = '$nr notebooks found';
$labels['nonotebooksfound'] = 'No notebooks found';
$labels['removelist'] = 'Remove from list';
+$labels['removelink'] = 'Remove email reference';
$labels['savingdata'] = 'Saving data...';
$labels['recordnotfound'] = 'Record not found';
diff --git a/plugins/kolab_notes/notes.js b/plugins/kolab_notes/notes.js
index 09813fe..5a9e05f 100644
--- a/plugins/kolab_notes/notes.js
+++ b/plugins/kolab_notes/notes.js
@@ -842,16 +842,19 @@ function rcube_kolab_notes_ui(settings)
.text(link.subject || link.uri)
)
.appendTo(attachmentslist);
-/*
+
if (!readonly && !data._from_mail) {
$('<a>')
.attr('href', '#delete')
- .attr('title', rcmail.gettext('delete'))
+ .attr('title', rcmail.gettext('removelink', 'kolab_notes'))
.addClass('delete')
.html(rcmail.gettext('delete'))
+ .click({ uri:link.uri }, function(e) {
+ remove_link(this, e.data.uri);
+ return false;
+ })
.appendTo(li);
}
-*/
});
}
@@ -939,6 +942,19 @@ function rcube_kolab_notes_ui(settings)
}
/**
+ *
+ */
+ function remove_link(elem, uri)
+ {
+ // remove the link item matching the given uri
+ me.selected_note.links = $.grep(me.selected_note.links, function(link) { return link.uri != uri; });
+ me.selected_note._links_removed = true
+
+ // remove UI list item
+ $(elem).hide().closest('li').addClass('deleted');
+ }
+
+ /**
* Open a new window to print the currently selected note
*/
function print_note()
@@ -1134,10 +1150,6 @@ function rcube_kolab_notes_ui(settings)
var savedata = get_save_data();
- // copy links as they're yet immutable
- if (me.selected_note.links)
- savedata.links = me.selected_note.links;
-
// add reference to old list if changed
if (me.selected_note.list && savedata.list != me.selected_note.list) {
savedata._fromlist = me.selected_note.list;
@@ -1175,6 +1187,11 @@ function rcube_kolab_notes_ui(settings)
tags: []
};
+ // copy links
+ if ($.isArray(me.selected_note.links)) {
+ savedata.links = me.selected_note.links;
+ }
+
// collect tags
$('.tagedit-list input[type="hidden"]', rcmail.gui_objects.noteviewtitle).each(function(i, elem){
if (elem.value)
@@ -1203,7 +1220,8 @@ function rcube_kolab_notes_ui(settings)
return savedata.title != me.selected_note.title
|| savedata.description != me.selected_note.description
|| savedata.tags.join(',') != (me.selected_note.tags || []).join(',')
- || savedata.list != me.selected_note.list;
+ || savedata.list != me.selected_note.list
+ || me.selected_note._links_removed;
}
/**
diff --git a/plugins/kolab_notes/skins/larry/notes.css b/plugins/kolab_notes/skins/larry/notes.css
index 24daa9d..1937da6 100644
--- a/plugins/kolab_notes/skins/larry/notes.css
+++ b/plugins/kolab_notes/skins/larry/notes.css
@@ -530,14 +530,26 @@
}
.notesview .attachmentslist li.message.eml {
+ position: relative;
display: inline-block;
background-image: url(sprites.png);
background-position: -6px -128px;
margin-right: 1em;
+ padding-right: 28px;
}
.notesview .attachmentslist li.message a.messagelink {
padding-left: 24px;
+ padding-right: 0;
+}
+
+.notesview .attachmentslist li.message a.delete {
+ background-position: -6px -378px;
+}
+
+.notesview .attachmentslist li.deleted a.messagelink,
+.notesview .attachmentslist li.deleted a.messagelink:hover {
+ text-decoration: line-through;
}
ul.toolbarmenu li .appendnote span.icon {
commit 44c2639cbeb9bf612d178515c4db2bff0235a38d
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Mon Oct 13 15:33:39 2014 +0200
Save email message a task is created from as relation (#3439); display the reference in the task details and edit dialogs
diff --git a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
index 817cfdf..e44b2c6 100644
--- a/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
+++ b/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
@@ -820,6 +820,59 @@ class tasklist_kolab_driver extends tasklist_driver
}
/**
+ * Find messages linked with a task record
+ */
+ private function get_links($uid)
+ {
+ $config = kolab_storage_config::get_instance();
+ return array_map(array($this, '_convert_message_uri'), $config->get_object_links($uid));
+ }
+
+ /**
+ *
+ */
+ private function save_links($uid, $links)
+ {
+ // make sure we have a valid array
+ if (empty($links)) {
+ $links = array();
+ }
+
+ // convert the given (simplified) message links into absolute IMAP URIs
+ $links = array_map(function($link) {
+ $url = parse_url(substr($link, 8));
+ parse_str($url['query'], $linkref);
+
+ $path = explode('/', $url['path']);
+ $linkref['uid'] = array_pop($path);
+ $linkref['folder'] = join('/', array_map('rawurldecode', $path));
+
+ return kolab_storage_config::build_member_url($linkref);
+ }, $links);
+
+ $config = kolab_storage_config::get_instance();
+ $remove = array_diff($config->get_object_links($uid), $links);
+ return $config->save_object_links($uid, $links, $remove);
+ }
+
+ /**
+ * Simplify the given message URI by converting the mailbox
+ * part into a relative IMAP path valid for the current user.
+ */
+ protected function _convert_message_uri($uri)
+ {
+ if (strpos($uri, 'imap:///') === 0) {
+ $linkref = kolab_storage_config::parse_member_url($uri);
+
+ return 'imap:///' . implode('/', array_map('rawurlencode', explode('/', $linkref['folder']))) .
+ '/' . $linkref['uid'] .
+ '?' . http_build_query($linkref['params'], '', '&');
+ }
+
+ return $uri;
+ }
+
+ /**
* Convert from Kolab_Format to internal representation
*/
private function _to_rcube_task($record)
@@ -839,6 +892,7 @@ class tasklist_kolab_driver extends tasklist_driver
'organizer' => $record['organizer'],
'sequence' => $record['sequence'],
'tags' => $record['tags'],
+ 'links' => $this->get_links($record['uid']),
);
// convert from DateTime to internal date format
@@ -1013,9 +1067,10 @@ class tasklist_kolab_driver extends tasklist_driver
if (!$list_id || !($folder = $this->get_folder($list_id)))
return false;
- // tags are stored separately
+ // email links and tags are stored separately
+ $links = $task['links'];
$tags = $task['tags'];
- unset($task['tags']);
+ unset($task['tags'], $task['links']);
// moved from another folder
if ($task['_fromlist'] && ($fromfolder = $this->get_folder($task['_fromlist']))) {
@@ -1049,6 +1104,8 @@ class tasklist_kolab_driver extends tasklist_driver
$saved = false;
}
else {
+ // save links in configuration.relation object
+ $this->save_links($object['uid'], $links);
// save tags in configuration.relation object
$this->save_tags($object['uid'], $tags);
@@ -1170,6 +1227,17 @@ class tasklist_kolab_driver extends tasklist_driver
}
/**
+ * Build a URI representing the given message reference
+ *
+ * @see tasklist_driver::get_message_uri()
+ */
+ public function get_message_uri($headers, $folder)
+ {
+ $uri = kolab_storage_config::get_message_uri($headers, $folder);
+ return $this->_convert_message_uri($uri);
+ }
+
+ /**
*
*/
public function tasklist_edit_form($action, $list, $fieldprop)
diff --git a/plugins/tasklist/drivers/tasklist_driver.php b/plugins/tasklist/drivers/tasklist_driver.php
index cdaa76b..2102d21 100644
--- a/plugins/tasklist/drivers/tasklist_driver.php
+++ b/plugins/tasklist/drivers/tasklist_driver.php
@@ -288,6 +288,20 @@ abstract class tasklist_driver
public function get_attachment_body($id, $task) { }
/**
+ * Build a URI representing the given message reference
+ *
+ * @param object rcube_message_header Instance holding the message headers
+ * @param string IMAP folder the message resides in
+ *
+ * @return string An URI referencing the given IMAP message
+ */
+ public function get_message_uri($headers, $folder)
+ {
+ // to be implemented by the derived classes
+ return false;
+ }
+
+ /**
* Helper method to determine whether the given task is considered "complete"
*
* @param array $task Hash array with event properties:
diff --git a/plugins/tasklist/localization/en_US.inc b/plugins/tasklist/localization/en_US.inc
index 7275995..4563999 100644
--- a/plugins/tasklist/localization/en_US.inc
+++ b/plugins/tasklist/localization/en_US.inc
@@ -37,6 +37,7 @@ $labels['start'] = 'Start';
$labels['starttime'] = 'Start time';
$labels['alarms'] = 'Reminder';
$labels['repeat'] = 'Repeat';
+$labels['links'] = 'References';
$labels['status'] = 'Status';
$labels['status-needs-action'] = 'Needs action';
$labels['status-in-process'] = 'In process';
@@ -61,6 +62,7 @@ $labels['mytasks'] = 'My tasks';
$labels['mytaskstitle'] = 'Tasks assigned to you';
$labels['nodate'] = 'no date';
$labels['removetag'] = 'Remove';
+$labels['removelink'] = 'Remove email reference';
$labels['auto'] = 'Auto';
$labels['taskdetails'] = 'Details';
diff --git a/plugins/tasklist/skins/larry/sprites.png b/plugins/tasklist/skins/larry/sprites.png
index 7a9c89f..3552b00 100644
Binary files a/plugins/tasklist/skins/larry/sprites.png and b/plugins/tasklist/skins/larry/sprites.png differ
diff --git a/plugins/tasklist/skins/larry/tasklist.css b/plugins/tasklist/skins/larry/tasklist.css
index aafc9e8..bf53e6b 100644
--- a/plugins/tasklist/skins/larry/tasklist.css
+++ b/plugins/tasklist/skins/larry/tasklist.css
@@ -1083,6 +1083,56 @@ label.block {
-o-box-shadow: 0 0 5px 2px rgba(71,135,177, 0.9);
}
+#task-links {
+ margin-top: 0;
+ margin-bottom: 0.2em;
+}
+
+#task-links label {
+ vertical-align: top;
+ margin-top: 0.3em;
+}
+
+#task-links .attachmentslist {
+ display: inline-block;
+}
+
+#task-links .attachmentslist li {
+ display: inline-block;
+ margin-right: 1em;
+}
+
+#taskedit-links .attachmentslist li.message.eml,
+#task-links .attachmentslist li.message.eml {
+ background-image: url(sprites.png);
+ background-position: -2px -388px;
+}
+
+#taskedit-links .attachmentslist li.message a.messagelink,
+#task-links .attachmentslist li.message a.messagelink {
+ padding: 0 0 0 24px;
+}
+
+#taskedit-links .attachmentslist li.deleted a.messagelink,
+#taskedit-links .attachmentslist li.deleted a.messagelink:hover {
+ text-decoration: line-through;
+}
+
+#taskedit-links label {
+ float: left;
+ margin-top: 0.3em;
+}
+
+#taskedit-links .task-text {
+ margin-left: 8em;
+ min-height: 22px;
+}
+
+#taskedit-links .attachmentslist li a.delete {
+ top: 0;
+ background-position: -6px -378px;
+}
+
#task-attachments .attachmentslist li {
float: left;
margin-right: 1em;
diff --git a/plugins/tasklist/skins/larry/templates/mainview.html b/plugins/tasklist/skins/larry/templates/mainview.html
index f3fd595..4d3b9c1 100644
--- a/plugins/tasklist/skins/larry/templates/mainview.html
+++ b/plugins/tasklist/skins/larry/templates/mainview.html
@@ -211,6 +211,10 @@
<label><roundcube:label name="tasklist.status" /></label>
<span class="task-text"></span>
</div>
+ <div id="task-links" class="form-section">
+ <label><roundcube:label name="tasklist.links" /></label>
+ <span class="task-text"></span>
+ </div>
<div id="task-attachments" class="form-section">
<label><roundcube:label name="attachments" /></label>
<div class="task-text"></div>
diff --git a/plugins/tasklist/skins/larry/templates/taskedit.html b/plugins/tasklist/skins/larry/templates/taskedit.html
index e44c5d8..8155668 100644
--- a/plugins/tasklist/skins/larry/templates/taskedit.html
+++ b/plugins/tasklist/skins/larry/templates/taskedit.html
@@ -54,6 +54,11 @@
<label for="taskedit-tasklist"><roundcube:label name="tasklist.list" /></label>
<roundcube:object name="plugin.tasklist_select" id="taskedit-tasklist" />
</div>
+ <div class="form-section" id="taskedit-links">
+ <label><roundcube:label name="tasklist.links" /></label>
+ <div class="task-text"></div>
+ <br style="clear:left">
+ </div>
</div>
<!-- recurrence settings -->
<div id="taskedit-panel-recurrence">
diff --git a/plugins/tasklist/tasklist.js b/plugins/tasklist/tasklist.js
index 8a92887..3cadd57 100644
--- a/plugins/tasklist/tasklist.js
+++ b/plugins/tasklist/tasklist.js
@@ -558,6 +558,12 @@ function rcube_tasklist_ui(settings)
}
});
+ // register click handler for message links
+ $('#task-links, #taskedit-links').on('click', 'li a.messagelink', function(e) {
+ rcmail.open_window(this.href);
+ return false;
+ });
+
// handle global document clicks: close popup menus
$(document.body).click(clear_popups);
@@ -1778,6 +1784,13 @@ function rcube_tasklist_ui(settings)
}
}
+ // build attachments list
+ $('#task-links').hide();
+ if ($.isArray(rec.links) && rec.links.length) {
+ task_show_links(rec.links || [], $('#task-links').children('.task-text'));
+ $('#task-links').show();
+ }
+
// list task attendees
if (list.attendees && rec.attendees) {
/*
@@ -1984,6 +1997,14 @@ function rcube_tasklist_ui(settings)
// set alarm(s)
me.set_alarms_edit('#taskedit-alarms', action != 'new' && rec.valarms ? rec.valarms : []);
+ if ($.isArray(rec.links) && rec.links.length) {
+ task_show_links(rec.links, $('#taskedit-links .task-text'), true);
+ $('#taskedit-links').show();
+ }
+ else {
+ $('#taskedit-links').hide();
+ }
+
// set recurrence
me.set_recurrence_edit(rec);
@@ -2271,6 +2292,53 @@ function rcube_tasklist_ui(settings)
/**
*
*/
+ function task_show_links(links, container, edit)
+ {
+ var dellink, ul = $('<ul>').addClass('attachmentslist');
+
+ $.each(links, function(i, link) {
+ var li = $('<li>').addClass('link')
+ .addClass('message eml')
+ .append($('<a>')
+ .attr('href', link.mailurl)
+ .addClass('messagelink')
+ .text(link.subject || link.uri)
+ )
+ .appendTo(ul);
+
+ // add icon to remove the link
+ if (edit) {
+ $('<a>')
+ .attr('href', '#delete')
+ .attr('title', rcmail.gettext('removelink','tasklist'))
+ .addClass('delete')
+ .text(rcmail.gettext('delete'))
+ .click({ uri:link.uri }, function(e) {
+ remove_link(this, e.data.uri);
+ return false;
+ })
+ .appendTo(li);
+ }
+ });
+
+ container.empty().append(ul);
+ }
+
+ /**
+ *
+ */
+ function remove_link(elem, uri)
+ {
+ // remove the link item matching the given uri
+ me.selected_task.links = $.grep(me.selected_task.links, function(link) { return link.uri != uri; });
+
+ // remove UI list item
+ $(elem).hide().closest('li').addClass('deleted');
+ }
+
+ /**
+ *
+ */
function add_childtask(id)
{
if (rcmail.busy)
diff --git a/plugins/tasklist/tasklist.php b/plugins/tasklist/tasklist.php
index 5824527..9acded6 100644
--- a/plugins/tasklist/tasklist.php
+++ b/plugins/tasklist/tasklist.php
@@ -564,6 +564,11 @@ class tasklist extends rcube_plugin
$rec['attachments'] = $attachments;
+ // convert link references into simple URIs
+ if (array_key_exists('links', $rec)) {
+ $rec['links'] = array_map(function($link) { return is_array($link) ? $link['uri'] : strval($link); }, (array)$rec['links']);
+ }
+
// convert invalid data
if (isset($rec['attendees']) && !is_array($rec['attendees']))
$rec['attendees'] = array();
@@ -1045,6 +1050,15 @@ class tasklist extends rcube_plugin
$rec['attachments'][$k]['classname'] = rcube_utils::file2class($attachment['mimetype'], $attachment['name']);
}
+ // convert link URIs references into structs
+ if (array_key_exists('links', $rec)) {
+ foreach ((array)$rec['links'] as $i => $link) {
+ if (strpos($link, 'imap://') === 0) {
+ $rec['links'][$i] = $this->get_message_reference($link);
+ }
+ }
+ }
+
if (!is_array($rec['tags']))
$rec['tags'] = (array)$rec['tags'];
sort($rec['tags'], SORT_LOCALE_STRING);
@@ -1163,7 +1177,7 @@ class tasklist extends rcube_plugin
$this->rc->output->set_env('autocomplete_threads', (int)$this->rc->config->get('autocomplete_threads', 0));
$this->rc->output->set_env('autocomplete_max', (int)$this->rc->config->get('autocomplete_max', 15));
$this->rc->output->set_env('autocomplete_min_length', $this->rc->config->get('autocomplete_min_length'));
- $this->rc->output->add_label('autocompletechars', 'autocompletemore', 'libcalendaring.expandattendeegroup', 'libcalendaring.expandattendeegroupnodata');
+ $this->rc->output->add_label('autocompletechars', 'autocompletemore', 'delete', 'libcalendaring.expandattendeegroup', 'libcalendaring.expandattendeegroupnodata');
$this->rc->output->set_pagetitle($this->gettext('navtitle'));
$this->rc->output->send('tasklist.mainview');
@@ -1335,8 +1349,12 @@ class tasklist extends rcube_plugin
$this->load_driver();
+ // add a reference to the email message
+ if ($msguri = $this->driver->get_message_uri($message->headers, $mbox)) {
+ $task['links'] = array($this->get_message_reference($msguri));
+ }
// copy mail attachments to task
- if ($message->attachments && $this->driver->attachments) {
+ else if ($message->attachments && $this->driver->attachments) {
if (!is_array($_SESSION[self::SESSION_KEY]) || $_SESSION[self::SESSION_KEY]['id'] != $task['id']) {
$_SESSION[self::SESSION_KEY] = array();
$_SESSION[self::SESSION_KEY]['id'] = $task['id'];
@@ -1489,6 +1507,45 @@ class tasklist extends rcube_plugin
}
/**
+ * Resolve the email message reference from the given URI
+ */
+ public function get_message_reference($uri, $resolve = false)
+ {
+ if (strpos($uri, 'imap:///') === 0) {
+ $url = parse_url(substr($uri, 8));
+ parse_str($url['query'], $params);
+
+ $path = explode('/', $url['path']);
+ $uid = array_pop($path);
+ $folder = join('/', array_map('rawurldecode', $path));
+ }
+
+ if ($folder && $uid) {
+ // TODO: check if folder/uid still references an existing message
+ // TODO: validate message or resovle the new URI using the message-id parameter
+
+ $linkref = array(
+ 'folder' => $folder,
+ 'uid' => $uid,
+ 'subject' => $params['subject'],
+ 'uri' => $uri,
+ 'mailurl' => $this->rc->url(array(
+ 'task' => 'mail',
+ 'action' => 'show',
+ 'mbox' => $folder,
+ 'uid' => $uid,
+ 'rel' => 'task',
+ ))
+ );
+ }
+ else {
+ $linkref = array();
+ }
+
+ return $linkref;
+ }
+
+ /**
* Import the full payload from a mail message attachment
*/
public function mail_import_attachment()
commit ef7f457c025545df77996f948398d52544b11b26
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Mon Oct 13 14:55:50 2014 +0200
Bugfixes for recent refactoring
diff --git a/plugins/libkolab/lib/kolab_storage_config.php b/plugins/libkolab/lib/kolab_storage_config.php
index 22fb90c..915e25c 100644
--- a/plugins/libkolab/lib/kolab_storage_config.php
+++ b/plugins/libkolab/lib/kolab_storage_config.php
@@ -722,7 +722,7 @@ class kolab_storage_config
}
// create a new relation
- if (!$done) {
+ if (!$done && !empty($links)) {
$relation = array(
'members' => array_merge($links, array($object_uri)),
'category' => 'generic',
@@ -775,7 +775,7 @@ class kolab_storage_config
// derive message identifier from URI
$member_id = md5($uri);
}
- array('member', '=', $member_id);
+ $filter[] = array('member', '=', $member_id);
// get UIDs of assigned notes
foreach ($this->get_objects($filter, $default) as $relation) {
commit 6f0ef60f7a15162bdb7052c73bbb2fd515ae773c
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Mon Oct 13 14:48:59 2014 +0200
Add fall-back to the full uri for searching relations in cache
diff --git a/plugins/libkolab/lib/kolab_format_configuration.php b/plugins/libkolab/lib/kolab_format_configuration.php
index 17b46a7..4506ed3 100644
--- a/plugins/libkolab/lib/kolab_format_configuration.php
+++ b/plugins/libkolab/lib/kolab_format_configuration.php
@@ -241,6 +241,10 @@ class kolab_format_configuration extends kolab_format
else if (!empty($member['params']['message-id'])) {
$words[] = $member['params']['message-id'];
}
+ else {
+ // derive message identifier from URI
+ $words[] = md5($url);
+ }
}
return $words;
diff --git a/plugins/libkolab/lib/kolab_storage_config.php b/plugins/libkolab/lib/kolab_storage_config.php
index e04ccd6..22fb90c 100644
--- a/plugins/libkolab/lib/kolab_storage_config.php
+++ b/plugins/libkolab/lib/kolab_storage_config.php
@@ -351,6 +351,8 @@ class kolab_storage_config
'params' => $params,
);
}
+
+ return false;
}
/**
@@ -765,10 +767,16 @@ class kolab_storage_config
$filter = array(
array('type', '=', 'relation'),
array('category', '=', 'generic'),
- // @TODO: what if Message-Id (and Date) does not exist?
- array('member', '=', $message->get('message-id', false)),
);
+ // query by message-id
+ $member_id = $message->get('message-id', false);
+ if (empty($member_id)) {
+ // derive message identifier from URI
+ $member_id = md5($uri);
+ }
+ array('member', '=', $member_id);
+
// get UIDs of assigned notes
foreach ($this->get_objects($filter, $default) as $relation) {
// we don't need to update members if the URI is found
commit 63b69871fee37777f03e17a916501f1e13f3f028
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Mon Oct 13 13:55:45 2014 +0200
Fix typo
diff --git a/plugins/libkolab/lib/kolab_storage_config.php b/plugins/libkolab/lib/kolab_storage_config.php
index 35d0d62..e04ccd6 100644
--- a/plugins/libkolab/lib/kolab_storage_config.php
+++ b/plugins/libkolab/lib/kolab_storage_config.php
@@ -699,7 +699,7 @@ class kolab_storage_config
// make sure the object_uri is still a member
if (!in_array($object_uri, $members)) {
- $members[$obejct_uri];
+ $members[$object_uri];
}
// remove relation if no other members remain
commit a807768c329badbbc3559959acf7a38ca430cab0
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Mon Oct 13 12:38:57 2014 +0200
Move email link/relation handling functions to libkolab for common use
diff --git a/plugins/kolab_notes/kolab_notes.php b/plugins/kolab_notes/kolab_notes.php
index 259f26d..369f1c5 100644
--- a/plugins/kolab_notes/kolab_notes.php
+++ b/plugins/kolab_notes/kolab_notes.php
@@ -998,46 +998,9 @@ class kolab_notes extends rcube_plugin
private function save_links($uid, $links)
{
- $config = kolab_storage_config::get_instance();
- $search = kolab_storage_config::build_member_url($uid);
- $relations = $this->get_relations($uid);
-
- // @TODO: here we support only one-way relations, i.e.
- // such relation can contain only note and mail members
- // So, when we remove a note member the whole relation
- // will be removed
-
- foreach ($relations as $relation) {
- if (empty($links)) {
- $config->delete($relation['uid']);
- }
- else {
- // make relation members up-to-date
- kolab_storage_config::resolve_members($relation);
-
- // assign all links to one relation, others will be removed
- $members = array_merge($links, array($search));
- $diff1 = array_diff($members, $relation['members']);
- $diff1 = array_diff($relation['members'], $members);
-
- if (count($diff1) || count($diff2)) {
- $relation['members'] = $members;
- $config->save($relation, 'relation');
- }
-
- $links = null;
- }
- }
-
- // create a new relation
- if (!empty($links)) {
- $relation = array(
- 'members' => array_merge($links, array($search)),
- 'category' => 'generic',
- );
-
- $config->save($relation, 'relation');
- }
+ $config = kolab_storage_config::get_instance();
+ $remove = array_diff($config->get_object_links($uid), $links);
+ return $config->save_object_links($uid, $links, $remove);
}
/**
@@ -1045,23 +1008,8 @@ class kolab_notes extends rcube_plugin
*/
private function get_links($uid)
{
- $result = array();
- $search = kolab_storage_config::build_member_url($uid);
-
- foreach ($this->get_relations($uid) as $relation) {
- if (in_array($search, (array) $relation['members'])) {
- // make relation members up-to-date
- kolab_storage_config::resolve_members($relation);
-
- foreach ($relation['members'] as $member) {
- if ($member != $search) {
- $result[] = $member;
- }
- }
- }
- }
-
- return array_unique($result);
+ $config = kolab_storage_config::get_instance();
+ return $config->get_object_links($uid);
}
/**
@@ -1092,22 +1040,6 @@ class kolab_notes extends rcube_plugin
}
/**
- * Find relation objects referring to specified note
- */
- private function get_relations($uid)
- {
- $config = kolab_storage_config::get_instance();
- $default = true;
- $filter = array(
- array('type', '=', 'relation'),
- array('category', '=', 'generic'),
- array('member', '=', $uid),
- );
-
- return $config->get_objects($filter, $default, 100);
- }
-
- /**
* Resolve the email message reference from the given URI
*/
public function get_message_reference($uri, $resolve = false)
diff --git a/plugins/libkolab/lib/kolab_storage_config.php b/plugins/libkolab/lib/kolab_storage_config.php
index 8a0fab5..35d0d62 100644
--- a/plugins/libkolab/lib/kolab_storage_config.php
+++ b/plugins/libkolab/lib/kolab_storage_config.php
@@ -654,6 +654,100 @@ class kolab_storage_config
}
/**
+ * Find objects linked with the given groupware object through a relation
+ *
+ * @param string Object UUID
+ * @param array List of related URIs
+ */
+ public function get_object_links($uid)
+ {
+ $links = array();
+ $object_uri = self::build_member_url($uid);
+
+ foreach ($this->get_relations_for_member($uid) as $relation) {
+ if (in_array($object_uri, (array) $relation['members'])) {
+ // make relation members up-to-date
+ kolab_storage_config::resolve_members($relation);
+
+ foreach ($relation['members'] as $member) {
+ if ($member != $object_uri) {
+ $links[] = $member;
+ }
+ }
+ }
+ }
+
+ return array_unique($links);
+ }
+
+ /**
+ *
+ */
+ public function save_object_links($uid, $links, $remove = array())
+ {
+ $object_uri = self::build_member_url($uid);
+ $relations = $this->get_relations_for_member($uid);
+ $done = false;
+
+ foreach ($relations as $relation) {
+ // make relation members up-to-date
+ kolab_storage_config::resolve_members($relation);
+
+ // remove and add links
+ $members = array_diff($relation['members'], (array)$remove);
+ $members = array_unique(array_merge($members, $links));
+
+ // make sure the object_uri is still a member
+ if (!in_array($object_uri, $members)) {
+ $members[$obejct_uri];
+ }
+
+ // remove relation if no other members remain
+ if (count($members) <= 1) {
+ $done = $this->delete($relation['uid']);
+ }
+ // update relation object if members changed
+ else if (count(array_diff($members, $relation['members'])) || count(array_diff($relation['members'], $members))) {
+ $relation['members'] = $members;
+ $done = $this->save($relation, 'relation');
+ $links = array();
+ }
+ // no changes, we're happy
+ else {
+ $done = true;
+ $links = array();
+ }
+ }
+
+ // create a new relation
+ if (!$done) {
+ $relation = array(
+ 'members' => array_merge($links, array($object_uri)),
+ 'category' => 'generic',
+ );
+
+ $ret = $this->save($relation, 'relation');
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Find relation objects referring to specified note
+ */
+ public function get_relations_for_member($uid, $reltype = 'generic')
+ {
+ $default = true;
+ $filter = array(
+ array('type', '=', 'relation'),
+ array('category', '=', $reltype),
+ array('member', '=', $uid),
+ );
+
+ return $this->get_objects($filter, $default, 100);
+ }
+
+ /**
* Find kolab objects assigned to specified e-mail message
*
* @param rcube_message $message E-mail message
More information about the commits
mailing list