From 0e11940a65777b8dd22d017da472c2dc373d650c Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Mon, 06 Dec 2010 09:06:44 -0500
Subject: [PATCH] - Improve performance of folder rename and delete actions. Don't get list of all folders when we need only children of the specified folder.

---
 CHANGELOG                          |    1 
 program/steps/settings/folders.inc |   16 +++++---
 program/include/rcube_imap.php     |   94 ++++++++++++++++++++++------------------------
 3 files changed, 56 insertions(+), 55 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 312c4a2..8d51add 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -15,6 +15,7 @@
 - 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
 - Fix plaintext versions of HTML messages don't contain placeholders for emotions (#1485206)
+- Improve performance of folder rename and delete actions
 
 RELEASE 0.5-BETA
 ----------------
diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index 8cb866a..7db5e54 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -3018,7 +3018,7 @@
     /**
      * Get mailbox size (size of all messages in a mailbox)
      *
-     * @param string $name Mailbox name    
+     * @param string $name Mailbox name
      * @return int Mailbox size in bytes, False on error
      */
     function get_mailbox_size($name)
@@ -3093,6 +3093,7 @@
      *
      * @param string $mbox_name Mailbox to rename
      * @param string $new_name  New mailbox name
+     *
      * @return boolean True on success
      */
     function rename_mailbox($mbox_name, $new_name)
@@ -3102,92 +3103,87 @@
         // make absolute path
         $mailbox  = $this->mod_mailbox($mbox_name);
         $abs_name = $this->mod_mailbox($new_name);
+        $delm     = $this->get_hierarchy_delimiter();
 
-        // check if mailbox is subscribed
-        $a_subscribed = $this->_list_mailboxes();
-        $subscribed   = in_array($mailbox, $a_subscribed);
-
-        // unsubscribe folder
-        if ($subscribed)
-            $this->conn->unsubscribe($mailbox);
+        // get list of subscribed folders
+        if ((strpos($mailbox, '%') === false) && (strpos($mailbox, '*') === false)) {
+            $a_subscribed = $this->_list_mailboxes('', $mbox_name . $delm . '*');
+            $subscribed   = $this->mailbox_exists($mbox_name, true);
+        }
+        else {
+            $a_subscribed = $this->_list_mailboxes();
+            $subscribed   = in_array($mailbox, $a_subscribed);
+        }
 
         if (strlen($abs_name))
             $result = $this->conn->renameFolder($mailbox, $abs_name);
 
         if ($result) {
-            $delm = $this->get_hierarchy_delimiter();
+            // unsubscribe the old folder, subscribe the new one
+            if ($subscribed) {
+                $this->conn->unsubscribe($mailbox);
+                $this->conn->subscribe($abs_name);
+            }
 
             // check if mailbox children are subscribed
-            foreach ($a_subscribed as $c_subscribed)
+            foreach ($a_subscribed as $c_subscribed) {
                 if (preg_match('/^'.preg_quote($mailbox.$delm, '/').'/', $c_subscribed)) {
                     $this->conn->unsubscribe($c_subscribed);
                     $this->conn->subscribe(preg_replace('/^'.preg_quote($mailbox, '/').'/',
                         $abs_name, $c_subscribed));
                 }
+            }
 
             // clear cache
             $this->clear_message_cache($mailbox.'.msg');
             $this->clear_cache('mailboxes');
         }
 
