From f9cff418eb047531941bad66a33a4820f472dba7 Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Tue, 1 Apr 2014 16:29:48 +0200 Subject: [PATCH] Implement search in notes contents --- plugins/kolab_notes/kolab_notes.php | 38 +++++++++++++++++-- plugins/kolab_notes/localization/en_US.inc | 2 +- plugins/kolab_notes/notes.js | 44 ++++++++++++++++++---- 3 files changed, 71 insertions(+), 13 deletions(-) diff --git a/plugins/kolab_notes/kolab_notes.php b/plugins/kolab_notes/kolab_notes.php index 15f846ca..5ab2068b 100644 --- a/plugins/kolab_notes/kolab_notes.php +++ b/plugins/kolab_notes/kolab_notes.php @@ -207,7 +207,7 @@ class kolab_notes extends rcube_plugin */ public function notes_fetch() { - $search = rcube_utils::get_input_value('_q', RCUBE_INPUT_GPC); + $search = rcube_utils::get_input_value('_q', RCUBE_INPUT_GPC, true); $list = rcube_utils::get_input_value('_list', RCUBE_INPUT_GPC); $data = $this->notes_data($this->list_notes($list, $search), $tags); @@ -246,14 +246,36 @@ class kolab_notes extends rcube_plugin // full text search (only works with cache enabled) if (strlen($search)) { - foreach (rcube_utils::normalize_string(mb_strtolower($search), true) as $word) { - $query[] = array('words', '~', $word); + $words = array_filter(rcube_utils::normalize_string(mb_strtolower($search), true)); + foreach ($words as $word) { + if (strlen($word) > 2) { // only words > 3 chars are stored in DB + $query[] = array('words', '~', $word); + } } } $this->_read_lists(); if ($folder = $this->folders[$list_id]) { foreach ($folder->select($query) as $record) { + // post-filter search results + if (strlen($search)) { + $matches = 0; + $contents = mb_strtolower( + $record['title'] . + ($this->is_html($record) ? strip_tags($record['description']) : $record['description']) . + join(' ', (array)$record['categories']) + ); + foreach ($words as $word) { + if (mb_strpos($contents, $word) !== false) { + $matches++; + } + } + + // skip records not matching all search words + if ($matches < count($words)) { + continue; + } + } $record['list'] = $list_id; $results[] = $record; } @@ -337,7 +359,7 @@ class kolab_notes extends rcube_plugin } // clean HTML contents - if (!empty($note['description']) && preg_match('/<(html|body)(\s+[a-z]|>)/', $note['description'], $m) && strpos($note['description'], '') > 0) { + if (!empty($note['description']) && $this->is_html($note)) { $note['html'] = $this->_wash_html($note['description']); } @@ -494,6 +516,14 @@ class kolab_notes extends rcube_plugin return $folder->delete($note['uid'], $force); } + /** + * Determine whether the given note is HTML formatted + */ + private function is_html($note) + { + // check for opening and closing or tags + return (preg_match('/<(html|body)(\s+[a-z]|>)/', $note['description'], $m) && strpos($note['description'], '') > 0); + } /** * Process the given note data (submitted by the client) before saving it diff --git a/plugins/kolab_notes/localization/en_US.inc b/plugins/kolab_notes/localization/en_US.inc index 3fe7d505..5905bbbf 100644 --- a/plugins/kolab_notes/localization/en_US.inc +++ b/plugins/kolab_notes/localization/en_US.inc @@ -5,7 +5,7 @@ $labels['navtitle'] = 'Notes'; $labels['tags'] = 'Tags'; $labels['lists'] = 'Notebooks'; $labels['notes'] = 'Notes'; -$labels['create'] = 'Create'; +$labels['create'] = 'New Note'; $labels['newnote'] = 'New Note'; $labels['notags'] = 'No tags'; $labels['removetag'] = 'Remove tag'; diff --git a/plugins/kolab_notes/notes.js b/plugins/kolab_notes/notes.js index fe90072f..d7cd261c 100644 --- a/plugins/kolab_notes/notes.js +++ b/plugins/kolab_notes/notes.js @@ -31,6 +31,8 @@ function rcube_kolab_notes_ui(settings) var notesdata = {}; var tagsfilter = []; var tags = []; + var search_request; + var search_query; var me = this; /* public members */ @@ -275,19 +277,39 @@ function rcube_kolab_notes_ui(settings) } /** - * + * Execute search */ function quicksearch() { - + var q; + if (rcmail.gui_objects.qsearchbox && (q = rcmail.gui_objects.qsearchbox.value)) { + var id = 'search-'+q; + + // ignore if query didn't change + if (search_request == id) + return; + + search_request = id; + search_query = q; + + fetch_notes(); + } + else { // empty search input equals reset + reset_search(); + } } /** - * + * Reset search and get back to normal listing */ function reset_search() { - + $(rcmail.gui_objects.qsearchbox).val(''); + + if (search_request) { + search_request = search_query = null; + fetch_notes(); + } } /** @@ -300,14 +322,13 @@ function rcube_kolab_notes_ui(settings) if (id && id != me.selected_list) { me.selected_list = id; - noteslist.clear_selection(); } ui_loading = rcmail.set_busy(true, 'loading'); rcmail.http_request('fetch', { _list:me.selected_list, _q:search_query }, true); reset_view(); - noteslist.clear(); + noteslist.clear(true); notesdata = {}; tagsfilter = []; } @@ -334,7 +355,6 @@ function rcube_kolab_notes_ui(settings) if (me.selected_note && me.selected_note.uid == note.uid && !match) { noteslist.clear_selection(); -// reset_view(); } } } @@ -363,8 +383,16 @@ function rcube_kolab_notes_ui(settings) notesdata[rec.id] = rec; } - render_tagslist(data.tags || [], true) + render_tagslist(data.tags || [], !data.search) rcmail.set_busy(false, 'loading', ui_loading); + + // select the single result + if (data.data.length == 1) { + noteslist.select(data.data[0].id); + } + else if (me.selected_note && notesdata[me.selected_note.id]) { + noteslist.select(me.selected_note.id); + } } /**