4 commits - plugins/kolab_notes plugins/libkolab
Thomas Brüderli
bruederli at kolabsys.com
Tue Apr 15 09:46:06 CEST 2014
plugins/kolab_notes/kolab_notes.php | 170 +++++++++++++++++--
plugins/kolab_notes/localization/en_US.inc | 3
plugins/kolab_notes/notes.js | 85 +++++----
plugins/kolab_notes/skins/larry/notes.css | 56 +++++-
plugins/kolab_notes/skins/larry/sprites.png |binary
plugins/kolab_notes/skins/larry/templates/notes.html | 10 +
plugins/libkolab/lib/kolab_format.php | 37 ++--
plugins/libkolab/lib/kolab_format_note.php | 11 +
plugins/libkolab/lib/kolab_storage.php | 27 +++
9 files changed, 335 insertions(+), 64 deletions(-)
New commits:
commit ee269df7ae566bfefbb4b6934abf74a7aaee2f6e
Merge: f0ecee1 1a6f7e8
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Mon Apr 14 18:25:53 2014 +0200
Merge branch 'master' of ssh://git.kolab.org/git/roundcubemail-plugins-kolab
commit f0ecee1e5851ecd027b3ffb959cc6b9de3a056f0
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Mon Apr 14 18:25:23 2014 +0200
Implement full notes display and editing from mail view
diff --git a/plugins/kolab_notes/kolab_notes.php b/plugins/kolab_notes/kolab_notes.php
index 3be3ab9..2c47855 100644
--- a/plugins/kolab_notes/kolab_notes.php
+++ b/plugins/kolab_notes/kolab_notes.php
@@ -34,6 +34,7 @@ class kolab_notes extends rcube_plugin
private $lists;
private $folders;
private $cache = array();
+ private $message_notes = array();
/**
* Required startup method of a Roundcube plugin
@@ -68,6 +69,8 @@ class kolab_notes extends rcube_plugin
$this->rc->load_language($_SESSION['language'], array('notes.notes' => $this->gettext('navtitle'))); // add label for task title
if ($args['task'] == 'notes') {
+ $this->add_hook('storage_init', array($this, 'storage_init'));
+
// register task actions
$this->register_action('index', array($this, 'notes_view'));
$this->register_action('fetch', array($this, 'notes_fetch'));
@@ -77,6 +80,8 @@ class kolab_notes extends rcube_plugin
$this->register_action('dialog-ui', array($this, 'dialog_view'));
}
else if ($args['task'] == 'mail') {
+ $this->add_hook('storage_init', array($this, 'storage_init'));
+ $this->add_hook('message_load', array($this, 'mail_message_load'));
$this->add_hook('message_compose', array($this, 'mail_message_compose'));
$this->add_hook('template_object_messagebody', array($this, 'mail_messagebody_html'));
@@ -93,19 +98,36 @@ class kolab_notes extends rcube_plugin
))),
'messagemenu');
- $this->api->output->add_label('kolab_notes.appendnote', 'save', 'cancel');
+ $this->api->output->add_label('kolab_notes.appendnote', 'kolab_notes.editnote', 'kolab_notes.deletenotesconfirm', 'kolab_notes.entertitle', 'save', 'delete', 'cancel', 'close');
$this->include_script('notes_mail.js');
}
}
if (!$this->rc->output->ajax_call && (!$this->rc->output->env['framed'] || in_array($args['action'], array('folder-acl','dialog-ui')))) {
- require_once($this->home . '/kolab_notes_ui.php');
- $this->ui = new kolab_notes_ui($this);
- $this->ui->init();
+ $this->load_ui();
}
}
/**
+ * Hook into IMAP FETCH HEADER.FIELDS command and request MESSAGE-ID
+ */
+ public function storage_init($p)
+ {
+ $p['fetch_headers'] = trim($p['fetch_headers'] . ' MESSAGE-ID');
+ return $p;
+ }
+
+ /**
+ * Load and initialize UI class
+ */
+ private function load_ui()
+ {
+ require_once($this->home . '/kolab_notes_ui.php');
+ $this->ui = new kolab_notes_ui($this);
+ $this->ui->init();
+ }
+
+ /**
* Read available calendars for the current user and store them internally
*/
private function _read_lists($force = false)
@@ -205,8 +227,8 @@ class kolab_notes extends rcube_plugin
// attempt to create a default folder for this user
if (empty($this->lists)) {
- #if ($this->create_list(array('name' => 'Tasks', 'color' => '0000CC', 'default' => true)))
- # $this->_read_lists(true);
+ $folder = kolab_storage::folder_update(array('name' => 'Notes', 'type' => 'note', 'default' => true, 'subscribed' => true));
+ $this->_read_lists(true);
}
return $this->lists;
@@ -234,10 +256,10 @@ class kolab_notes extends rcube_plugin
// resolve message reference
if ($msgref = rcube_utils::get_input_value('_msg', RCUBE_INPUT_GPC, true)) {
$storage = $this->rc->get_storage();
- $storage->set_options(array('all_headers' => true));
list($uid, $folder) = explode('-', $msgref, 2);
if ($message = $storage->get_message_headers($msgref)) {
$this->rc->output->set_env('kolab_notes_template', array(
+ '_from_mail' => true,
'title' => $message->get('subject'),
'links' => array(array(
'uri' => $this->get_message_uri($message, $folder),
@@ -346,7 +368,7 @@ class kolab_notes extends rcube_plugin
// encode for client use
if (is_array($data)) {
- $this->_client_encode($data);
+ $this->_client_encode($data, true);
}
$this->rc->output->command('plugin.render_note', $data);
@@ -393,7 +415,7 @@ class kolab_notes extends rcube_plugin
/**
* Helper method to encode the given note record for use in the client
*/
- private function _client_encode(&$note)
+ private function _client_encode(&$note, $resolve = false)
{
foreach ($note as $key => $prop) {
if ($key[0] == '_' || $key == 'x-custom') {
@@ -413,6 +435,14 @@ class kolab_notes extends rcube_plugin
$note['html'] = $this->_wash_html($note['description']);
}
+ // resolve message links
+ if (is_array($note['links'])) {
+ $me = $this;
+ $note['links'] = array_map(function($link) use ($me, $resolve){
+ return $me->get_message_reference($link, $resolve) ?: array('uri' => $link);
+ }, $note['links']);
+ }
+
return $note;
}
@@ -680,11 +710,47 @@ class kolab_notes extends rcube_plugin
}
/**
- * Handler for 'messagebody_html' hooks
+ * Lookup backend storage and find notes tagged with the given message-ID
+ */
+ public function mail_message_load($p)
+ {
+ $this->message = $p['object'];
+ $this->message_notes = array();
+
+ // TODO: only query for notes if message was flagged with $KolabNotes ?
+
+ $message_id = trim($p['object']->headers->messageID, '<> ');
+ if ($message_id && $p['object']->uid) {
+ $query = array(array('tags','=','ref:' . $message_id));
+ foreach (kolab_storage::select($query, 'note') as $record) {
+ $record['list'] = kolab_storage::folder_id($record['_mailbox']);
+ $this->message_notes[] = $record;
+ }
+ }
+ }
+
+ /**
+ * Handler for 'messagebody_html' hook
*/
public function mail_messagebody_html($args)
{
-
+ $html = '';
+ foreach ($this->message_notes as $note) {
+ $html .= html::a(array(
+ 'href' => $this->rc->url(array('task' => 'notes', '_list' => $note['list'], '_id' => $note['uid'])),
+ 'class' => 'kolabnotesref',
+ 'rel' => $note['uid'] . '@' . $note['list'],
+ 'target' => '_blank',
+ ), Q($note['title']));
+ }
+
+ // prepend note links to message body
+ if ($html) {
+ $this->load_ui();
+ $args['content'] = html::div('kolabmessagenotes', $html) . $args['content'];
+ }
+
+ return $args;
}
/**
@@ -714,7 +780,7 @@ class kolab_notes extends rcube_plugin
'Subject' => $note['title'],
'Date' => $note['changed']->format('r'),
));
- console($note);
+
if ($this->is_html($note)) {
$message->setHTMLBody($note['description']);
@@ -735,9 +801,79 @@ class kolab_notes extends rcube_plugin
return $message->getMessage();
}
+ /**
+ * Build a URI representing the given message reference
+ */
private function get_message_uri($headers, $folder)
{
- return sprintf('imap://%s/%s#%s', $headers->folder ?: $folder, $headers->uid, urlencode($headers->messageID));
+ return sprintf('imap://%s/%s?message-id=%s&subject=%s',
+ $headers->folder ?: $folder,
+ $headers->uid,
+ urlencode($headers->messageID),
+ urlencode($headers->get('subject'))
+ );
+ }
+
+ /**
+ * Extract message reference components from the given URI
+ */
+ private function parse_message_uri($uri)
+ {
+ $url = parse_url($uri);
+ if ($url['scheme'] == 'imap') {
+ parse_str($url['query'], $param);
+ $linkref = array(
+ 'uri' => $uri,
+ 'message_id' => $param['message-id'] ?: urldecode($url['fragment']),
+ 'subject' => $param['subject'],
+ );
+
+ $path = explode('/', $url['host'] . $url['path']);
+ $linkref['msguid'] = array_pop($path);
+ $linkref['folder'] = join('/', $path);
+
+ return $linkref;
+ }
+
+ return false;
+ }
+
+ /**
+ * Resolve the email message reference from the given URI
+ */
+ public function get_message_reference($uri, $resolve = false)
+ {
+ if ($linkref = $this->parse_message_uri($uri)) {
+ // fetch message subject
+ if ($resolve || empty($linkref['subject'])) {
+ $imap = $this->rc->get_storage();
+ if (!($message = $imap->get_message_headers($linrkef['msguid'], $linkref['folder']))) {
+ // try to find message using the message_id fragment
+ $index = $imap->search_once($imap->list_folders_subscribed('', '*', 'mail', null, true), 'HEADER MESSAGE-ID ' . $linkref['message_id']);
+ if ($index->count()) {
+ $uid = reset($index->get());
+ $folder = $index->get_parameters('MAILBOX');
+ if ($message = $imap->get_message_headers($uid, $folder)) {
+ // replace metadata
+ $linkref['subject'] = $message->get('subject');
+ $linkref['msguid'] = $message->uid;
+ $linkref['folder'] = $message->folder;
+ $linkref['uri'] = $this->get_message_uri($message, $folder);
+ }
+ }
+ }
+ }
+
+ $linkref['mailurl'] = $this->rc->url(array(
+ 'task' => 'mail',
+ 'action' => 'show',
+ 'mbox' => $linkref['folder'],
+ 'uid' => $linkref['msguid'],
+ 'rel' => 'note',
+ ));
+ }
+
+ return $linkref;
}
/**
@@ -749,6 +885,14 @@ class kolab_notes extends rcube_plugin
// TODO: handle attachments
+ // convert link references into simple URIs
+ if (array_key_exists('links', $note)) {
+ $object['links'] = array_map(function($link){ return is_array($link) ? $link['uri'] : strval($link); }, $note['links']);
+ }
+ else {
+ $object['links'] = $old['links'];
+ }
+
// clean up HTML content
$object['description'] = $this->_wash_html($note['description']);
$is_html = true;
diff --git a/plugins/kolab_notes/localization/en_US.inc b/plugins/kolab_notes/localization/en_US.inc
index ccb737d..5e3d1bb 100644
--- a/plugins/kolab_notes/localization/en_US.inc
+++ b/plugins/kolab_notes/localization/en_US.inc
@@ -24,7 +24,8 @@ $labels['tabsharing'] = 'Sharing';
$labels['discard'] = 'Discard';
$labels['abort'] = 'Abort';
$labels['unsavedchanges'] = 'Unsaved Changes!';
-$labels['appendnote'] = 'Add a note';
+$labels['appendnote'] = 'Add a Note';
+$labels['editnote'] = 'Edit Note';
$labels['savein'] = 'Save in';
$labels['savingdata'] = 'Saving data...';
diff --git a/plugins/kolab_notes/notes.js b/plugins/kolab_notes/notes.js
index c05be5a..41dcac1 100644
--- a/plugins/kolab_notes/notes.js
+++ b/plugins/kolab_notes/notes.js
@@ -236,6 +236,7 @@ function rcube_kolab_notes_ui(settings)
function init_dialog()
{
rcmail.register_command('save', save_note, true);
+ rcmail.addEventListener('plugin.render_note', render_note);
rcmail.addEventListener('plugin.update_note', function(data){
data.id = rcmail.html_identifier_encode(data.uid);
notesdata[data.id] = data;
@@ -259,19 +260,24 @@ function rcube_kolab_notes_ui(settings)
}
init_editor();
- setTimeout(function(){
- me.selected_note = $.extend({
- list: me.selected_list,
- uid: null,
- title: rcmail.gettext('newnote','kolab_notes'),
- description: '',
- categories: [],
- created: rcmail.gettext('now', 'kolab_notes'),
- changed: rcmail.gettext('now', 'kolab_notes')
- }, rcmail.env.kolab_notes_template || {});
- render_note(me.selected_note);
-
- }, 100);
+ if (settings.selected_uid) {
+ me.selected_list = settings.selected_list;
+ edit_note(settings.selected_uid);
+ }
+ else {
+ setTimeout(function(){
+ me.selected_note = $.extend({
+ list: me.selected_list,
+ uid: null,
+ title: rcmail.gettext('newnote','kolab_notes'),
+ description: '',
+ categories: [],
+ created: rcmail.gettext('now', 'kolab_notes'),
+ changed: rcmail.gettext('now', 'kolab_notes')
+ }, rcmail.env.kolab_notes_template || {});
+ render_note(me.selected_note);
+ }, 100);
+ }
}
this.init_dialog = init_dialog;
@@ -319,16 +325,7 @@ function rcube_kolab_notes_ui(settings)
// register click handler for message links
$(rcmail.gui_objects.notesattachmentslist).on('click', 'li a.messagelink', function(){
- var uri = $(this).attr('rel');
- if (uri && uri.match(/imap:\/\/.+/)) {
- var path = uri.split('#')[0].substr(7).split('/'),
- uid = path.pop(),
- folder = path.join('/');
- if (folder && uid) {
- rcmail.open_window(rcmail.url('mail/show', { _mbox: folder, _uid: uid, _rel: 'note' }));
- }
- }
-
+ rcmail.open_window(this.href);
return false;
});
}
@@ -715,13 +712,14 @@ function rcube_kolab_notes_ui(settings)
return;
}
- var list = me.notebooks[data.list] || me.notebooks[me.selected_list];
+ var list = me.notebooks[data.list] || me.notebooks[me.selected_list] || {};
content = $('#notecontent').val(data.description),
readonly = data.readonly || !list.editable,
attachmentslist = $(rcmail.gui_objects.notesattachmentslist).html('');
$('.notetitle', rcmail.gui_objects.noteviewtitle).val(data.title).prop('disabled', readonly);
$('.dates .notecreated', rcmail.gui_objects.noteviewtitle).html(Q(data.created || ''));
$('.dates .notechanged', rcmail.gui_objects.noteviewtitle).html(Q(data.changed || ''));
+ $(rcmail.gui_objects.notebooks).filter('select').val(list.id);
if (data.created || data.changed) {
$('.dates', rcmail.gui_objects.noteviewtitle).show();
}
@@ -753,15 +751,24 @@ function rcube_kolab_notes_ui(settings)
if (data.links) {
$.each(data.links, function(i, link){
- $('<li>').addClass('link')
+ var li = $('<li>').addClass('link')
.addClass('message eml')
.append($('<a>')
- .attr('href', '#show')
- .attr('rel', link.uri)
+ .attr('href', link.mailurl)
.addClass('messagelink')
.html(Q(link.subject || link.message_id || link.uri))
)
.appendTo(attachmentslist);
+/*
+ if (!readonly && !data._from_mail) {
+ $('<a>')
+ .attr('href', '#delete')
+ .attr('title', rcmail.gettext('delete'))
+ .addClass('delete')
+ .html(rcmail.gettext('delete'))
+ .appendTo(li);
+ }
+*/
});
}
@@ -770,6 +777,9 @@ function rcube_kolab_notes_ui(settings)
.on('click', function(){ $('.tagline .placeholder').hide(); });
}
+ if (!data.list)
+ data.list = list.id;
+
me.selected_note = data;
me.selected_note.id = rcmail.html_identifier_encode(data.uid);
rcmail.enable_command('save', list.editable && !data.readonly);
@@ -781,7 +791,7 @@ function rcube_kolab_notes_ui(settings)
html = text2html(html);
}
- var node, editor = tinyMCE.get('notecontent');
+ var node, editor = tinyMCE.get('notecontent'), is_html = false;
if (!readonly && editor) {
$(rcmail.gui_objects.notesdetailview).hide();
$(rcmail.gui_objects.noteseditform).show();
@@ -795,13 +805,17 @@ function rcube_kolab_notes_ui(settings)
$('.notetitle', rcmail.gui_objects.noteviewtitle).focus().select();
// read possibly re-formatted content back from editor for later comparison
- me.selected_note.description = editor.getContent({ format:'html' })
+ me.selected_note.description = editor.getContent({ format:'html' });
+ is_html = true;
}
else {
$(rcmail.gui_objects.noteseditform).hide();
$(rcmail.gui_objects.notesdetailview).html(html).show();
}
+ // notify subscribers
+ rcmail.triggerEvent('kolab_notes_render', { data:data, readonly:readonly, html:is_html });
+
// Trigger resize (needed for proper editor resizing)
$(window).resize();
}
@@ -1010,6 +1024,11 @@ function rcube_kolab_notes_ui(settings)
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;
+ }
+
// do some input validation
if (savedata.title == '') {
alert(rcmail.gettext('entertitle', 'kolab_notes'));
@@ -1032,11 +1051,12 @@ function rcube_kolab_notes_ui(settings)
*/
function get_save_data()
{
- var editor = tinyMCE.get('notecontent');
+ var editor = tinyMCE.get('notecontent'),
+ listselect = $('option:selected', rcmail.gui_objects.notebooks);
var savedata = {
title: trim($('.notetitle', rcmail.gui_objects.noteviewtitle).val()),
description: editor ? editor.getContent({ format:'html' }) : $('#notecontent').val(),
- list: me.selected_note.list || me.selected_list,
+ list: listselect.length ? listselect.val() : me.selected_note.list || me.selected_list,
uid: me.selected_note.uid,
categories: []
};
@@ -1068,7 +1088,8 @@ function rcube_kolab_notes_ui(settings)
return savedata.title != me.selected_note.title
|| savedata.description != me.selected_note.description
- || savedata.categories.join(',') != (me.selected_note.categories || []).join(',');
+ || savedata.categories.join(',') != (me.selected_note.categories || []).join(',')
+ || savedata.list != me.selected_note.list;
}
/**
diff --git a/plugins/kolab_notes/skins/larry/notes.css b/plugins/kolab_notes/skins/larry/notes.css
index 96d283b..96e962f 100644
--- a/plugins/kolab_notes/skins/larry/notes.css
+++ b/plugins/kolab_notes/skins/larry/notes.css
@@ -103,7 +103,7 @@
}
.notesview .toolbarmenu.iconized .selected span.icon {
- background: url(sprites.png) -5px -109px no-repeat;
+ background: url(sprites.png) -4px -110px no-repeat;
}
.notesview #notedetailsbox {
@@ -137,16 +137,18 @@
width: 100%;
}
-.notesdialog #noteform {
- bottom: 30px;
-}
-
.notesview #notedetails {
padding: 8px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
+ border-bottom: 1px solid #dfdfdf;
+}
+
+.notesdialog #noteform,
+.notesdialog #notedetails {
+ bottom: 30px;
}
.notesview #notedetails pre {
@@ -266,12 +268,16 @@
position: absolute;
left: 0;
right: 0;
- bottom: 0;
+ bottom: 41px;
height: 27px;
background: #fff;
padding-left: 10px;
}
+.notesdialog #notereferences {
+ bottom: 0;
+}
+
.notesview #notebooks li {
margin: 0;
height: 20px;
@@ -369,4 +375,42 @@
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
+}
+
+.notesview .attachmentslist li.message.eml {
+ display: inline-block;
+ background-image: url(sprites.png);
+ background-position: -6px -128px;
+ margin-right: 1em;
+}
+
+.notesview .attachmentslist li.message a.messagelink {
+ padding-left: 24px;
+}
+
+ul.toolbarmenu li .appendnote span.icon {
+ background-image: url(sprites.png);
+ background-position: -4px -170px;
+}
+
+div.kolabmessagenotes {
+ margin: 8px 8px;
+ padding: 4px 8px;
+ border: 1px solid #dfdfdf;
+ background: #fafafa;
+ border-radius: 4px;
+}
+
+div.kolabmessagenotes a.kolabnotesref {
+ display: inline-block;
+ color: #333;
+ font-weight: bold;
+ padding: 3px 15px 2px 22px;
+ text-shadow: 0px 1px 1px #fff;
+ text-decoration: none;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 12em;
+ background: url(sprites.png) -6px -151px no-repeat;
}
\ No newline at end of file
diff --git a/plugins/kolab_notes/skins/larry/sprites.png b/plugins/kolab_notes/skins/larry/sprites.png
index 184cef4..62aff65 100644
Binary files a/plugins/kolab_notes/skins/larry/sprites.png and b/plugins/kolab_notes/skins/larry/sprites.png differ
diff --git a/plugins/kolab_notes/skins/larry/templates/notes.html b/plugins/kolab_notes/skins/larry/templates/notes.html
index 75fa188..8f35b61 100644
--- a/plugins/kolab_notes/skins/larry/templates/notes.html
+++ b/plugins/kolab_notes/skins/larry/templates/notes.html
@@ -60,6 +60,9 @@
<roundcube:object name="plugin.notetitle" id="notedetailstitle" class="boxtitle" />
<roundcube:object name="plugin.editform" id="noteform" />
<roundcube:object name="plugin.detailview" id="notedetails" class="scroller" />
+ <div id="notereferences">
+ <roundcube:object name="plugin.attachments_list" id="attachment-list" class="attachmentslist" />
+ </div>
<div class="footerleft formbuttons">
<roundcube:button command="save" type="input" class="button mainaction" label="save" />
</div>
@@ -115,9 +118,16 @@ $(document).ready(function(e){
var form = $('#noteform, #notedetails'),
content = $('#notecontent'),
header = $('#notedetailstitle'),
+ footer = $('#notereferences'),
w, h;
+ if ($('#attachment-list li').length)
+ footer.show();
+ else
+ footer.hide();
+
form.css('top', header.outerHeight()+'px');
+ form.css('bottom', ((footer.is(':visible') ? footer.outerHeight()+4 : 0) + 41) + 'px');
w = form.outerWidth();
h = form.outerHeight();
commit e0bc40f16047ae908ca256b661f2532a7f83b831
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Mon Apr 14 18:25:04 2014 +0200
Allow to store email message references for note objects (link format tentative) + store message-id in cache for querying
diff --git a/plugins/libkolab/lib/kolab_format.php b/plugins/libkolab/lib/kolab_format.php
index 563fbc6..7c34310 100644
--- a/plugins/libkolab/lib/kolab_format.php
+++ b/plugins/libkolab/lib/kolab_format.php
@@ -502,6 +502,11 @@ abstract class kolab_format
return array();
}
+ /**
+ * Utility function to extract object attachment data
+ *
+ * @param array Hash array reference to append attachment data into
+ */
protected function get_attachments(&$object)
{
// handle attachments
@@ -520,13 +525,19 @@ abstract class kolab_format
'content' => $content,
);
}
- else if (substr($attach->uri(), 0, 4) == 'http') {
+ else if (in_array(substr($attach->uri(), 0, 4), array('http','imap'))) {
$object['links'][] = $attach->uri();
}
}
}
- protected function set_attachments($object)
+ /**
+ * Utility function to set attachment properties to the kolabformat object
+ *
+ * @param array Object data as hash array
+ * @param boolean True to always overwrite attachment information
+ */
+ protected function set_attachments($object, $write = true)
{
// save attachments
$vattach = new vectorattachment;
@@ -537,16 +548,17 @@ abstract class kolab_format
$attach->setLabel((string)$attr['name']);
$attach->setUri('cid:' . $cid, $attr['mimetype'] ?: 'application/octet-stream');
if ($attach->isValid()) {
- $vattach->push($attach);
+ $vattach->push($attach);
+ $write = true;
}
else {
- rcube::raise_error(array(
- 'code' => 660,
- 'type' => 'php',
- 'file' => __FILE__,
- 'line' => __LINE__,
- 'message' => "Invalid attributes for attachment $cid: " . var_export($attr, true),
- ), true);
+ rcube::raise_error(array(
+ 'code' => 660,
+ 'type' => 'php',
+ 'file' => __FILE__,
+ 'line' => __LINE__,
+ 'message' => "Invalid attributes for attachment $cid: " . var_export($attr, true),
+ ), true);
}
}
@@ -554,8 +566,11 @@ abstract class kolab_format
$attach = new Attachment;
$attach->setUri($link, 'unknown');
$vattach->push($attach);
+ $write = true;
}
- $this->obj->setAttachments($vattach);
+ if ($write) {
+ $this->obj->setAttachments($vattach);
+ }
}
}
diff --git a/plugins/libkolab/lib/kolab_format_note.php b/plugins/libkolab/lib/kolab_format_note.php
index 08b7735..bca5156 100644
--- a/plugins/libkolab/lib/kolab_format_note.php
+++ b/plugins/libkolab/lib/kolab_format_note.php
@@ -109,10 +109,19 @@ class kolab_format_note extends kolab_format
{
$tags = array();
- foreach ((array) $this->data['categories'] as $cat) {
+ foreach ((array)$this->data['categories'] as $cat) {
$tags[] = rcube_utils::normalize_string($cat);
}
+ // add tag for message references
+ foreach ((array)$this->data['links'] as $link) {
+ $url = parse_url($link);
+ if ($url['scheme'] == 'imap') {
+ parse_str($url['query'], $param);
+ $tags[] = 'ref:' . trim($param['message-id'] ?: urldecode($url['fragment']), '<> ');
+ }
+ }
+
return $tags;
}
commit e25fd88b73c512169ca60d885be0babebf7f3a07
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Mon Apr 14 18:21:19 2014 +0200
Provide static fuction to query for objects address kolab groupware folders
diff --git a/plugins/libkolab/lib/kolab_storage.php b/plugins/libkolab/lib/kolab_storage.php
index b5e529c..b7c981b 100644
--- a/plugins/libkolab/lib/kolab_storage.php
+++ b/plugins/libkolab/lib/kolab_storage.php
@@ -177,6 +177,33 @@ class kolab_storage
return false;
}
+ /**
+ * Execute cross-folder searches with the given query.
+ *
+ * @param array Pseudo-SQL query as list of filter parameter triplets
+ * @param string Object type (contact,event,task,journal,file,note,configuration)
+ * @return array List of Kolab data objects (each represented as hash array)
+ * @see kolab_storage_format::select()
+ */
+ public static function select($query, $type)
+ {
+ self::setup();
+ $folder = null;
+ $result = array();
+
+ foreach ((array)self::list_folders('', '*', $type) as $foldername) {
+ if (!$folder)
+ $folder = new kolab_storage_folder($foldername);
+ else
+ $folder->set_folder($foldername);
+
+ foreach ($folder->select($query, '*') as $object) {
+ $result[] = $object;
+ }
+ }
+
+ return $result;
+ }
/**
*
More information about the commits
mailing list