-        // try to subscribe it
-        if ($result && $subscribed)
-            $this->conn->subscribe($abs_name);
-
         return $result;
     }
 
 
     /**
-     * Remove mailboxes from server
+     * Remove mailbox from server
      *
-     * @param string|array $mbox_name Mailbox name(s) string/array
+     * @param string $mbox_name Mailbox name
+     *
      * @return boolean True on success
      */
     function delete_mailbox($mbox_name)
     {
-        $deleted = false;
+        $result  = false;
+        $mailbox = $this->mod_mailbox($mbox_name);
+        $delm    = $this->get_hierarchy_delimiter();
 
-        if (is_array($mbox_name))
-            $a_mboxes = $mbox_name;
-        else if (is_string($mbox_name) && strlen($mbox_name))
-            $a_mboxes = explode(',', $mbox_name);
+        // get list of folders
+        if ((strpos($mailbox, '%') === false) && (strpos($mailbox, '*') === false))
+            $sub_mboxes = $this->list_unsubscribed('', $mailbox . $delm . '*');
+        else
+            $sub_mboxes = $this->list_unsubscribed();
 
-        if (is_array($a_mboxes)) {
-            $delimiter = $this->get_hierarchy_delimiter();
-        
-            foreach ($a_mboxes as $mbox_name) {
-                $mailbox = $this->mod_mailbox($mbox_name);
-                $sub_mboxes = $this->conn->listMailboxes('', $mbox_name . $delimiter . '*');
+        // send delete command to server
+        $result = $this->conn->deleteFolder($mailbox);
 
-                // unsubscribe mailbox before deleting
-                $this->conn->unsubscribe($mailbox);
+        if ($result) {
+            // unsubscribe mailbox
+            $this->conn->unsubscribe($mailbox);
 
-                // send delete command to server
-                $result = $this->conn->deleteFolder($mailbox);
-                if ($result) {
-                    $deleted = true;
-                    $this->clear_message_cache($mailbox.'.msg');
-	            }
-
-                foreach ($sub_mboxes as $c_mbox) {
-                    if ($c_mbox != 'INBOX') {
-                        $this->conn->unsubscribe($c_mbox);
-                        $result = $this->conn->deleteFolder($c_mbox);
-                        if ($result) {
-                            $deleted = true;
-    	                    $this->clear_message_cache($c_mbox.'.msg');
-                        }
+            foreach ($sub_mboxes as $c_mbox) {
+                if (preg_match('/^'.preg_quote($mailbox.$delm, '/').'/', $c_mbox)) {
+                    $this->conn->unsubscribe($c_mbox);
+                    if ($this->conn->deleteFolder($c_mbox)) {
+	                    $this->clear_message_cache($c_mbox.'.msg');
                     }
                 }
             }
+
+            // clear mailbox-related cache
+            $this->clear_message_cache($mailbox.'.msg');
+            $this->clear_cache('mailboxes');
         }
 
-        // clear mailboxlist cache
-        if ($deleted)
-            $this->clear_cache('mailboxes');
-
-        return $deleted;
+        return $result;
     }
 
 
diff --git a/program/steps/settings/folders.inc b/program/steps/settings/folders.inc
index b90487a..1ceca74 100644
--- a/program/steps/settings/folders.inc
+++ b/program/steps/settings/folders.inc
@@ -65,17 +65,21 @@
 // delete an existing mailbox
 else if ($RCMAIL->action == 'delete-folder')
 {
-    $a_mboxes  = $IMAP->list_unsubscribed();
-    $delimiter = $IMAP->get_hierarchy_delimiter();
-  
     $mbox_utf8 = get_input_value('_mbox', RCUBE_INPUT_POST, true);
     $mbox      = rcube_charset_convert($mbox_utf8, RCMAIL_CHARSET, 'UTF7-IMAP');
 
+    // get folder's children or all folders if the name contains special characters
+    $delimiter = $IMAP->get_hierarchy_delimiter();
+    if ((strpos($mbox, '%') === false) && (strpos($mbox, '*') === false))
+        $a_mboxes  = $IMAP->list_unsubscribed('', $mbox.$delimiter.'*');
+    else
+        $a_mboxes  = $IMAP->list_unsubscribed();
+
     if (strlen($mbox))
-        $deleted = $IMAP->delete_mailbox(array($mbox));
+        $deleted = $IMAP->delete_mailbox($mbox);
 
     if ($OUTPUT->ajax_call && $deleted) {
-        // Remove folder rows
+        // Remove folder and subfolders rows
         $OUTPUT->command('remove_folder_row', $mbox_utf8);
         foreach ($a_mboxes as $folder) {
             if (preg_match('/^'. preg_quote($mbox.$delimiter, '/') .'/', $folder)) {
@@ -121,7 +125,7 @@
                     . rcube_charset_convert($foldersplit[$level], 'UTF7-IMAP');
 
                 $before = isset($folderlist[$x+1]) ? rcube_charset_convert($folderlist[$x+1], 'UTF7-IMAP') : false;
-        
+
                 $OUTPUT->command('replace_folder_row', rcube_charset_convert($oldfolder, 'UTF7-IMAP'),
                     rcube_charset_convert($folderlist[$x], 'UTF7-IMAP'), $display_rename, $before);
             }

--
Gitblit v1.9.1