From e232acbfde30e27101f84da7f0a617f8a8522512 Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Fri, 03 Dec 2010 07:25:49 -0500
Subject: [PATCH] - Improve performance of moving or copying of all messages in a folder (use CLOSE intead of EXPUNGE) - Code cleanup + added more phpdoc comments

---
 CHANGELOG                              |    2 
 program/include/rcube_imap.php         |   15 ++-
 program/include/rcube_imap_generic.php |  228 +++++++++++++++++++++++++++++++--------------
 3 files changed, 170 insertions(+), 75 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 6044c02..8f9b0b5 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -12,6 +12,8 @@
 - Fix invalid Request when creating a folder (#1487443)
 - Add folder size and quota indicator in folder manager (#1485780)
 - Add possibility to move a subfolder into root folder (#1486791)
+- Fix copying all messages in a folder copies only messages from current page
+- Improve performance of moving or copying of all messages in a folder
 
 RELEASE 0.5-BETA
 ----------------
diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index dd9f81b..bf88c29 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -185,7 +185,7 @@
      */
     function close()
     {
-        $this->conn->close();
+        $this->conn->closeConnection();
         $this->write_cache();
     }
 
@@ -198,7 +198,7 @@
      */
     function reconnect()
     {
-        $this->close();
+        $this->closeConnection();
         $this->connect($this->host, $this->user, $this->pass, $this->port, $this->ssl);
 
         // issue SELECT command to restore connection status
@@ -617,7 +617,7 @@
         }
         // RECENT count is fetched a bit different
         else if ($mode == 'RECENT') {
-            $count = $this->conn->checkForRecent($mailbox);
+            $count = $this->conn->countRecent($mailbox);
         }
         // use SEARCH for message counting
         else if ($this->skip_deleted) {
@@ -2582,6 +2582,7 @@
 
         // send expunge command in order to have the moved message
         // really deleted from the source mailbox
+$aa = rcube_timer();
         if ($moved) {
             $this->_expunge($from_mbox, false, $uids);
             $this->_clear_messagecount($from_mbox);
@@ -2591,7 +2592,7 @@
         else if ($config->get('delete_always', false) && $tbox == $config->get('trash_mbox')) {
             $moved = $this->delete_message($uids, $fbox);
         }
-
+rcube_print_time($aa);
         if ($moved) {
             // unset threads internal cache
             unset($this->icache['threads']);
@@ -2774,7 +2775,11 @@
         else
             $a_uids = NULL;
 
-        $result = $this->conn->expunge($mailbox, $a_uids);
+        // CLOSE(+SELECT) should be faster than EXPUNGE
+        if (empty($a_uids) || $a_uids == '1:*')
+            $result = $this->conn->close();
+        else
+            $result = $this->conn->expunge($mailbox, $a_uids);
 
         if ($result && $clear_cache) {
             $this->clear_message_cache($mailbox.'.msg');
diff --git a/program/include/rcube_imap_generic.php b/program/include/rcube_imap_generic.php
index 16c9d4a..d3742fe 100644
--- a/program/include/rcube_imap_generic.php
+++ b/program/include/rcube_imap_generic.php
@@ -683,7 +683,7 @@
 			    $error = sprintf("Empty startup greeting (%s:%d)", $host, $this->prefs['port']);
 
 	        $this->setError(self::ERROR_BAD, $error);
-            $this->close();
+            $this->closeConnection();
 	        return false;
 	    }
 
@@ -700,13 +700,13 @@
                	$res = $this->execute('STARTTLS');
 
                 if ($res[0] != self::ERROR_OK) {
-                    $this->close();
+                    $this->closeConnection();
                     return false;
                 }
 
 			    if (!stream_socket_enable_crypto($this->fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
 				    $this->setError(self::ERROR_BAD, "Unable to negotiate TLS");
-                    $this->close();
+                    $this->closeConnection();
 				    return false;
 			    }
 
@@ -738,7 +738,7 @@
             // Prevent from sending credentials in plain text when connection is not secure
 		    if ($auth_method == 'LOGIN' && $this->getCapability('LOGINDISABLED')) {
 			    $this->setError(self::ERROR_BAD, "Login disabled by IMAP server");
-                $this->close();
+                $this->closeConnection();
 			    return false;
             }
             // replace AUTH with CRAM-MD5 for backward compat.
@@ -778,8 +778,7 @@
 		    return true;
         }
 
-        // Close connection
-        $this->close();
+        $this->closeConnection();
 
         return false;
     }
@@ -789,7 +788,7 @@
 		return ($this->fp && $this->logged) ? true : false;
     }
 
-    function close()
+    function closeConnection()
     {
 	    if ($this->putLine($this->nextTag() . ' LOGOUT')) {
     	    $this->readReply();
@@ -799,6 +798,14 @@
 		$this->fp = false;
     }
 
+    /**
+     * Executes SELECT command (if mailbox is already not in selected state)
+     *
+     * @param string $mailbox Mailbox name
+     *
+     * @return boolean True on success, false on error
+     * @access public
+     */
     function select($mailbox)
     {
 	    if (!strlen($mailbox)) {
@@ -842,7 +849,7 @@
     }
 
     /**
-     * Executes STATUS comand
+     * Executes STATUS command
      *
      * @param string $mailbox Mailbox name
      * @param array  $items   Additional requested item names. By default
@@ -887,21 +894,133 @@
         return false;
     }
 
-    function checkForRecent($mailbox)
+    /**
+     * Executes EXPUNGE command
+     *
+     * @param string $mailbox  Mailbox name
+     * @param string $messages Message UIDs to expunge
+     *
+     * @return boolean True on success, False on error
+     * @access public
+     */
+    function expunge($mailbox, $messages=NULL)
     {
-	    if (!strlen($mailbox)) {
-		    $mailbox = 'INBOX';
-	    }
+	    if (!$this->select($mailbox)) {
+            return false;
+        }
 
-	    $this->select($mailbox);
+        // Clear internal status cache
+        unset($this->data['STATUS:'.$mailbox]);
 
-	    if ($this->selected == $mailbox) {
-		    return $this->data['RECENT'];
-	    }
+		if ($messages)
+			$result = $this->execute('UID EXPUNGE', array($messages), self::COMMAND_NORESPONSE);
+		else
+			$result = $this->execute('EXPUNGE', null, self::COMMAND_NORESPONSE);
+
+		if ($result == self::ERROR_OK) {
+			$this->selected = ''; // state has changed, need to reselect
+			return true;
+		}
 
 	    return false;
     }
 
+    /**
+     * Executes CLOSE command
+     *
+     * @return boolean True on success, False on error
+     * @access public
+     * @since 0.5
+     */
+    function close()
+    {
+        $result = $this->execute('CLOSE', NULL, self::COMMAND_NORESPONSE);
+
+        if ($result == self::ERROR_OK) {
+            $this->selected = '';
+            return true;
+        }
+
+	    return false;
+    }
+
+    /**
+     * Executes SUBSCRIBE command
+     *
+     * @param string $mailbox Mailbox name
+     *
+     * @return boolean True on success, False on error
+     * @access public
+     */
+    function subscribe($mailbox)
+    {
+	    $result = $this->execute('SUBSCRIBE', array($this->escape($mailbox)),
+	        self::COMMAND_NORESPONSE);
+
+	    return ($result == self::ERROR_OK);
+    }
+
+    /**
+     * Executes UNSUBSCRIBE command
+     *
+     * @param string $mailbox Mailbox name
+     *
+     * @return boolean True on success, False on error
+     * @access public
+     */
+    function unsubscribe($mailbox)
+    {
+	    $result = $this->execute('UNSUBSCRIBE', array($this->escape($mailbox)),
+	        self::COMMAND_NORESPONSE);
+
+	    return ($result == self::ERROR_OK);
+    }
+
+    /**
+     * Executes DELETE command
+     *
+     * @param string $mailbox Mailbox name
+     *
+     * @return boolean True on success, False on error
+     * @access public
+     */
+    function deleteFolder($mailbox)
+    {
+        $result = $this->execute('DELETE', array($this->escape($mailbox)),
+	        self::COMMAND_NORESPONSE);
+
+	    return ($result == self::ERROR_OK);
+    }
+
+    /**
+     * Removes all messages in a folder
+     *
+     * @param string $mailbox Mailbox name
+     *
+     * @return boolean True on success, False on error
+     * @access public
+     */
+    function clearFolder($mailbox)
+    {
+	    $num_in_trash = $this->countMessages($mailbox);
+	    if ($num_in_trash > 0) {
+		    $this->delete($mailbox, '1:*');
+	    }
+
+        $res = $this->close();
+//	    $res = $this->expunge($mailbox);
+
+	    return $res;
+    }
+
+    /**
+     * Returns count of all messages in a folder
+     *
+     * @param string $mailbox Mailbox name
+     *
+     * @return int Number of messages, False on error
+     * @access public
+     */
     function countMessages($mailbox, $refresh = false)
     {
 	    if ($refresh) {
@@ -925,6 +1044,29 @@
         }
 
         return false;
+    }
+
+    /**
+     * Returns count of messages with \Recent flag in a folder
+     *
+     * @param string $mailbox Mailbox name
+     *
+     * @return int Number of messages, False on error
+     * @access public
+     */
+    function countRecent($mailbox)
+    {
+	    if (!strlen($mailbox)) {
+		    $mailbox = 'INBOX';
+	    }
+
+	    $this->select($mailbox);
+
+	    if ($this->selected == $mailbox) {
+		    return $this->data['RECENT'];
+	    }
+
+	    return false;
     }
 
     /**
@@ -1565,27 +1707,6 @@
 	    return $result;
     }
 
-    function expunge($mailbox, $messages=NULL)
-    {
-	    if (!$this->select($mailbox)) {
-            return false;
-        }
-
-        // Clear internal status cache
-        unset($this->data['STATUS:'.$mailbox]);
-
-		if ($messages)
-			$result = $this->execute('UID EXPUNGE', array($messages), self::COMMAND_NORESPONSE);
-		else
-			$result = $this->execute('EXPUNGE', null, self::COMMAND_NORESPONSE);
-
-		if ($result == self::ERROR_OK) {
-			$this->selected = ''; // state has changed, need to reselect
-			return true;
-		}
-
-	    return false;
-    }
 
     function modFlag($mailbox, $messages, $flag, $mod)
     {
@@ -2151,39 +2272,6 @@
 	        self::COMMAND_NORESPONSE);
 
 		return ($result == self::ERROR_OK);
-    }
-
-    function deleteFolder($mailbox)
-    {
-        $result = $this->execute('DELETE', array($this->escape($mailbox)),
-	        self::COMMAND_NORESPONSE);
-
-	    return ($result == self::ERROR_OK);
-    }
-
-    function clearFolder($mailbox)
-    {
-	    $num_in_trash = $this->countMessages($mailbox);
-	    if ($num_in_trash > 0) {
-		    $this->delete($mailbox, '1:*');
-	    }
-	    return ($this->expunge($mailbox) >= 0);
-    }
-
-    function subscribe($mailbox)
-    {
-	    $result = $this->execute('SUBSCRIBE', array($this->escape($mailbox)),
-	        self::COMMAND_NORESPONSE);
-
-	    return ($result == self::ERROR_OK);
-    }
-
-    function unsubscribe($mailbox)
-    {
-	    $result = $this->execute('UNSUBSCRIBE', array($this->escape($mailbox)),
-	        self::COMMAND_NORESPONSE);
-
-	    return ($result == self::ERROR_OK);
     }
 
     function append($mailbox, &$message)

--
Gitblit v1.9.1