From d843b290d5ec78fe4c3e956915d7722cceb79314 Mon Sep 17 00:00:00 2001 From: Michael M Slusarz Date: Wed, 16 Sep 2009 12:25:12 -0600 Subject: [PATCH] Request #3438, Request #6875: Relative date searches --- imp/docs/CHANGES | 1 + imp/js/search.js | 25 +++++++++++++++++++++++++ imp/lib/Search.php | 29 ++++++++++++++++++++++++----- imp/lib/UI/Search.php | 21 +++++++++++++++++++++ imp/search-basic.php | 2 +- imp/templates/search/search.html | 6 ++++++ 6 files changed, 78 insertions(+), 6 deletions(-) diff --git a/imp/docs/CHANGES b/imp/docs/CHANGES index 327f3ed99..0e0098b44 100644 --- a/imp/docs/CHANGES +++ b/imp/docs/CHANGES @@ -2,6 +2,7 @@ v5.0-git -------- +[mms] Add ability to search by relative date intervals (Request #3438). [mms] Add advanced search query interface to DIMP (Request #6875). [mms] Add ability to search by a custom defined header (Request #6875). [mms] Improved advanced search query interface (Request #6875). diff --git a/imp/js/search.js b/imp/js/search.js index 9090e4589..f6ad78d17 100644 --- a/imp/js/search.js +++ b/imp/js/search.js @@ -79,6 +79,10 @@ var ImpSearch = { this.insertDate(c.t, c.v); break; + case 'within': + this.insertWithin(c.t, c.v); + break; + case 'flag': this.insertFlag(c.v); break; @@ -133,6 +137,10 @@ var ImpSearch = { this.insertDate(val); break; + case 'within': + this.insertWithin(val); + break; + case 'flag': this.insertFlag(val); break; @@ -212,6 +220,18 @@ var ImpSearch = { this.criteria[id] = { t: type, v: data }; }, + insertWithin: function(id, data) + { + data = data || { l: '', v: '' }; + + var tmp = [ + new Element('EM').insert(this.getLabel(id)), + new Element('INPUT', { type: 'text', size: 8 }).setValue(data.v), + $($('within_criteria').cloneNode(true)).writeAttribute({ id: null }).show().setValue(data.l) + ]; + this.criteria[this.insertCriteria(tmp)] = { t: id }; + }, + insertFlag: function(id) { var tmp = [ @@ -262,6 +282,11 @@ var ImpSearch = { data.push(this.criteria[c]); break; + case 'within': + this.criteria[c].v = { l: $F($(c).down('SELECT')), v: parseInt($F($(c).down('INPUT')), 10) }; + data.push(this.criteria[c]); + break; + case 'flag': data.push({ t: 'flag', v: this.criteria[c].t }); break; diff --git a/imp/lib/Search.php b/imp/lib/Search.php index 07f9b76f7..ef6aac224 100644 --- a/imp/lib/Search.php +++ b/imp/lib/Search.php @@ -24,7 +24,8 @@ * array( * stdClass object { * 't' => (string) 'Type' - The criteria type - * Values: header, customhdr, body, text, date, size, flag + * Values: header, customhdr, body, text, date, within, 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: @@ -38,6 +39,10 @@ * 'm' - (integer) The search month (is 1 less than * the actual month) * 'd' - (integer) The search day + * 'within' - (stdClass object) Contains 2 elements: + * 'l' - (string) The length of time. Either 'y' + * (years), 'm' (months), or 'd' (days) + * 'v' - (integer) The length of time * 'size' - (integer) The search size in bytes * 'flag' - (string) The flag to search for * 'n' => (boolean) 'Not' - Should we do a not search? @@ -190,6 +195,16 @@ class IMP_Search 'type' => 'date', 'not' => true ), + 'older' => array( + 'label' => _("Older Than"), + 'type' => 'within', + 'not' => true + ), + 'younger' => array( + 'label' => _("Younger Than"), + 'type' => 'within', + 'not' => true + ), // Displayed in KB, but stored internally in bytes 'size_smaller' => array( 'label' => _("Size (KB) <"), @@ -670,16 +685,20 @@ class IMP_Search } break; + case 'customhdr': + $text_array[] = sprintf("%s for '%s'", $rule->v->h, ((!empty($rule->n)) ? _("not") . ' ' : '') . $rule->v->s); + 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); + case 'within': + $text_array[] = sprintf("%s %u %s", $searchfields[$field]['label'], $rule->v->v, $rule->v->l == 'y' ? _("years") : ($rule->v->l == 'm' ? _("months") : _("days"))); break; - case 'customhdr': - $text_array[] = sprintf("%s for '%s'", $rule->v->h, ((!empty($rule->n)) ? _("not") . ' ' : '') . $rule->v->s); + case 'size': + $text_array[] = $searchfields[$field]['label'] . ' ' . ($rule->v / 1024); break; default: diff --git a/imp/lib/UI/Search.php b/imp/lib/UI/Search.php index 79891728a..34adf34f2 100644 --- a/imp/lib/UI/Search.php +++ b/imp/lib/UI/Search.php @@ -75,6 +75,27 @@ class IMP_UI_Search } break; + case 'within': + /* Limited to day granularity because that is the technical + * limit for IMAP servers without 'WITHIN' extension. */ + if (!empty($rule->v)) { + $secs = $rule->v->v * 60 * 60 * 24; + + switch ($rule->v->l) { + case 'y': + $secs *= 365; + break; + + case 'm': + $secs *= 30; + break; + } + + $ob->intervalSearch($secs, $rule->t == 'older' ? Horde_Imap_Client_Search_Query::INTERVAL_OLDER : Horde_Imap_Client_Search_Query::INTERVAL_YOUNGER); + $search_array[] = $ob; + } + break; + case 'size': if (!empty($rule->v)) { $ob->size(intval($rule->v), $rule->t == 'size_larger'); diff --git a/imp/search-basic.php b/imp/search-basic.php index ac1fedd36..6d91190c8 100644 --- a/imp/search-basic.php +++ b/imp/search-basic.php @@ -39,7 +39,7 @@ $f_fields = $s_fields = array(); $search_mailbox = Horde_Util::getFormData('search_mailbox'); foreach ($imp_search->searchFields() as $key => $val) { - if (!in_array($val['type'], array('customhdr', 'date'))) { + if (!in_array($val['type'], array('customhdr', 'date', 'within'))) { $s_fields[] = array( 'val' => $key, 'label' => $val['label'] diff --git a/imp/templates/search/search.html b/imp/templates/search/search.html index b81ffe490..c1ae7c92e 100644 --- a/imp/templates/search/search.html +++ b/imp/templates/search/search.html @@ -87,3 +87,9 @@ + + -- 2.11.0