From 94bdcce081eb4b080fcaab74bc8466237c2dfcd4 Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Fri, 06 May 2011 04:14:48 -0400
Subject: [PATCH] - Add possibility (for plugins) to filter folders lists by some additional criteria (e.g. folder type)

---
 skins/default/templates/mail.html         |    2 
 program/include/main.inc                  |   12 ++++-
 program/include/rcube_imap.php            |   77 ++++++++++++++++++++++++++------------
 program/steps/mail/compose.inc            |    5 ++
 program/steps/mail/check_recent.inc       |    2 
 program/steps/mail/getunread.inc          |    2 
 skins/default/templates/messageerror.html |    2 
 skins/default/templates/message.html      |    2 
 8 files changed, 71 insertions(+), 33 deletions(-)

diff --git a/program/include/main.inc b/program/include/main.inc
index baaca65..00069c2 100644
--- a/program/include/main.inc
+++ b/program/include/main.inc
@@ -1170,13 +1170,16 @@
   if ($type=='ul' && !$attrib['id'])
     $attrib['id'] = 'rcmboxlist';
 
+  if (empty($attrib['folder_name']))
+    $attrib['folder_name'] = '*';
+
   // get mailbox list
   $mbox_name = $RCMAIL->imap->get_mailbox_name();
   
   // build the folders tree
   if (empty($a_mailboxes)) {
     // get mailbox list
-    $a_folders = $RCMAIL->imap->list_mailboxes();
+    $a_folders = $RCMAIL->imap->list_mailboxes('', $attrib['folder_name'], $attrib['folder_filter']);
     $delimiter = $RCMAIL->imap->get_hierarchy_delimiter();
     $a_mailboxes = array();
 
@@ -1223,10 +1226,13 @@
   $p += array('maxlength' => 100, 'realnames' => false);
   $a_mailboxes = array();
 
+  if (empty($p['folder_name']))
+    $p['folder_name'] = '*';
+
   if ($p['unsubscribed'])
-    $list = $RCMAIL->imap->list_unsubscribed();
+    $list = $RCMAIL->imap->list_unsubscribed('', $p['folder_name'], $p['folder_filter']);
   else
-    $list = $RCMAIL->imap->list_mailboxes();
+    $list = $RCMAIL->imap->list_mailboxes('', $p['folder_name'], $p['folder_filter']);
 
   $delimiter = $RCMAIL->imap->get_hierarchy_delimiter();
 
diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index d7100a6..484e70b 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -3014,18 +3014,20 @@
      * Public method for listing subscribed folders
      *
      * @param   string  $root   Optional root folder
-     * @param   string  $filter Optional filter for mailbox listing
+     * @param   string  $name   Optional name pattern
+     * @param   string  $filter Optional filter
      *
      * @return  array   List of mailboxes/folders
      * @access  public
      */
-    function list_mailboxes($root='', $filter='*')
+    function list_mailboxes($root='', $name='*', $filter=null)
     {
-        $a_mboxes = $this->_list_mailboxes($root, $filter);
+        $a_mboxes = $this->_list_mailboxes($root, $name, $filter);
 
         // INBOX should always be available
-        if (!in_array('INBOX', $a_mboxes))
+        if ((!$filter || $filter == 'mail') && !in_array('INBOX', $a_mboxes)) {
             array_unshift($a_mboxes, 'INBOX');
+        }
 
         // sort mailboxes
         $a_mboxes = $this->_sort_mailbox_list($a_mboxes);
@@ -3038,23 +3040,31 @@
      * Private method for mailbox listing
      *
      * @param   string  $root   Optional root folder
-     * @param   string  $filter Optional filter for mailbox listing
+     * @param   string  $name   Optional name pattern
+     * @param   mixed   $filter Optional filter
+     *
      * @return  array   List of mailboxes/folders
      * @see     rcube_imap::list_mailboxes()
      * @access  private
      */
-    private function _list_mailboxes($root='', $filter='*')
+    private function _list_mailboxes($root='', $name='*', $filter=null)
     {
+        $cache_key = 'mailboxes';
+        if (!empty($filter)) {
+            $cache_key .= ':'.substr((is_string($filter) ? $filter : serialize($filter)), 0, 90);
+        }
+
         // get cached folder list
-        $a_mboxes = $this->get_cache('mailboxes');
-        if (is_array($a_mboxes))
+        $a_mboxes = $this->get_cache($cache_key);
+        if (is_array($a_mboxes)) {
             return $a_mboxes;
+        }
 
         $a_defaults = $a_out = array();
 
         // Give plugins a chance to provide a list of mailboxes
         $data = rcmail::get_instance()->plugins->exec_hook('mailboxes_list',
-            array('root' => $root, 'filter' => $filter, 'mode' => 'LSUB'));
+            array('root' => $root, 'name' => $name, 'filter' => $filter, 'mode' => 'LSUB'));
 
         if (isset($data['folders'])) {
             $a_folders = $data['folders'];
@@ -3065,7 +3075,7 @@
             // #1486225: Some dovecot versions returns wrong result using LIST-EXTENDED
             if (!$config->get('imap_force_lsub') && $this->get_capability('LIST-EXTENDED')) {
                 // This will also set mailbox options, LSUB doesn't do that
-                $a_folders = $this->conn->listMailboxes($root, $filter,
+                $a_folders = $this->conn->listMailboxes($root, $name,
                     NULL, array('SUBSCRIBED'));
 
                 // remove non-existent folders
@@ -3081,15 +3091,16 @@
             }
             // retrieve list of folders from IMAP server using LSUB
             else {
-                $a_folders = $this->conn->listSubscribed($root, $filter);
+                $a_folders = $this->conn->listSubscribed($root, $name);
             }
         }
 
-        if (!is_array($a_folders) || !sizeof($a_folders))
+        if (!is_array($a_folders) || !sizeof($a_folders)) {
             $a_folders = array();
+        }
 
         // write mailboxlist to cache
-        $this->update_cache('mailboxes', $a_folders);
+        $this->update_cache($cache_key, $a_folders);
 
         return $a_folders;
     }
@@ -3099,21 +3110,24 @@
      * Get a list of all folders available on the IMAP server
      *
      * @param string $root   IMAP root dir
-     * @param string $filter Optional filter for mailbox listing
+     * @param string  $name   Optional name pattern
+     * @param mixed   $filter Optional filter
+     *
      * @return array Indexed array with folder names
      */
-    function list_unsubscribed($root='', $filter='*')
+    function list_unsubscribed($root='', $name='*', $filter=null)
     {
+        // @TODO: caching
         // Give plugins a chance to provide a list of mailboxes
         $data = rcmail::get_instance()->plugins->exec_hook('mailboxes_list',
-            array('root' => $root, 'filter' => $filter, 'mode' => 'LIST'));
+            array('root' => $root, 'name' => $name, 'filter' => $filter, 'mode' => 'LIST'));
 
         if (isset($data['folders'])) {
             $a_mboxes = $data['folders'];
         }
         else {
             // retrieve list of folders from IMAP server
-            $a_mboxes = $this->conn->listMailboxes($root, $filter);
+            $a_mboxes = $this->conn->listMailboxes($root, $name);
         }
 
         if (!is_array($a_mboxes)) {
@@ -3121,8 +3135,9 @@
         }
 
         // INBOX should always be available
-        if (!in_array('INBOX', $a_mboxes))
+        if ((!$filter || $filter == 'mail') && !in_array('INBOX', $a_mboxes)) {
             array_unshift($a_mboxes, 'INBOX');
+        }
 
         // filter folders and sort them
         $a_mboxes = $this->_sort_mailbox_list($a_mboxes);
@@ -3263,7 +3278,7 @@
 
             // clear cache
             $this->clear_message_cache($mailbox.'.msg');
-            $this->clear_cache('mailboxes');
+            $this->clear_cache('/^mailboxes.*/', true);
         }
 
         return $result;
@@ -3305,7 +3320,7 @@
 
             // clear mailbox-related cache
             $this->clear_message_cache($mailbox.'.msg');
-            $this->clear_cache('mailboxes');
+            $this->clear_cache('/^mailboxes.*/', true);
         }
 
         return $result;
@@ -3777,22 +3792,36 @@
     /**
      * Clears the cache.
      *
-     * @param string $key Cache key
+     * @param string  $key          Cache key name or pattern
+     * @param boolean $pattern_mode Enable it to clear all keys with name
+     *                              matching PREG pattern in $key
      * @access public
      */
-    function clear_cache($key=NULL)
+    function clear_cache($key=null, $pattern_mode=false)
     {
         if (!$this->caching_enabled)
             return;
 
-        if ($key===NULL) {
-            foreach ($this->cache as $key => $data)
+        if ($key === null) {
+            foreach (array_keys($this->cache) as $key)
                 $this->_clear_cache_record($key);
 
             $this->cache = array();
             $this->cache_changed = false;
             $this->cache_changes = array();
         }
+        else if ($pattern_mode) {
+            foreach (array_keys($this->cache) as $k) {
+                if (preg_match($key, $k)) {
+                    $this->_clear_cache_record($k);
+                    $this->cache_changes[$k] = false;
+                    unset($this->cache[$key]);
+                }
+            }
+            if (!count($this->cache)) {
+                $this->cache_changed = false;
+            }
+        }
         else {
             $this->_clear_cache_record($key);
             $this->cache_changes[$key] = false;
diff --git a/program/steps/mail/check_recent.inc b/program/steps/mail/check_recent.inc
index fc26d63..c636e45 100644
--- a/program/steps/mail/check_recent.inc
+++ b/program/steps/mail/check_recent.inc
@@ -24,7 +24,7 @@
 
 // list of folders to check
 if ($check_all) {
-    $a_mailboxes = $IMAP->list_mailboxes();
+    $a_mailboxes = $IMAP->list_mailboxes('', '*', 'mail');
 }
 else {
     $a_mailboxes = (array) $current;
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index 531e698..4fe9244 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -1297,7 +1297,10 @@
 function rcmail_store_target_selection($attrib)
 {
   $attrib['name'] = '_store_target';
-  $select = rcmail_mailbox_select(array_merge($attrib, array('noselection' => '- '.rcube_label('dontsave').' -')));
+  $select = rcmail_mailbox_select(array_merge($attrib, array(
+    'noselection' => '- '.rcube_label('dontsave').' -',
+    'folder_filter' => 'mail'
+  )));
   return $select->show($_SESSION['compose']['param']['sent_mbox'], $attrib);
 }
 
diff --git a/program/steps/mail/getunread.inc b/program/steps/mail/getunread.inc
index 4ae7e05..27ae5f7 100644
--- a/program/steps/mail/getunread.inc
+++ b/program/steps/mail/getunread.inc
@@ -19,7 +19,7 @@
 
 */
 
-$a_folders = $IMAP->list_mailboxes();
+$a_folders = $IMAP->list_mailboxes('', '*', 'mail');
 
 if (!empty($a_folders))
 {
diff --git a/skins/default/templates/mail.html b/skins/default/templates/mail.html
index d390962..597a905 100644
--- a/skins/default/templates/mail.html
+++ b/skins/default/templates/mail.html
@@ -28,7 +28,7 @@
 <div id="mailboxlist-container">
 <div id="mailboxlist-title" class="boxtitle"><roundcube:label name="mailboxlist" /></div>
 <div class="boxlistcontent">
-<roundcube:object name="mailboxlist" id="mailboxlist" />
+<roundcube:object name="mailboxlist" id="mailboxlist" folder_filter="mail" />
 </div>
 <div class="boxfooter">
   <roundcube:button name="mailboxmenulink" id="mailboxmenulink" type="link" title="folderactions" class="button groupactions" onclick="rcmail_ui.show_popup('mailboxmenu');return false" content=" " />
diff --git a/skins/default/templates/message.html b/skins/default/templates/message.html
index d59210c..8e4824d 100644
--- a/skins/default/templates/message.html
+++ b/skins/default/templates/message.html
@@ -28,7 +28,7 @@
 <roundcube:button command="delete" type="link" class="buttonPas delete" classAct="button delete" classSel="button deleteSel" title="deletemessage" content=" " />
 <roundcube:container name="toolbar" id="messagetoolbar" />
 <roundcube:button name="messagemenulink" id="messagemenulink" type="link" class="button messagemenu" title="messageactions" onclick="rcmail_ui.show_popup('messagemenu');return false" content=" " />
-<roundcube:object name="mailboxlist" type="select" noSelection="moveto" maxlength="25" onchange="rcmail.command('moveto', this.options[this.selectedIndex].value)" class="mboxlist" />
+<roundcube:object name="mailboxlist" type="select" noSelection="moveto" maxlength="25" onchange="rcmail.command('moveto', this.options[this.selectedIndex].value)" class="mboxlist" folder_filter="mail" />
 </div>
 
 <roundcube:include file="/includes/replyallmenu.html" />
diff --git a/skins/default/templates/messageerror.html b/skins/default/templates/messageerror.html
index 559d166..9af45f4 100644
--- a/skins/default/templates/messageerror.html
+++ b/skins/default/templates/messageerror.html
@@ -42,7 +42,7 @@
 <div id="mailboxlist-container">
 <div class="boxtitle"><roundcube:label name="mailboxlist" /></div>
 <div class="boxlistcontent">
-<roundcube:object name="mailboxlist" id="mailboxlist" maxlength="25" />
+<roundcube:object name="mailboxlist" id="mailboxlist" folder_filter="mail" />
 </div>
 <div class="boxfooter">
   <roundcube:button name="mailboxmenulink" id="mailboxmenulink" type="link" title="folderactions" class="button groupactions" onclick="rcmail_ui.show_popup('mailboxmenu');return false" content=" " />

--
Gitblit v1.9.1