From 5802e08e4833c0567f6e2f7d7a50ece521dc3f6e Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Thu, 08 Oct 2015 05:33:53 -0400
Subject: [PATCH] Mail messages searching with predefined date interval (T103)

---
 skins/larry/templates/mail.html       |    2 
 CHANGELOG                             |    1 
 program/steps/mail/search.inc         |   41 +++++++++++--
 skins/classic/templates/mail.html     |    2 
 program/steps/mail/func.inc           |   54 ++++++++++++-----
 program/localization/en_US/labels.inc |    6 ++
 skins/larry/styles.css                |    6 ++
 program/js/app.js                     |   20 ++++++
 skins/larry/mail.css                  |    3 +
 9 files changed, 112 insertions(+), 23 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 52a6c1b..444447d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
 CHANGELOG Roundcube Webmail
 ===========================
 
+- Implemented mail messages searching with predefined date interval
 - PGP encryption support via Mailvelope integration
 - PGP encryption support via Enigma plugin
 - PHP7 compatibility fixes (#1490416)
diff --git a/program/js/app.js b/program/js/app.js
index 8a9712f..46e0857 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -4896,6 +4896,9 @@
     if (filter)
       url._filter = filter;
 
+    if (this.gui_objects.search_interval)
+      url._interval = $(this.gui_objects.search_interval).val();
+
     if (search) {
       url._q = search;
 
@@ -4932,6 +4935,9 @@
     if (this.gui_objects.qsearchbox)
       this.gui_objects.qsearchbox.value = '';
 
+    if (this.gui_objects.search_interval)
+      $(this.gui_objects.search_interval).val('');
+
     if (this.env.qsearch)
       this.abort_request(this.env.qsearch);
 
@@ -4961,6 +4967,20 @@
     }
   };
 
+  this.set_searchinterval = function(interval)
+  {
+    var old = this.env.search_interval;
+    this.env.search_interval = interval;
+
+    // re-send search query with new interval
+    if (interval != old && this.env.search_request) {
+      if (!this.qsearch(this.gui_objects.qsearchbox.value) && this.env.search_filter && this.env.search_filter != 'ALL')
+        this.filter_mailbox(this.env.search_filter);
+      if (interval)
+        this.select_folder(this.env.mailbox, '', true);
+    }
+  };
+
   this.set_searchmods = function(mods)
   {
     var mbox = this.env.mailbox,
diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc
index 08f6a60..01a079e 100644
--- a/program/localization/en_US/labels.inc
+++ b/program/localization/en_US/labels.inc
@@ -225,6 +225,12 @@
 $labels['currentfolder'] = 'Current folder';
 $labels['subfolders'] = 'This and subfolders';
 $labels['allfolders'] = 'All folders';
+$labels['searchinterval-1W'] = 'older than a week';
+$labels['searchinterval-1M'] = 'older than a month';
+$labels['searchinterval-1Y'] = 'older than a year';
+$labels['searchinterval1W'] = 'younger than a week';
+$labels['searchinterval1M'] = 'younger than a month';
+$labels['searchinterval1Y'] = 'younger than a year';
 
 $labels['openinextwin'] = 'Open in new window';
 $labels['emlsave'] = 'Download (.eml)';
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index f456945..d949cf6 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -125,6 +125,7 @@
     'messagecontentframe' => 'rcmail_messagecontent_frame',
     'messageimportform'   => 'rcmail_message_import_form',
     'searchfilter'        => 'rcmail_search_filter',
+    'searchinterval'      => 'rcmail_search_interval',
     'searchform'          => array($OUTPUT, 'search_form'),
 ));
 
@@ -2028,8 +2029,9 @@
 {
     global $RCMAIL;
 
-    if (!strlen($attrib['id']))
+    if (!strlen($attrib['id'])) {
         $attrib['id'] = 'rcmlistfilter';
+    }
 
     $attrib['onchange'] = rcmail_output::JS_OBJECT_NAME.'.filter_mailbox(this.value)';
 
@@ -2043,27 +2045,45 @@
         $attachment .= ' HEADER Content-Type ' . rcube_imap_generic::escape($type);
     }
 
-    $select_filter = new html_select($attrib);
-    $select_filter->add($RCMAIL->gettext('all'), 'ALL');
-    $select_filter->add($RCMAIL->gettext('unread'), 'UNSEEN');
-    $select_filter->add($RCMAIL->gettext('flagged'), 'FLAGGED');
-    $select_filter->add($RCMAIL->gettext('unanswered'), 'UNANSWERED');
+    $select = new html_select($attrib);
+    $select->add($RCMAIL->gettext('all'), 'ALL');
+    $select->add($RCMAIL->gettext('unread'), 'UNSEEN');
+    $select->add($RCMAIL->gettext('flagged'), 'FLAGGED');
+    $select->add($RCMAIL->gettext('unanswered'), 'UNANSWERED');
     if (!$RCMAIL->config->get('skip_deleted')) {
-        $select_filter->add($RCMAIL->gettext('deleted'), 'DELETED');
-        $select_filter->add($RCMAIL->gettext('undeleted'), 'UNDELETED');
+        $select->add($RCMAIL->gettext('deleted'), 'DELETED');
+        $select->add($RCMAIL->gettext('undeleted'), 'UNDELETED');
     }
-    $select_filter->add($RCMAIL->gettext('withattachment'), $attachment);
-    $select_filter->add($RCMAIL->gettext('priority').': '.$RCMAIL->gettext('highest'), 'HEADER X-PRIORITY 1');
-    $select_filter->add($RCMAIL->gettext('priority').': '.$RCMAIL->gettext('high'), 'HEADER X-PRIORITY 2');
-    $select_filter->add($RCMAIL->gettext('priority').': '.$RCMAIL->gettext('normal'), 'NOT HEADER X-PRIORITY 1 NOT HEADER X-PRIORITY 2 NOT HEADER X-PRIORITY 4 NOT HEADER X-PRIORITY 5');
-    $select_filter->add($RCMAIL->gettext('priority').': '.$RCMAIL->gettext('low'), 'HEADER X-PRIORITY 4');
-    $select_filter->add($RCMAIL->gettext('priority').': '.$RCMAIL->gettext('lowest'), 'HEADER X-PRIORITY 5');
-
-    $out = $select_filter->show($_REQUEST['_search'] ? $_SESSION['search_filter'] : 'ALL');
+    $select->add($RCMAIL->gettext('withattachment'), $attachment);
+    $select->add($RCMAIL->gettext('priority').': '.$RCMAIL->gettext('highest'), 'HEADER X-PRIORITY 1');
+    $select->add($RCMAIL->gettext('priority').': '.$RCMAIL->gettext('high'), 'HEADER X-PRIORITY 2');
+    $select->add($RCMAIL->gettext('priority').': '.$RCMAIL->gettext('normal'), 'NOT HEADER X-PRIORITY 1 NOT HEADER X-PRIORITY 2 NOT HEADER X-PRIORITY 4 NOT HEADER X-PRIORITY 5');
+    $select->add($RCMAIL->gettext('priority').': '.$RCMAIL->gettext('low'), 'HEADER X-PRIORITY 4');
+    $select->add($RCMAIL->gettext('priority').': '.$RCMAIL->gettext('lowest'), 'HEADER X-PRIORITY 5');
 
     $RCMAIL->output->add_gui_object('search_filter', $attrib['id']);
 
-    return $out;
+    return $select->show($_REQUEST['_search'] ? $_SESSION['search_filter'] : 'ALL');
+}
+
+function rcmail_search_interval($attrib)
+{
+    global $RCMAIL;
+
+    if (!strlen($attrib['id'])) {
+        $attrib['id'] = 'rcmsearchinterval';
+    }
+
+    $select = new html_select($attrib);
+    $select->add('', '');
+
+    foreach (array('1W', '1M', '1Y', '-1W', '-1M', '-1Y') as $value) {
+        $select->add($RCMAIL->gettext('searchinterval' . $value), $value);
+    }
+
+    $RCMAIL->output->add_gui_object('search_interval', $attrib['id']);
+
+    return $select->show($_REQUEST['_search'] ? $_SESSION['search_interval'] : '');
 }
 
 function rcmail_message_error()
diff --git a/program/steps/mail/search.inc b/program/steps/mail/search.inc
index f69892e..ee6ba88 100644
--- a/program/steps/mail/search.inc
+++ b/program/steps/mail/search.inc
@@ -38,16 +38,15 @@
 $filter  = rcube_utils::get_input_value('_filter', rcube_utils::INPUT_GET);
 $headers = rcube_utils::get_input_value('_headers', rcube_utils::INPUT_GET);
 $scope   = rcube_utils::get_input_value('_scope', rcube_utils::INPUT_GET);
+$interval = rcube_utils::get_input_value('_interval', rcube_utils::INPUT_GET);
 $continue = rcube_utils::get_input_value('_continue', rcube_utils::INPUT_GET);
 $subject = array();
 
 $filter         = trim($filter);
-$search_request = md5($mbox.$scope.$filter.$str);
+$search_request = md5($mbox.$scope.$interval.$filter.$str);
 
 // add list filter string
 $search_str = $filter && $filter != 'ALL' ? $filter : '';
-
-$_SESSION['search_filter'] = $filter;
 
 // Check the search string for type of search
 if (preg_match("/^from:.*/i", $str)) {
@@ -102,6 +101,10 @@
 
 $search = isset($srch) ? trim($srch) : trim($str);
 
+if ($search_interval = rcmail_search_interval_criteria($interval)) {
+    $search_str .= ' ' . $search_interval;
+}
+
 if (!empty($subject)) {
     $search_str .= str_repeat(' OR', count($subject)-1);
     foreach ($subject as $sub) {
@@ -144,9 +147,10 @@
     $_SESSION['search'] = $RCMAIL->storage->get_search_set();
     $_SESSION['last_text_search'] = $str;
 }
-$_SESSION['search_request'] = $search_request;
-$_SESSION['search_scope']   = $scope;
-
+$_SESSION['search_request']  = $search_request;
+$_SESSION['search_scope']    = $scope;
+$_SESSION['search_interval'] = $interval;
+$_SESSION['search_filter']   = $filter;
 
 // Get the headers
 if (!$result->incomplete) {
@@ -212,3 +216,28 @@
 }
 
 $OUTPUT->send();
+
+
+// Creates BEFORE/SINCE search criteria from the specified interval
+// Interval can be: 1W, 1M, 1Y, -1W, -1M, -1Y
+function rcmail_search_interval_criteria($interval)
+{
+    if (empty($interval)) {
+        return;
+    }
+
+    if ($interval[0] == '-') {
+        $search   = 'BEFORE';
+        $interval = substr($interval, 1);
+    }
+    else {
+        $search = 'SINCE';
+    }
+
+    $date     = new DateTime('now');
+    $interval = new DateInterval('P' . $interval);
+
+    $date->sub($interval);
+
+    return $search . ' ' . $date->format('j-M-Y');
+}
diff --git a/skins/classic/templates/mail.html b/skins/classic/templates/mail.html
index b7af014..c0bb469 100644
--- a/skins/classic/templates/mail.html
+++ b/skins/classic/templates/mail.html
@@ -115,6 +115,8 @@
     <li><label><input type="checkbox" name="s_mods[]" value="bcc" id="s_mod_bcc" onclick="rcmail_ui.set_searchmod(this)" /> <span><roundcube:label name="bcc" /></span></label></li>
     <li><label><input type="checkbox" name="s_mods[]" value="body" id="s_mod_body" onclick="rcmail_ui.set_searchmod(this)" /> <span><roundcube:label name="body" /></span></label></li>
     <li><label><input type="checkbox" name="s_mods[]" value="text" id="s_mod_text" onclick="rcmail_ui.set_searchmod(this)" /> <span><roundcube:label name="msgtext" /></span></label></li>
+    <li><label class="comment"><roundcube:label name="date" /></label></li>
+    <li><roundcube:object name="searchinterval" id="s_interval" onchange="rcmail.set_searchinterval($(this).val())" /></li>
     <li><label class="comment"><roundcube:label name="searchscope" /></label></li>
     <li><label><input type="radio" name="s_scope" value="base" id="s_scope_base" onclick="rcmail.set_searchscope(this.value)" /> <span><roundcube:label name="currentfolder" /></span></label></li>
     <li><label><input type="radio" name="s_scope" value="sub" id="s_scope_sub" onclick="rcmail.set_searchscope(this.value)" /> <span><roundcube:label name="subfolders" /></span></label></li>
diff --git a/skins/larry/mail.css b/skins/larry/mail.css
index 80e2109..3dc93d2 100644
--- a/skins/larry/mail.css
+++ b/skins/larry/mail.css
@@ -251,6 +251,9 @@
 	background-position: -28px -458px;
 }
 
+#s_interval {
+	margin: 3px 8px;
+}
 
 /*** message list ***/
 
diff --git a/skins/larry/styles.css b/skins/larry/styles.css
index 88459af..a66bbac 100644
--- a/skins/larry/styles.css
+++ b/skins/larry/styles.css
@@ -2408,6 +2408,12 @@
 ul.toolbarmenu li.separator label {
 	color: #bbb;
 	font-style: italic;
+	padding: 0 8px;
+	line-height: 17px;
+}
+
+ul.toolbarmenu li input {
+	margin: 0;
 }
 
 ul.toolbarmenu li a.icon {
diff --git a/skins/larry/templates/mail.html b/skins/larry/templates/mail.html
index bda3efb..4bf87c9 100644
--- a/skins/larry/templates/mail.html
+++ b/skins/larry/templates/mail.html
@@ -52,6 +52,8 @@
 		<li role="menuitem"><label><input type="checkbox" name="s_mods[]" value="bcc" id="s_mod_bcc" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="bcc" /></span></label></li>
 		<li role="menuitem"><label><input type="checkbox" name="s_mods[]" value="body" id="s_mod_body" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="body" /></span></label></li>
 		<li role="menuitem"><label><input type="checkbox" name="s_mods[]" value="text" id="s_mod_text" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="msgtext" /></span></label></li>
+		<li role="separator" class="separator"><label><roundcube:label name="date" /></label></li>
+		<li role="menuitem"><roundcube:object name="searchinterval" id="s_interval" onchange="rcmail.set_searchinterval($(this).val())" /></li>
 		<li role="separator" class="separator"><label><roundcube:label name="searchscope" /></label></li>
 		<li role="menuitem"><label><input type="radio" name="s_scope" value="base" id="s_scope_base" onclick="UI.set_searchscope(this)" /> <span><roundcube:label name="currentfolder" /></span></label></li>
 		<li role="menuitem"><label><input type="radio" name="s_scope" value="sub" id="s_scope_sub" onclick="UI.set_searchscope(this)" /> <span><roundcube:label name="subfolders" /></span></label></li>

--
Gitblit v1.9.1