Add ability to search by a custom defined header.
Add documentation for criteria UI object
Clean up the way we store flag searches in criteria UI object to be more
consistent with other criteria
Cleanup the way we output gettext strings on search page
Move dimp quicksearch folder ID to IMP_Search::DIMP_QUICKSEARCH
v5.0-git
--------
+[mms] Add ability to search by a custom defined header (Request #6875).
[mms] Improved advanced search query interface (Request #6875).
[mms] More intelligent ordering of autocomplete search results.
[mms] Add a mini search query interface (Request #6875).
var ImpSearch = {
// The following variables are defined in search.php:
- // loading, months, need_criteria, need_folder, need_vfolder_label,
- // types
+ // months, text, types
criteria: {},
saved_searches: {},
show_unsub: false,
this.insertText(c.t, c.v, c.n);
break;
+ case 'customhdr':
+ this.insertCustomHdr(c.v, c.n);
+ break;
+
case 'size':
this.insertSize(c.t, c.v);
break;
break;
case 'flag':
- this.insertFlag(c.t);
+ this.insertFlag(c.v);
break;
}
}, this);
this.insertText(val);
break;
+ case 'customhdr':
+ this.insertCustomHdr();
+ break;
+
case 'size':
this.insertSize(val);
break;
var tmp = [
new Element('EM').insert(this.getLabel(id)),
new Element('INPUT', { type: 'text', size: 25 }),
- new Element('SPAN').insert(new Element('INPUT', { checked: Boolean(not), className: 'checkbox', type: 'checkbox' })).insert(this.not_match)
+ new Element('SPAN').insert(new Element('INPUT', { checked: Boolean(not), className: 'checkbox', type: 'checkbox' })).insert(this.text.not_match)
];
this.criteria[this.insertCriteria(tmp)] = { t: id };
},
+ insertCustomHdr: function(text, not)
+ {
+ text = text || { h: '', s: '' };
+
+ var tmp = [
+ new Element('EM').insert(this.text.customhdr),
+ new Element('INPUT', { type: 'text', size: 25 }).setValue(text.h),
+ new Element('SPAN').insert(new Element('EM').insert(this.text.search_term + ' ')).insert(new Element('INPUT', { type: 'text', size: 25 }).setValue(text.s)),
+ new Element('SPAN').insert(new Element('INPUT', { checked: Boolean(not), className: 'checkbox', type: 'checkbox' })).insert(this.text.not_match)
+ ];
+ this.criteria[this.insertCriteria(tmp)] = { t: 'customhdr' };
+ },
+
insertSize: function(id, size)
{
var tmp = [
var d = (data ? new Date(data.y, data.m, data.d) : new Date()),
tmp = [
new Element('EM').insert(this.getLabel(id)),
- new Element('SPAN').insert(new Element('SPAN')).insert(new Element('A', { href: '#', className: 'calendarPopup', title: this.dateselection }).insert(new Element('SPAN', { className: 'searchuiImg searchuiCalendar' })))
+ new Element('SPAN').insert(new Element('SPAN')).insert(new Element('A', { href: '#', className: 'calendarPopup', title: this.text.dateselection }).insert(new Element('SPAN', { className: 'searchuiImg searchuiCalendar' })))
];
this.replaceDate(this.insertCriteria(tmp), id, { y: d.getFullYear(), m: d.getMonth(), d: d.getDate() });
},
insertFlag: function(id)
{
var tmp = [
- new Element('EM').insert(this.flag),
+ new Element('EM').insert(this.text.flag),
this.getLabel(id).slice(0, -2)
];
this.criteria[this.insertCriteria(tmp)] = { t: id };
var data = [], tmp;
if (!this._getAll().findAll(function(i) { return i.checked; }).size()) {
- alert(this.need_folder);
+ alert(this.text.need_folder);
+ } else if ($F('vfolder_save') && $F('vfolder_label').empty()) {
+ alert(this.text.need_vfolder_label);
} else {
tmp = $('search_criteria_table').childElements().pluck('id');
if (tmp.size()) {
data.push(this.criteria[c]);
break;
+ case 'customhdr':
+ this.criteria[c].v = { h: $F($(c).down('INPUT')), s: $F($(c).down('INPUT', 1)) };
+ data.push(this.criteria[c]);
+ break;
+
case 'size':
tmp2 = Number($F($(c).down('INPUT')));
if (!isNaN(tmp2)) {
$('criteria_form').setValue(data.toJSON());
$('search_form').submit();
} else {
- alert(this.need_criteria);
+ alert(this.text.need_criteria);
}
}
},
case 'link_sub':
tmp = this._getAll();
this.show_unsub = !this.show_unsub;
- $('search_folders_hdr').next('DIV').update(this.loading);
+ $('search_folders_hdr').next('DIV').update(this.text.loading);
new Ajax.Request($('search_form').readAttribute('action'), {
parameters: { show_unsub: Number(this.show_unsub) },
onComplete: this._showFoldersCallback.bind(this, tmp)
*
* $_SESSION['imp']['search'] = array(
* 'id_1' => array(
- * 'c' => (array) List of search criteria. For virtual folders, this
- * data is stored in the preferences,
+ * 'c' => (array) List of search criteria (the IMP-specific data
+ * structure that allows recreation of the search query on the
+ * search page). For virtual folders, this data is stored in
+ * the preferences,
* 'f' => (array) List of folders to search,
- * 'l' => (string) Description of search,
+ * 'l' => (string) Description (label) of search,
* 'q' => (Horde_Imap_Client_Search_Query) [serialized],
* 'v' => (boolean) True if this is a Virtual Folder
* ),
* ....
* );
*
+ * The format of the 'c' (search criteria) array is as folows:
+ * array(
+ * stdClass object {
+ * 't' => (string) 'Type' - The criteria type
+ * Values: header, customhdr, body, text, date, size, flag
+ * 'v' => (mixed) 'Value' - The data used to build the search
+ * 'header' - (string) The value to search for in the header
+ * 'customhdr' - (stdClass object) Contains 2 elements:
+ * 'h' - (string) The header name
+ * 's' - (string) The search string
+ * 'body' - (string) The value to search for in the body
+ * 'text' - (string) The value to search for in the entire
+ * message
+ * 'date' - (stdClass object) Contains 3 elements:
+ * 'y' - (integer) The search year
+ * 'm' - (integer) The search month (is 1 less than
+ * the actual month)
+ * 'd' - (integer) The search day
+ * 'size' - (integer) The search size in bytes
+ * 'flag' - (string) The flag to search for
+ * 'n' => (boolean) 'Not' - Should we do a not search?
+ * Only used for the following types: header, customhdr, body,
+ * text
+ * },
+ * ...
+ * )
+ *
* Copyright 2002-2009 The Horde Project (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (GPL). If you
/* The mailbox search prefix. */
const MBOX_PREFIX = 'impsearch\0';
- /* The basic search mailbox name. */
+ /* The special search mailbox names. */
const BASIC_SEARCH = 'impbsearch';
+ const DIMP_QUICKSEARCH = 'dimpqsearch';
/* Bitmask constants for listQueries(). */
const LIST_SEARCH = 1;
'type' => 'header',
'not' => true
),
- 'custom' => array(
+ 'customhdr' => array(
'label' => _("Custom Header"),
'type' => 'customhdr',
'not' => true
$text_array = array();
foreach ($criteria as $rule) {
$field = $rule->t;
-
- if (isset($flagfields[$field])) {
- $text_array[] = sprintf(_("flagged \"%s\""), $flagfields[$field]);
- } else {
- switch ($searchfields[$field]['type']) {
- case 'date':
- $text_array[] = sprintf("%s '%s'", $searchfields[$field]['label'], strftime("%x", mktime(0, 0, 0, $rule->v->m + 1, $rule->v->d, $rule->v->y)));
- break;
-
- case 'size':
- $text_array[] = $searchfields[$field]['label'] . ' ' . ($rule->v / 1024);
- break;
-
- default:
- $text_array[] = sprintf("%s for '%s'", $searchfields[$field]['label'], ((!empty($rule->n)) ? _("not") . ' ' : '') . $rule->v);
- break;
+ $type = isset($searchfields[$field]['type'])
+ ? $searchfields[$field]['type']
+ : $field;
+
+ switch ($searchfields[$field]['type']) {
+ case 'flag':
+ if (isset($flagfields[$rule->v])) {
+ $text_array[] = sprintf(_("flagged \"%s\""), $flagfields[$field]);
}
+ break;
+
+ case 'date':
+ $text_array[] = sprintf("%s '%s'", $searchfields[$field]['label'], strftime("%x", mktime(0, 0, 0, $rule->v->m + 1, $rule->v->d, $rule->v->y)));
+ break;
+
+ case 'size':
+ $text_array[] = $searchfields[$field]['label'] . ' ' . ($rule->v / 1024);
+ break;
+
+ case 'customhdr':
+ $text_array[] = sprintf("%s for '%s'", $rule->v->h, ((!empty($rule->n)) ? _("not") . ' ' : '') . $rule->v->s);
+ break;
+
+ default:
+ $text_array[] = sprintf("%s for '%s'", $searchfields[$field]['label'], ((!empty($rule->n)) ? _("not") . ' ' : '') . $rule->v);
+ break;
}
}
foreach ($search as $rule) {
$ob = new Horde_Imap_Client_Search_Query();
- if (isset($flag_fields[$rule->t])) {
- $val = $imp_flags->parseFormId($rule->t);
- $ob->flag($val['flag'], $val['set']);
- $search_array[] = $ob;
- } else {
- /* Ignore unknown types. */
- switch ($search_fields[$rule->t]['type']) {
- case 'header':
- if (!empty($rule->v)) {
- $ob->headerText($rule->t, $rule->v, !empty($rule->n));
- $search_array[] = $ob;
- }
- break;
-
- case 'body':
- case 'text':
- if (!empty($rule->v)) {
- $ob->text($rule->c, $search_fields[$rule->t]['type'] == 'body', !empty($rule->n));
- $search_array[] = $ob;
- }
- break;
-
- case 'date':
- if (!empty($rule->v)) {
- $date = new Horde_Date(array('year' => $rule->v->y, 'month' => $rule->v->m + 1, 'mday' => $rule->v->d));
- $ob->dateSearch($date, ($rule->t == 'date_on') ? Horde_Imap_Client_Search_Query::DATE_ON : (($rule->t == 'date_until') ? Horde_Imap_Client_Search_Query::DATE_BEFORE : Horde_Imap_Client_Search_Query::DATE_SINCE));
- $search_array[] = $ob;
- }
- break;
-
- case 'size':
- if (!empty($rule->v)) {
- $ob->size(intval($rule->v), $rule->t == 'size_larger');
- $search_array[] = $ob;
- }
- break;
+ $type = isset($search_fields[$rule->t]['type'])
+ ? $search_fields[$rule->t]['type']
+ : $rule->t;
+
+ switch ($type) {
+ case 'flag':
+ if (isset($flag_fields[$rule->v])) {
+ $val = $imp_flags->parseFormId($rule->t);
+ $ob->flag($val['flag'], $val['set']);
+ $search_array[] = $ob;
+ }
+ break;
+
+ case 'header':
+ if (!empty($rule->v)) {
+ $ob->headerText($rule->t, $rule->v, !empty($rule->n));
+ $search_array[] = $ob;
+ }
+ break;
+
+ case 'customhdr':
+ if (!empty($rule->v)) {
+ $ob->headerText($rule->v->h, $rule->v->s, !empty($rule->n));
+ $search_array[] = $ob;
+ }
+ break;
+
+ case 'body':
+ case 'text':
+ if (!empty($rule->v)) {
+ $ob->text($rule->c, $search_fields[$rule->t]['type'] == 'body', !empty($rule->n));
+ $search_array[] = $ob;
+ }
+ break;
+
+ case 'date':
+ if (!empty($rule->v)) {
+ $date = new Horde_Date(array('year' => $rule->v->y, 'month' => $rule->v->m + 1, 'mday' => $rule->v->d));
+ $ob->dateSearch($date, ($rule->t == 'date_on') ? Horde_Imap_Client_Search_Query::DATE_ON : (($rule->t == 'date_until') ? Horde_Imap_Client_Search_Query::DATE_BEFORE : Horde_Imap_Client_Search_Query::DATE_SINCE));
+ $search_array[] = $ob;
+ }
+ break;
+
+ case 'size':
+ if (!empty($rule->v)) {
+ $ob->size(intval($rule->v), $rule->t == 'size_larger');
+ $search_array[] = $ob;
}
+ break;
}
}
if ($flag) {
$tmp = new stdClass;
- $tmp->t = $flag;
+ $tmp->t = 'flag';
+ $tmp->v = $flag;
$c_list[] = $tmp;
}
Horde_UI_JsCalendar::init();
+/* Gettext strings for this page. */
+$gettext_strings = array(
+ 'customhdr' => _("Custom Header:"),
+ 'dateselection' => _("Date Selection"),
+ 'flag' => _("Flag:"),
+ 'loading' => _("Loading..."),
+ 'need_criteria' => _("Please select at least one search criteria."),
+ 'need_folder' => _("Please select at least one folder to search."),
+ 'need_vfolder_label' => _("Virtual Folders require a label."),
+ 'not_match' => _("Do NOT Match"),
+ 'search_term' => _("Search Term:")
+);
+
Horde::addInlineScript(array(
- 'ImpSearch.dateselection = ' . Horde_Serialize::serialize(_("Date Selection"), Horde_Serialize::JSON, $charset),
- 'ImpSearch.flag = ' . Horde_Serialize::serialize(_("Flag:"), Horde_Serialize::JSON, $charset),
- 'ImpSearch.loading = ' . Horde_Serialize::serialize(_("Loading..."), Horde_Serialize::JSON, $charset),
'ImpSearch.months = ' . Horde_Serialize::serialize(Horde_UI_JsCalendar::months(), Horde_Serialize::JSON, $charset),
- 'ImpSearch.need_criteria = ' . Horde_Serialize::serialize(_("Please select at least one search criteria."), Horde_Serialize::JSON, $charset),
- 'ImpSearch.need_folder = ' . Horde_Serialize::serialize(_("Please select at least one folder to search."), Horde_Serialize::JSON, $charset),
- 'ImpSearch.need_vfolder_label = ' . Horde_Serialize::serialize(_("Virtual Folders require a label."), Horde_Serialize::JSON, $charset),
- 'ImpSearch.not_match = ' . Horde_Serialize::serialize(_("Do NOT Match"), Horde_Serialize::JSON, $charset),
+ 'ImpSearch.text = ' . Horde_Serialize::serialize($gettext_strings, Horde_Serialize::JSON, $charset),
'ImpSearch.types = ' . Horde_Serialize::serialize($types, Horde_Serialize::JSON, $charset)
));
Horde::addInlineScript($on_domload, 'dom');
'popup_height' => 610,
'popup_width' => 820,
'preview_pref' => intval($GLOBALS['prefs']->getValue('dimp_show_preview')),
- 'qsearchid' => IMP_Search::MBOX_PREFIX . 'dimpqsearch',
+ 'qsearchid' => IMP_Search::MBOX_PREFIX . IMP_Search::DIMP_QUICKSEARCH,
'qsearchfield' => $GLOBALS['prefs']->getValue('dimp_qsearch_field'),
'refresh_time' => intval($GLOBALS['prefs']->getValue('refresh_time')),
'searchprefix' => IMP_Search::MBOX_PREFIX,