From 710e2748498ed97e7086b0dc3c40f11b29aeec8f Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Wed, 20 Oct 2010 09:33:27 -0400
Subject: [PATCH] - Improve performance of unseen messages counting, use STATUS instead of SELECT+SEARCH (#1487058)

---
 CHANGELOG                              |    1 
 program/include/rcube_imap_generic.php |   69 ++++++++++++++++++++++++++++++----
 2 files changed, 62 insertions(+), 8 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index b150215..ad733e6 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -37,6 +37,7 @@
 - Add METADATA extension support into IMAP classes (RFC5464)
 - Fix decoding of e-mail address strings in message headers (#1487068)
 - Fix handling of attachments when Content-Disposition is not inline nor attachment (#1487051)
+- Improve performance of unseen messages counting (#1487058)
 
 RELEASE 0.4.2
 -------------
diff --git a/program/include/rcube_imap_generic.php b/program/include/rcube_imap_generic.php
index e7e858f..4c082b9 100644
--- a/program/include/rcube_imap_generic.php
+++ b/program/include/rcube_imap_generic.php
@@ -733,6 +733,41 @@
         return false;
     }
 
+    /**
+     * Executes STATUS comand
+     *
+     * @param string $mailbox Mailbox name
+     * @param array  $items   Requested item names
+     *
+     * @return array Status item-value hash
+     * @access public
+     * @since 0.5-beta
+     */
+    function status($mailbox, $items)
+    {
+	    if (empty($mailbox) || empty($items)) {
+		    return false;
+	    }
+
+        list($code, $response) = $this->execute('STATUS', array($this->escape($mailbox),
+            '(' . implode(' ', (array) $items) . ')'));
+
+        if ($code == self::ERROR_OK && preg_match('/\* STATUS /i', $response)) {
+            $result   = array();
+            $response = substr($response, 9); // remove prefix "* STATUS "
+
+            list($mbox, $items) = $this->tokenizeResponse($response, 2);
+
+            for ($i=0, $len=count($items); $i<$len; $i += 2) {
+                $result[$items[$i]] = (int) $items[$i+1];
+            }
+
+			return $result;
+		}
+
+        return false;
+    }
+
     function checkForRecent($mailbox)
     {
 	    if (empty($mailbox)) {
@@ -757,6 +792,32 @@
 	    if ($this->selected == $mailbox) {
 		    return $this->data['EXISTS'];
 	    }
+
+        return false;
+    }
+
+    /**
+     * Returns count of messages without \Seen flag in a specified folder
+     *
+     * @param string $mailbox Mailbox name
+     *
+     * @return int Number of messages, False on error
+     * @access public
+     */
+    function countUnseen($mailbox)
+    {
+        // Try STATUS, should be faster
+        $counts = $this->status($mailbox, array('UNSEEN'));
+        if (is_array($counts)) {
+            return (int) $counts['UNSEEN'];
+        }
+
+        // Invoke SEARCH as a fallback
+        // @TODO: ESEARCH support
+        $index = $this->search($mailbox, 'ALL UNSEEN');
+        if (is_array($index)) {
+            return count($index);
+        }
 
         return false;
     }
@@ -1411,14 +1472,6 @@
             self::COMMAND_NORESPONSE);
 
 	    return $result;
-    }
-
-    function countUnseen($folder)
-    {
-        $index = $this->search($folder, 'ALL UNSEEN');
-        if (is_array($index))
-            return count($index);
-        return false;
     }
 
     // Don't be tempted to change $str to pass by reference to speed this up - it will slow it down by about

--
Gitblit v1.9.1