Store note tags in relation objects (#3395)
This commit is contained in:
parent
f554c20175
commit
26f71de1db
3 changed files with 208 additions and 40 deletions
|
@ -409,7 +409,13 @@ class kolab_notes extends rcube_plugin
|
|||
$list = rcube_utils::get_input_value('_list', RCUBE_INPUT_GPC);
|
||||
|
||||
$data = $this->notes_data($this->list_notes($list, $search), $tags);
|
||||
$this->rc->output->command('plugin.data_ready', array('list' => $list, 'search' => $search, 'data' => $data, 'tags' => array_values($tags)));
|
||||
|
||||
$this->rc->output->command('plugin.data_ready', array(
|
||||
'list' => $list,
|
||||
'search' => $search,
|
||||
'data' => $data,
|
||||
'tags' => array_values($tags)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -417,18 +423,14 @@ class kolab_notes extends rcube_plugin
|
|||
*/
|
||||
protected function notes_data($records, &$tags)
|
||||
{
|
||||
$tags = array();
|
||||
$config = kolab_storage_config::get_instance();
|
||||
$tags = $config->apply_tags($records);
|
||||
|
||||
foreach ($records as $i => $rec) {
|
||||
unset($records[$i]['description']);
|
||||
$this->_client_encode($records[$i]);
|
||||
|
||||
foreach ((array)$rec['categories'] as $tag) {
|
||||
$tags[] = $tag;
|
||||
}
|
||||
}
|
||||
|
||||
$tags = array_unique($tags);
|
||||
return $records;
|
||||
}
|
||||
|
||||
|
@ -460,8 +462,7 @@ class kolab_notes extends rcube_plugin
|
|||
$matches = 0;
|
||||
$contents = mb_strtolower(
|
||||
$record['title'] .
|
||||
($this->is_html($record) ? strip_tags($record['description']) : $record['description']) .
|
||||
join(' ', (array)$record['categories'])
|
||||
($this->is_html($record) ? strip_tags($record['description']) : $record['description'])
|
||||
);
|
||||
foreach ($words as $word) {
|
||||
if (mb_strpos($contents, $word) !== false) {
|
||||
|
@ -519,10 +520,12 @@ class kolab_notes extends rcube_plugin
|
|||
return $this->cache[$key];
|
||||
}
|
||||
|
||||
$result = false;
|
||||
|
||||
$this->_read_lists();
|
||||
if ($list_id) {
|
||||
if ($folder = $this->get_folder($list_id)) {
|
||||
return $folder->get_object($uid);
|
||||
$result = $folder->get_object($uid);
|
||||
}
|
||||
}
|
||||
// iterate over all calendar folders and search for the event ID
|
||||
|
@ -530,12 +533,17 @@ class kolab_notes extends rcube_plugin
|
|||
foreach ($this->folders as $list_id => $folder) {
|
||||
if ($result = $folder->get_object($uid)) {
|
||||
$result['list'] = $list_id;
|
||||
return $result;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
if ($result) {
|
||||
// get note tags
|
||||
$result['tags'] = $this->get_tags($result['uid']);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -665,9 +673,12 @@ class kolab_notes extends rcube_plugin
|
|||
// generate new note object from input
|
||||
$object = $this->_write_preprocess($note, $old);
|
||||
|
||||
// email links are handled separately
|
||||
// email links and tags are handled separately
|
||||
$links = $object['links'];
|
||||
$tags = $object['tags'];
|
||||
|
||||
unset($object['links']);
|
||||
unset($object['tags']);
|
||||
|
||||
$saved = $folder->save($object, 'note', $note['uid']);
|
||||
|
||||
|
@ -682,9 +693,12 @@ class kolab_notes extends rcube_plugin
|
|||
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);
|
||||
|
||||
$note = $object;
|
||||
$note['list'] = $list_id;
|
||||
$note['tags'] = (array) $tags;
|
||||
|
||||
// cache this in memory for later read
|
||||
$key = $list_id . ':' . $note['uid'];
|
||||
|
@ -700,6 +714,7 @@ class kolab_notes extends rcube_plugin
|
|||
function move_note($note, $list_id)
|
||||
{
|
||||
$this->_read_lists();
|
||||
|
||||
$tofolder = $this->get_folder($list_id);
|
||||
$fromfolder = $this->get_folder($note['list']);
|
||||
|
||||
|
@ -730,6 +745,7 @@ class kolab_notes extends rcube_plugin
|
|||
|
||||
if ($status) {
|
||||
$this->save_links($note['uid'], null);
|
||||
$this->save_tags($note['uid'], null);
|
||||
}
|
||||
|
||||
return $status;
|
||||
|
@ -1037,6 +1053,18 @@ class kolab_notes extends rcube_plugin
|
|||
return array_unique($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get note tags
|
||||
*/
|
||||
private function get_tags($uid)
|
||||
{
|
||||
$config = kolab_storage_config::get_instance();
|
||||
$tags = $config->get_tags($uid);
|
||||
$tags = array_map(function($v) { return $v['name']; }, $tags);
|
||||
|
||||
return $tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find notes assigned to specified message
|
||||
*/
|
||||
|
@ -1148,6 +1176,15 @@ class kolab_notes extends rcube_plugin
|
|||
return $linkref;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update note tags
|
||||
*/
|
||||
private function save_tags($uid, $tags)
|
||||
{
|
||||
$config = kolab_storage_config::get_instance();
|
||||
$config->save_tags($uid, $tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the given note data (submitted by the client) before saving it
|
||||
*/
|
||||
|
@ -1192,8 +1229,8 @@ class kolab_notes extends rcube_plugin
|
|||
}
|
||||
|
||||
// make list of categories unique
|
||||
if (is_array($object['categories'])) {
|
||||
$object['categories'] = array_unique(array_filter($object['categories']));
|
||||
if (is_array($object['tags'])) {
|
||||
$object['tags'] = array_unique(array_filter($object['tags']));
|
||||
}
|
||||
|
||||
unset($object['list'], $object['tempid'], $object['created'], $object['changed'], $object['created_'], $object['changed_']);
|
||||
|
|
|
@ -325,7 +325,7 @@ function rcube_kolab_notes_ui(settings)
|
|||
uid: null,
|
||||
title: rcmail.gettext('newnote','kolab_notes'),
|
||||
description: '',
|
||||
categories: [],
|
||||
tags: [],
|
||||
created: rcmail.gettext('now', 'kolab_notes'),
|
||||
changed: rcmail.gettext('now', 'kolab_notes')
|
||||
}, rcmail.env.kolab_notes_template || {});
|
||||
|
@ -417,7 +417,7 @@ function rcube_kolab_notes_ui(settings)
|
|||
uid: null,
|
||||
title: rcmail.gettext('newnote','kolab_notes'),
|
||||
description: '',
|
||||
categories: [],
|
||||
tags: [],
|
||||
created: rcmail.gettext('now', 'kolab_notes'),
|
||||
changed: rcmail.gettext('now', 'kolab_notes')
|
||||
}
|
||||
|
@ -687,9 +687,9 @@ function rcube_kolab_notes_ui(settings)
|
|||
for (var id in noteslist.rows) {
|
||||
tr = noteslist.rows[id].obj;
|
||||
note = notesdata[id];
|
||||
match = note.categories && note.categories.length;
|
||||
match = note.tags && note.tags.length;
|
||||
for (var i=0; match && note && i < tagsfilter.length; i++) {
|
||||
if ($.inArray(tagsfilter[i], note.categories) < 0)
|
||||
if ($.inArray(tagsfilter[i], note.tags) < 0)
|
||||
match = false;
|
||||
}
|
||||
|
||||
|
@ -787,7 +787,7 @@ function rcube_kolab_notes_ui(settings)
|
|||
|
||||
// tag-edit line
|
||||
var tagline = $('.tagline', rcmail.gui_objects.noteviewtitle).empty()[readonly?'addClass':'removeClass']('disabled').show();
|
||||
$.each(typeof data.categories == 'object' && data.categories.length ? data.categories : [''], function(i,val){
|
||||
$.each(typeof data.tags == 'object' && data.tags.length ? data.tags : [''], function(i,val) {
|
||||
$('<input>')
|
||||
.attr('name', 'tags[]')
|
||||
.attr('tabindex', '0')
|
||||
|
@ -796,7 +796,7 @@ function rcube_kolab_notes_ui(settings)
|
|||
.appendTo(tagline);
|
||||
});
|
||||
|
||||
if (!data.categories || !data.categories.length) {
|
||||
if (!data.tags || !data.tags.length) {
|
||||
$('<span>').addClass('placeholder')
|
||||
.html(rcmail.gettext('notags', 'kolab_notes'))
|
||||
.appendTo(tagline)
|
||||
|
@ -941,7 +941,7 @@ function rcube_kolab_notes_ui(settings)
|
|||
printwin.document.title = data.title;
|
||||
$('#notetitle', printwin.document).html(Q(data.title));
|
||||
$('#notebody', printwin.document).html(data.description);
|
||||
$('#notetags', printwin.document).html('<span class="tag">' + data.categories.join('</span><span class="tag">') + '</span>');
|
||||
$('#notetags', printwin.document).html('<span class="tag">' + data.tags.join('</span><span class="tag">') + '</span>');
|
||||
$('#notecreated', printwin.document).html(Q(me.selected_note.created));
|
||||
$('#notechanged', printwin.document).html(Q(me.selected_note.changed));
|
||||
printwin.print();
|
||||
|
@ -1026,8 +1026,8 @@ function rcube_kolab_notes_ui(settings)
|
|||
if (typeof counts == 'undefined') {
|
||||
counts = {};
|
||||
$.each(notesdata, function(id, rec){
|
||||
for (var t, j=0; rec && rec.categories && j < rec.categories.length; j++) {
|
||||
t = rec.categories[j];
|
||||
for (var t, j=0; rec && rec.tags && j < rec.tags.length; j++) {
|
||||
t = rec.tags[j];
|
||||
if (typeof counts[t] == 'undefined')
|
||||
counts[t] = 0;
|
||||
counts[t]++;
|
||||
|
@ -1064,10 +1064,10 @@ function rcube_kolab_notes_ui(settings)
|
|||
|
||||
if (is_new || me.selected_note && data.id == me.selected_note.id) {
|
||||
render_note(data);
|
||||
render_tagslist(data.categories || []);
|
||||
render_tagslist(data.tags || []);
|
||||
}
|
||||
else if (data.categories) {
|
||||
render_tagslist(data.categories);
|
||||
else if (data.tags) {
|
||||
render_tagslist(data.tags);
|
||||
}
|
||||
|
||||
// add list item on top
|
||||
|
@ -1153,18 +1153,18 @@ function rcube_kolab_notes_ui(settings)
|
|||
description: editor ? editor.getContent({ format:'html' }).replace(/^<p><\/p>/, '') : $('#notecontent').val(),
|
||||
list: listselect.length ? listselect.val() : me.selected_note.list || me.selected_list,
|
||||
uid: me.selected_note.uid,
|
||||
categories: []
|
||||
tags: []
|
||||
};
|
||||
|
||||
// collect tags
|
||||
$('.tagedit-list input[type="hidden"]', rcmail.gui_objects.noteviewtitle).each(function(i, elem){
|
||||
if (elem.value)
|
||||
savedata.categories.push(elem.value);
|
||||
savedata.tags.push(elem.value);
|
||||
});
|
||||
// including the "pending" one in the text box
|
||||
var newtag = $('#tagedit-input').val();
|
||||
if (newtag != '') {
|
||||
savedata.categories.push(newtag);
|
||||
savedata.tags.push(newtag);
|
||||
}
|
||||
|
||||
return savedata;
|
||||
|
@ -1183,7 +1183,7 @@ 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.tags.join(',') != (me.selected_note.tags || []).join(',')
|
||||
|| savedata.list != me.selected_note.list;
|
||||
}
|
||||
|
||||
|
@ -1367,7 +1367,7 @@ function rcube_kolab_notes_ui(settings)
|
|||
drop_rec = notesdata[drop_id];
|
||||
|
||||
// target already has this tag assigned
|
||||
if (!drop_rec || (drop_rec.categories && $.inArray(tag, drop_rec.categories) >= 0)) {
|
||||
if (!drop_rec || (drop_rec.tags && $.inArray(tag, drop_rec.tags) >= 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1387,9 +1387,9 @@ function rcube_kolab_notes_ui(settings)
|
|||
if (savedata.id) delete savedata.id;
|
||||
if (savedata.html) delete savedata.html;
|
||||
|
||||
if (!savedata.categories)
|
||||
savedata.categories = [];
|
||||
savedata.categories.push(tag);
|
||||
if (!savedata.tags)
|
||||
savedata.tags = [];
|
||||
savedata.tags.push(tag);
|
||||
|
||||
rcmail.lock_form(rcmail.gui_objects.noteseditform, true);
|
||||
saving_lock = rcmail.set_busy(true, 'kolab_notes.savingdata');
|
||||
|
|
|
@ -515,4 +515,135 @@ class kolab_storage_config
|
|||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign tags to kolab objects
|
||||
*
|
||||
* @param array $records List of kolab objects
|
||||
*
|
||||
* @return array List of tags
|
||||
*/
|
||||
public function apply_tags(&$records)
|
||||
{
|
||||
// first convert categories into tags
|
||||
foreach ($records as $i => $rec) {
|
||||
if (!empty($rec['categories'])) {
|
||||
$folder = new kolab_storage_folder($rec['_mailbox']);
|
||||
if ($object = $folder->get_object($rec['uid'])) {
|
||||
$tags = $rec['categories'];
|
||||
|
||||
unset($object['categories']);
|
||||
unset($records[$i]['categories']);
|
||||
|
||||
$this->save_tags($rec['uid'], $tags);
|
||||
$folder->save($object, $rec['_type'], $rec['uid']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$tags = array();
|
||||
|
||||
// assign tags to objects
|
||||
foreach ($this->get_tags() as $tag) {
|
||||
foreach ($records as $idx => $rec) {
|
||||
$uid = self::build_member_url($rec['uid']);
|
||||
if (in_array($uid, (array) $tag['members'])) {
|
||||
$records[$idx]['tags'][] = $tag['name'];
|
||||
}
|
||||
}
|
||||
|
||||
$tags[] = $tag['name'];
|
||||
}
|
||||
|
||||
$tags = array_unique($tags);
|
||||
|
||||
return $tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update object tags
|
||||
*
|
||||
* @param string $uid Kolab object UID
|
||||
* @param array $tags List of tag names
|
||||
*/
|
||||
public function save_tags($uid, $tags)
|
||||
{
|
||||
$url = self::build_member_url($uid);
|
||||
$relations = $this->get_tags();
|
||||
|
||||
foreach ($relations as $idx => $relation) {
|
||||
$selected = !empty($tags) && in_array($relation['name'], $tags);
|
||||
$found = !empty($relation['members']) && in_array($url, $relation['members']);
|
||||
$update = false;
|
||||
|
||||
// remove member from the relation
|
||||
if ($found && !$selected) {
|
||||
$relation['members'] = array_diff($relation['members'], (array) $url);
|
||||
$update = true;
|
||||
}
|
||||
// add member to the relation
|
||||
else if (!$found && $selected) {
|
||||
$relation['members'][] = $url;
|
||||
$update = true;
|
||||
}
|
||||
|
||||
if ($update) {
|
||||
if ($this->save($relation, 'relation')) {
|
||||
$this->tags[$idx] = $relation; // update in-memory cache
|
||||
}
|
||||
}
|
||||
|
||||
if ($selected) {
|
||||
$tags = array_diff($tags, (array)$relation['name']);
|
||||
}
|
||||
}
|
||||
|
||||
// create new relations
|
||||
if (!empty($tags)) {
|
||||
foreach ($tags as $tag) {
|
||||
$relation = array(
|
||||
'name' => $tag,
|
||||
'members' => (array) $url,
|
||||
'category' => 'tag',
|
||||
);
|
||||
|
||||
if ($this->save($relation, 'relation')) {
|
||||
$this->tags[] = $relation; // update in-memory cache
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags (all or referring to specified object)
|
||||
*
|
||||
* @param string $uid Optional object UID
|
||||
*
|
||||
* @return array List of Relation objects
|
||||
*/
|
||||
public function get_tags($uid = '*')
|
||||
{
|
||||
if (!isset($this->tags)) {
|
||||
$filter = array(array('type', '=', 'relation'));
|
||||
$default = true;
|
||||
$data_filter = array('category' => 'tag');
|
||||
|
||||
$this->tags = $this->get_objects($filter, $default, $data_filter);
|
||||
}
|
||||
|
||||
if ($uid === '*') {
|
||||
return $this->tags;
|
||||
}
|
||||
|
||||
$result = array();
|
||||
$search = self::build_member_url($uid);
|
||||
|
||||
foreach ($this->tags as $tag) {
|
||||
if (in_array($search, (array) $tag['members'])) {
|
||||
$result[] = $tag;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue