summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralecpl <alec@alec.pl>2011-11-08 11:22:14 +0000
committeralecpl <alec@alec.pl>2011-11-08 11:22:14 +0000
commitaa07b2290640061a65c9f90d5f30cfc5d4ada195 (patch)
treeae52bc09831b5eac9facb0153d50d51b699594a2
parent06744da24100473aa8180cf07ec1970987d2f66b (diff)
- Fix so folders with \Noinferiors attribute aren't listed in parent selector
- Add LIST result and folder attributes cache - rcmail_render_folder_tree_select(): fix 'exceptions' parameter, add 'skip_noinferiors' option
-rw-r--r--CHANGELOG1
-rw-r--r--program/include/main.inc48
-rw-r--r--program/include/rcube_imap.php69
-rw-r--r--program/include/rcube_imap_generic.php12
-rw-r--r--program/steps/settings/edit_folder.inc3
-rw-r--r--program/steps/settings/folders.inc4
6 files changed, 83 insertions, 54 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 0e72c41e8..ffd8498cc 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
+- Fix so folders with \Noinferiors attribute aren't listed in parent selector
- Fix handling of curly brackets in URLs (#1488168)
- Fix handling of dates (birthday/anniversary) in contact data (#1488147)
- Fix error on opening searched LDAP contact (#1488144)
diff --git a/program/include/main.inc b/program/include/main.inc
index 7e31c012f..95d422d6a 100644
--- a/program/include/main.inc
+++ b/program/include/main.inc
@@ -1232,7 +1232,7 @@ function rcmail_mailbox_select($p = array())
if ($p['noselection'])
$select->add($p['noselection'], '');
- rcmail_render_folder_tree_select($a_mailboxes, $mbox, $p['maxlength'], $select, $p['realnames'], 0, $p['exceptions']);
+ rcmail_render_folder_tree_select($a_mailboxes, $mbox, $p['maxlength'], $select, $p['realnames'], 0, $p);
return $select;
}
@@ -1281,9 +1281,9 @@ function rcmail_build_folder_tree(&$arrFolders, $folder, $delm='/', $path='')
$path .= $prefix.$currentFolder;
if (!isset($arrFolders[$currentFolder])) {
- // Check \Noselect option (if options are in cache)
- if (!$virtual && ($opts = $RCMAIL->imap->mailbox_options($path))) {
- $virtual = in_array('\\Noselect', $opts);
+ // Check \Noselect attribute (if attributes are in cache)
+ if (!$virtual && ($attrs = $RCMAIL->imap->mailbox_attributes($path))) {
+ $virtual = in_array('\\Noselect', $attrs);
}
$arrFolders[$currentFolder] = array(
@@ -1402,30 +1402,40 @@ function rcmail_render_folder_tree_html(&$arrFolders, &$mbox_name, &$jslist, $at
* @access private
* @return string
*/
-function rcmail_render_folder_tree_select(&$arrFolders, &$mbox_name, $maxlength, &$select, $realnames=false, $nestLevel=0, $exceptions=array())
+function rcmail_render_folder_tree_select(&$arrFolders, &$mbox_name, $maxlength, &$select, $realnames=false, $nestLevel=0, $opts=array())
{
+ global $RCMAIL;
+
$out = '';
foreach ($arrFolders as $key => $folder) {
- if (empty($exceptions) || !in_array($folder['id'], $exceptions)) {
- if (!$realnames && ($folder_class = rcmail_folder_classname($folder['id'])))
- $foldername = rcube_label($folder_class);
- else {
- $foldername = $folder['name'];
-
- // shorten the folder name to a given length
- if ($maxlength && $maxlength>1)
- $foldername = abbreviate_string($foldername, $maxlength);
- }
-
- $select->add(str_repeat('&nbsp;', $nestLevel*4) . $foldername, $folder['id']);
+ // skip exceptions (and its subfolders)
+ if (!empty($opts['exceptions']) && in_array($folder['id'], $opts['exceptions'])) {
+ continue;
}
- else if ($nestLevel)
+
+ // skip folders in which it isn't possible to create subfolders
+ if (!empty($opts['skip_noinferiors']) && ($attrs = $RCMAIL->imap->mailbox_attributes($folder['id']))
+ && in_array('\\Noinferiors', $attrs)
+ ) {
continue;
+ }
+
+ if (!$realnames && ($folder_class = rcmail_folder_classname($folder['id'])))
+ $foldername = rcube_label($folder_class);
+ else {
+ $foldername = $folder['name'];
+
+ // shorten the folder name to a given length
+ if ($maxlength && $maxlength>1)
+ $foldername = abbreviate_string($foldername, $maxlength);
+ }
+
+ $select->add(str_repeat('&nbsp;', $nestLevel*4) . $foldername, $folder['id']);
if (!empty($folder['folders']))
$out .= rcmail_render_folder_tree_select($folder['folders'], $mbox_name, $maxlength,
- $select, $realnames, $nestLevel+1, $exceptions);
+ $select, $realnames, $nestLevel+1, $opts);
}
return $out;
diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index 43d35908f..7508acda5 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -3087,7 +3087,19 @@ class rcube_imap
*/
function list_unsubscribed($root='', $name='*', $filter=null, $rights=null, $skip_sort=false)
{
- // @TODO: caching
+ $cache_key = $root.':'.$name;
+ if (!empty($filter)) {
+ $cache_key .= ':'.(is_string($filter) ? $filter : serialize($filter));
+ }
+ $cache_key .= ':'.$rights;
+ $cache_key = 'mailboxes.list.'.md5($cache_key);
+
+ // get cached folder list
+ $a_mboxes = $this->get_cache($cache_key);
+ if (is_array($a_mboxes)) {
+ return $a_mboxes;
+ }
+
// Give plugins a chance to provide a list of mailboxes
$data = rcmail::get_instance()->plugins->exec_hook('mailboxes_list',
array('root' => $root, 'name' => $name, 'filter' => $filter, 'mode' => 'LIST'));
@@ -3109,6 +3121,11 @@ class rcube_imap
array_unshift($a_mboxes, 'INBOX');
}
+ // cache folder attributes
+ if ($root == '' && $name == '*' && empty($filter)) {
+ $this->update_cache('mailboxes.attributes', $this->conn->data['LIST']);
+ }
+
// filter folders list according to rights requirements
if ($rights && $this->get_capability('ACL')) {
$a_folders = $this->filter_rights($a_folders, $rights);
@@ -3119,6 +3136,9 @@ class rcube_imap
$a_mboxes = $this->_sort_mailbox_list($a_mboxes);
}
+ // write mailboxlist to cache
+ $this->update_cache($cache_key, $a_mboxes);
+
return $a_mboxes;
}
@@ -3450,30 +3470,29 @@ class rcube_imap
/**
- * Gets folder options from LIST response, e.g. \Noselect, \Noinferiors
+ * Gets folder attributes from LIST response, e.g. \Noselect, \Noinferiors
*
* @param string $mailbox Folder name
- * @param bool $force Set to True if options should be refreshed
- * Options are available after LIST command only
+ * @param bool $force Set to True if attributes should be refreshed
*
* @return array Options list
*/
- function mailbox_options($mailbox, $force=false)
+ function mailbox_attributes($mailbox, $force=false)
{
- if ($mailbox == 'INBOX') {
- return array();
+ // get attributes directly from LIST command
+ if (!empty($this->conn->data['LIST']) && is_array($this->conn->data['LIST'][$mailbox])) {
+ $opts = $this->conn->data['LIST'][$mailbox];
}
-
- if (!is_array($this->conn->data['LIST']) || !is_array($this->conn->data['LIST'][$mailbox])) {
- if ($force) {
- $this->conn->listMailboxes('', $mailbox);
- }
- else {
- return array();
- }
+ // get cached folder attributes
+ else if (!$force) {
+ $opts = $this->get_cache('mailboxes.attributes');
+ $opts = $opts[$mailbox];
}
- $opts = $this->conn->data['LIST'][$mailbox];
+ if (!is_array($opts)) {
+ $this->conn->listMailboxes('', $mailbox);
+ $opts = $this->conn->data['LIST'][$mailbox];
+ }
return is_array($opts) ? $opts : array();
}
@@ -3556,17 +3575,17 @@ class rcube_imap
}
}
- $options['name'] = $mailbox;
- $options['options'] = $this->mailbox_options($mailbox, true);
- $options['namespace'] = $this->mailbox_namespace($mailbox);
- $options['rights'] = $acl && !$options['is_root'] ? (array)$this->my_rights($mailbox) : array();
- $options['special'] = in_array($mailbox, $this->default_folders);
+ $options['name'] = $mailbox;
+ $options['attributes'] = $this->mailbox_attributes($mailbox, true);
+ $options['namespace'] = $this->mailbox_namespace($mailbox);
+ $options['rights'] = $acl && !$options['is_root'] ? (array)$this->my_rights($mailbox) : array();
+ $options['special'] = in_array($mailbox, $this->default_folders);
// Set 'noselect' and 'norename' flags
- if (is_array($options['options'])) {
- foreach ($options['options'] as $opt) {
- $opt = strtolower($opt);
- if ($opt == '\noselect' || $opt == '\nonexistent') {
+ if (is_array($options['attributes'])) {
+ foreach ($options['attributes'] as $attrib) {
+ $attrib = strtolower($attrib);
+ if ($attrib == '\noselect' || $attrib == '\nonexistent') {
$options['noselect'] = true;
}
}
diff --git a/program/include/rcube_imap_generic.php b/program/include/rcube_imap_generic.php
index 5c7a41c73..f200e17ca 100644
--- a/program/include/rcube_imap_generic.php
+++ b/program/include/rcube_imap_generic.php
@@ -2258,13 +2258,11 @@ class rcube_imap_generic
}
// Add to options array
- if (!empty($opts)) {
- if (empty($this->data['LIST'][$mailbox]))
- $this->data['LIST'][$mailbox] = $opts;
- else
- $this->data['LIST'][$mailbox] = array_unique(array_merge(
- $this->data['LIST'][$mailbox], $opts));
- }
+ if (empty($this->data['LIST'][$mailbox]))
+ $this->data['LIST'][$mailbox] = $opts;
+ else if (!empty($opts))
+ $this->data['LIST'][$mailbox] = array_unique(array_merge(
+ $this->data['LIST'][$mailbox], $opts));
}
// * STATUS <mailbox> (<result>)
else if ($cmd == 'STATUS') {
diff --git a/program/steps/settings/edit_folder.inc b/program/steps/settings/edit_folder.inc
index 36a4b28ba..e9566f7aa 100644
--- a/program/steps/settings/edit_folder.inc
+++ b/program/steps/settings/edit_folder.inc
@@ -119,7 +119,8 @@ function rcmail_folder_form($attrib)
'realnames' => false,
'maxlength' => 150,
'unsubscribed' => true,
- 'exceptions' => array($mbox_imap),
+ 'skip_noinferiors' => true,
+ 'exceptions' => array($mbox_imap),
));
$form['props']['fieldsets']['location']['content']['path'] = array(
diff --git a/program/steps/settings/folders.inc b/program/steps/settings/folders.inc
index 206f62c60..77cbb5571 100644
--- a/program/steps/settings/folders.inc
+++ b/program/steps/settings/folders.inc
@@ -283,8 +283,8 @@ function rcube_subscription_form($attrib)
}
if (!$protected) {
- $opts = $IMAP->mailbox_options($folder['id']);
- $noselect = in_array('\\Noselect', $opts);
+ $attrs = $IMAP->mailbox_attributes($folder['id']);
+ $noselect = in_array('\\Noselect', $attrs);
}
$disabled = (($protected && $subscribed) || $noselect);