From: Michael M Slusarz Date: Wed, 11 Aug 2010 18:37:53 +0000 (-0600) Subject: Add IMP_Imap_Tree_Element::. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=bd0035ec69fbc02d17a379ad01cb943fcd74795d;p=horde.git Add IMP_Imap_Tree_Element::. Since we don't need all information every time we access mailbox element information, this adds substantial overhead. Instead, convert the return from IMP_Imap_Tree#element() to a IMP_Imap_Tree_Element object which does most of the necessary overhead only when the data is actually accessed. Clean up some things while doing this. Namely, IMP_Imap_Tree#build() is essentially duplicative of the more flexible IMP_Imap_Tree#listFolders() so ax the former. --- diff --git a/imp/folders-mimp.php b/imp/folders-mimp.php index 19b2d3b90..7a94e7532 100644 --- a/imp/folders-mimp.php +++ b/imp/folders-mimp.php @@ -33,14 +33,16 @@ $showAll = (!$subscribe || $_SESSION['imp']['showunsub']); /* Initialize the IMP_Imap_Tree object. */ $imptree = $injector->getInstance('IMP_Imap_Tree'); -$mask = IMP_Imap_Tree::NEXT_SHOWCLOSED; +$mask = IMP_Imap_Tree::FLIST_ELT; /* Toggle subscribed view, if necessary. */ if ($subscribe && Horde_Util::getFormData('ts')) { $showAll = !$showAll; $_SESSION['imp']['showunsub'] = $showAll; $imptree->showUnsubscribed($showAll); - $mask |= IMP_Imap_Tree::NEXT_SHOWSUB; + if ($showAll) { + $mask |= IMP_Imap_Tree::FLIST_UNSUB; + } } /* Initialize Horde_Template. */ @@ -48,13 +50,13 @@ $t = $injector->createInstance('Horde_Template'); /* Start iterating through the list of mailboxes, displaying them. */ $rows = array(); -$tree_ob = $imptree->build($mask); -foreach ($tree_ob[0] as $val) { +foreach ($imptree->folderList($mask) as $val) { + $poll_info = $val->poll_info; $rows[] = array( - 'level' => str_repeat(' ', $val['level'] * 2), - 'label' => htmlspecialchars(Horde_String::abbreviate($val['base_elt']['l'], 30 - ($val['level'] * 2))), - 'link' => (empty($val['container']) ? IMP::generateIMPUrl('mailbox-mimp.php', $val['value']) : null), - 'msgs' => (isset($val['msgs']) ? ($val['unseen'] . '/' . $val['msgs']) : null) + 'level' => str_repeat(' ', $val->level * 2), + 'label' => htmlspecialchars(Horde_String::abbreviate($val->label, 30 - ($val->level * 2))), + 'link' => ($val->container ? null : IMP::generateIMPUrl('mailbox-mimp.php', $val->value)), + 'msgs' => (isset($poll_info->msgs) ? ($poll_info->unseen . '/' . $poll_info->msgs) : null) ); } $t->set('rows', $rows); diff --git a/imp/folders.php b/imp/folders.php index d043ce858..c989b8703 100644 --- a/imp/folders.php +++ b/imp/folders.php @@ -357,16 +357,19 @@ if ($_SESSION['imp']['file_upload'] && ($actionID == 'import_mbox')) { } /* Build the folder tree. */ -list($raw_rows, $newmsgs) = $imaptree->build(); +$mask = IMP_Imap_Tree::FLIST_CONTAINER | + IMP_Imap_Tree::FLIST_VFOLDER | + IMP_Imap_Tree::FLIST_ELT | + IMP_Imap_Tree::FLIST_EXPANDED; +$raw_rows = $imaptree->folderList($mask); /* Build the list of display names. */ -reset($raw_rows); $displayNames = $fullNames = array(); -while (list($k, $r) = each($raw_rows)) { - $displayNames[] = $r['display']; +foreach ($raw_rows as $k => $r) { + $displayNames[] = $r->display; - $tmp = IMP::displayFolder($r['value'], true); - if ($tmp != $r['display']) { + $tmp = IMP::displayFolder($r->value, true); + if ($tmp != $r->display) { $fullNames[$k] = $tmp; } } @@ -418,54 +421,72 @@ $a_template->set('help', Horde_Help::link('imp', 'folder-options')); $a_template->set('expand_all', Horde::widget($folders_url_ob->copy()->add(array('actionID' => 'expand_all_folders', 'folders_token' => $folders_token)), _("Expand All Folders"), 'widget', '', '', _("Expand All"), true)); $a_template->set('collapse_all', Horde::widget($folders_url_ob->copy()->add(array('actionID' => 'collapse_all_folders', 'folders_token' => $folders_token)), _("Collapse All Folders"), 'widget', '', '', _("Collapse All"), true)); -/* Check to see if user wants new mail notification */ -if (!empty($newmsgs)) { - /* Open the mailbox R/W so we ensure the 'recent' flags are cleared from - * the current mailbox. */ - foreach ($newmsgs as $mbox => $nm) { - $injector->getInstance('IMP_Imap')->getOb()->openMailbox($mbox, Horde_Imap_Client::OPEN_READWRITE); - } - - IMP::newmailAlerts($newmsgs); -} - /* Get the tree images. */ $imp_ui_folder = new IMP_Ui_Folder(); $tree_imgs = $imp_ui_folder->getTreeImages($raw_rows, array('expand_url' => $folders_url_ob)); /* Add some further information to the $raw_rows array. */ -$rows = array(); +$newmsgs = $rows = array(); $name_url = Horde::applicationUrl('mailbox.php')->add('no_newmail_popup', 1); $rowct = 0; foreach ($raw_rows as $key => $val) { - $val['nocheckbox'] = !empty($val['vfolder']); - if (!empty($val['vfolder']) && $val['editvfolder']) { + $row = array(); + + $row['nocheckbox'] = !empty($val->vfolder); + if (!empty($val->vfolder) && $val->editvfolder) { $imp_search = $injector->getInstance('IMP_Search'); - $val['delvfolder'] = $imp_search->deleteUrl($val['value'])->link(array('title' => _("Delete Virtual Folder"))) . _("Delete") . ''; - $val['editvfolder'] = $imp_search->editUrl($val['value'])->link(array('title' => _("Edit Virtual Folder"))) . _("Edit") . ''; + $row['delvfolder'] = $imp_search->deleteUrl($val->value)->link(array('title' => _("Delete Virtual Folder"))) . _("Delete") . ''; + $row['editvfolder'] = $imp_search->editUrl($val->value)->link(array('title' => _("Edit Virtual Folder"))) . _("Edit") . ''; } - $val['cname'] = (++$rowct % 2) ? 'item0' : 'item1'; + $row['cname'] = (++$rowct % 2) + ? 'item0' + : 'item1'; - /* Highlight line differently if folder/mailbox is unsubscribed. */ - if ($showAll && - $subscribe && - !$val['container'] && - !$imaptree->isSubscribed($val['base_elt'])) { - $val['cname'] .= ' folderunsub'; - } + if ($val->container) { + $row['name'] = $val->name; + } else { + /* Highlight line differently if folder/mailbox is unsubscribed. */ + if ($showAll && $subscribe && !$val->sub) { + $row['cname'] .= ' folderunsub'; + } + + $row['name'] = $val->name; + + if ($val->polled) { + $row['polled'] = true; - if (!$val['container']) { - if (!empty($val['unseen'])) { - $val['name'] = '' . $val['name'] . ''; + $poll_info = $val->poll_info; + if ($poll_info->recent) { + $newmsgs[$val->value] = $poll_info->recent; + } + + if ($poll_info->unseen) { + $row['name'] = '' . $val->name . ''; + } + + $row['msgs'] = $poll_info->msgs; + $row['unseen'] = $poll_info->unseen; } - $val['name'] = $name_url->copy()->add('mailbox', $val['value'])->link(array('title' => $val['vfolder'] ? $val['base_elt']['l'] : $val['display'])) . $val['name'] . ''; + + $row['name'] = $name_url->copy()->add('mailbox', $val->value)->link(array('title' => $val->vfolder ? $val->label : $val->display)) . $row['name'] . ''; } - $val['line'] = $tree_imgs[$key]; + $row['line'] = $tree_imgs[$key]; + + $rows[] = $row; +} + +/* Check to see if user wants new mail notification */ +if (!empty($newmsgs)) { + /* Open the mailbox R/W so we ensure the 'recent' flags are cleared from + * the current mailbox. */ + foreach ($newmsgs as $mbox => $nm) { + $injector->getInstance('IMP_Imap')->getOb()->openMailbox($mbox, Horde_Imap_Client::OPEN_READWRITE); + } - $rows[] = $val; + IMP::newmailAlerts($newmsgs); } /* Render the rows now. */ diff --git a/imp/lib/Ajax/Application.php b/imp/lib/Ajax/Application.php index ef03162ff..0935bf449 100644 --- a/imp/lib/Ajax/Application.php +++ b/imp/lib/Ajax/Application.php @@ -1953,7 +1953,7 @@ class IMP_Ajax_Application extends Horde_Core_Ajax_Application if (!empty($changes['a'])) { $result['a'] = array(); foreach ($changes['a'] as $val) { - $result['a'][] = $this->_createMailboxElt(is_array($val) ? $val : $imptree->element($val)); + $result['a'][] = $this->_createMailboxElt(is_object($val) ? $val : $imptree->element($val)); } } @@ -1978,7 +1978,7 @@ class IMP_Ajax_Application extends Horde_Core_Ajax_Application /** * Create an object used by DimpCore to generate the folder tree. * - * @param array $elt The output from IMP_Tree::element(). + * @param IMP_Imap_Tree_Elt $elt An element object. * * @return stdClass The element object. Contains the following items: *
@@ -2003,28 +2003,27 @@ class IMP_Ajax_Application extends Horde_Core_Ajax_Application
      *                 2 = user vfolder [integer] [DEFAULT: 0]
      * 
*/ - protected function _createMailboxElt($elt) + protected function _createMailboxElt(IMP_Imap_Tree_Elt $elt) { $ob = new stdClass; - if ($elt['children']) { + if ($ob->children) { $ob->ch = 1; } - $ob->cl = $elt['class']; - $ob->m = $elt['value']; - if ($ob->m != $elt['name']) { - $ob->l = $elt['name']; + $ob->m = $elt->value; + if ($ob->m != $elt->name) { + $ob->l = $elt->name; } - if ($elt['parent'] != IMP_Imap_Tree::BASE_ELT) { - $ob->pa = $elt['parent']; + if ($elt->parent != IMP_Imap_Tree::BASE_ELT) { + $ob->pa = $elt->parent; } - if ($elt['polled']) { + if ($elt->polled) { $ob->po = 1; } - if ($elt['vfolder']) { - $ob->v = $GLOBALS['injector']->getInstance('IMP_Search')->isEditableVFolder($elt['value']) ? 2 : 1; + if ($elt->vfolder) { + $ob->v = $GLOBALS['injector']->getInstance('IMP_Search')->isEditableVFolder($elt->value) ? 2 : 1; } - if (!$elt['sub']) { + if (!$elt->sub) { $ob->un = 1; } @@ -2033,32 +2032,36 @@ class IMP_Ajax_Application extends Horde_Core_Ajax_Application $ob->t = $tmp; } - if ($elt['container']) { + if ($elt->container) { $ob->cl = 'exp'; $ob->co = 1; - if ($elt['nonimap']) { + if ($elt->nonimap) { $ob->n = 1; } } else { - if ($elt['polled']) { - $ob->u = intval($elt['unseen']); + if ($elt->polled) { + $poll_info = $elt->poll_info; + $ob->u = $poll_info['unseen']; } - if ($elt['special']) { + if ($elt->special) { $ob->s = 1; - } elseif (!$elt['vfolder'] && $elt['children']) { + } elseif (!$elt->vfolder && $elt->children) { $ob->cl = 'exp'; } } - if ($elt['user_icon']) { + $icon = $elt->icon; + if ($icon->user_icon) { $ob->cl = 'customimg'; - $dir = empty($elt['icondir']) + $dir = empty($icon->icondir) ? Horde_Themes::img() - : $elt['icondir']; + : $icon->icondir; $ob->i = empty($dir) - ? $elt['icon'] - : $dir . '/' . $elt['icon']; + ? $icon->icon + : $dir . '/' . $icon->icon; + } else { + $ob->cl = $icon['class']; } return $ob; diff --git a/imp/lib/Block/tree_folders.php b/imp/lib/Block/tree_folders.php index aee3ee3c3..f1b6cbcf6 100644 --- a/imp/lib/Block/tree_folders.php +++ b/imp/lib/Block/tree_folders.php @@ -68,39 +68,42 @@ class Horde_Block_imp_tree_folders extends Horde_Block /* Initialize the IMP_Tree object. */ $imaptree = $injector->getInstance('IMP_Imap_Tree'); - $mask = IMP_Imap_Tree::NEXT_SHOWCLOSED; - if ($prefs->getValue('subscribe')) { - $mask |= IMP_Imap_Tree::NEXT_SHOWSUB; - } + $mask = IMP_Imap_Tree::FLIST_CONTAINER | + IMP_Imap_Tree::FLIST_VFOLDER | + IMP_Imap_Tree::FLIST_ELT; $unseen = 0; $inbox = null; - $tree_ob = $imaptree->build($mask, null, null, false); - foreach ($tree_ob[0] as $val) { - $label = $val['name']; - if (!empty($val['unseen'])) { - $unseen += $val['unseen']; - $label = '' . $label . ' (' . $val['unseen'] . '/' . $val['msgs'] . ')'; + foreach ($imaptree->folderList($mask) as $val) { + $label = $val->name; + + if ($val->polled) { + $poll_info = $val->poll_info; + if (!empty($poll_info->unseen)) { + $unseen += $poll_info->unseen; + $label = '' . $label . ' (' . $poll_info->unseen . '/' . $poll_info->msgs . ')'; + } } /* If this is the INBOX, save it to later rewrite our parent node * to include new mail notification. */ - if ($val['value'] == 'INBOX') { + if ($val->value == 'INBOX') { $inbox = $val; } + $icon = $val->icon; $tree->addNode( - $parent . $val['value'], - ($val['level']) ? $parent . $val['parent'] : $parent, + $parent . $val->value, + ($val->level) ? $parent . $val->parent : $parent, $label, - $indent + $val['level'], - $imaptree->isOpen($val['value']), + $indent + $val->level, + $val->is_open, array( - 'icon' => $val['icon'], - 'icondir' => (string)$val['icondir'], - 'iconopen' => $val['iconopen'], - 'url' => ($val['container']) ? null : $name_url->add('mailbox', $val['value']), + 'icon' => $icon->icon, + 'icondir' => strval($icon->icondir), + 'iconopen' => $icon->iconopen, + 'url' => ($val->container) ? null : $name_url->add('mailbox', $val->value), ) ); } diff --git a/imp/lib/Folder.php b/imp/lib/Folder.php index 8ae34e87e..dc46270ca 100644 --- a/imp/lib/Folder.php +++ b/imp/lib/Folder.php @@ -103,20 +103,22 @@ class IMP_Folder $imaptree = $GLOBALS['injector']->getInstance('IMP_Imap_Tree'); - $list_mask = IMP_Imap_Tree::FLIST_CONTAINER | IMP_Imap_Tree::FLIST_OB; + $list_mask = IMP_Imap_Tree::FLIST_CONTAINER | IMP_Imap_Tree::FLIST_ELT; if (!$sub) { $list_mask |= IMP_Imap_Tree::FLIST_UNSUB; } - $flist = $imaptree->folderList($list_mask); - reset($flist); - while (list(,$ob) = each($flist)) { - if (in_array($ob['v'], $filter)) { + foreach ($imaptree->folderList($list_mask) as $ob) { + if (in_array($ob->value, $filter)) { continue; } - $label = str_repeat(' ', 2 * $ob['c']) . $ob['l']; - $list[$ob['v']] = array('val' => $imaptree->isContainer($ob) ? '' : $ob['v'], 'label' => $label, 'abbrev' => Horde_String::abbreviate($label, 30)); + $label = str_repeat(' ', 2 * $ob->level) . $ob->label; + $list[$ob->value] = array( + 'abbrev' => Horde_String::abbreviate($label, 30), + 'label' => $label, + 'val' => $ob->container ? '' : $ob->value + ); } /* Add the INBOX on top of list if not in the filter list. */ @@ -325,7 +327,6 @@ class IMP_Folder /* Get list of any folders that are underneath this one. */ $all_folders = array_merge(array($old), $imaptree->folderList(IMP_Imap_Tree::FLIST_UNSUB, $old)); - $sub_folders = $imaptree->folderList(); try { $GLOBALS['injector']->getInstance('IMP_Imap')->getOb()->renameMailbox($old, $new); diff --git a/imp/lib/Imap/Tree.php b/imp/lib/Imap/Tree.php index 812ee50ba..9cc45432f 100644 --- a/imp/lib/Imap/Tree.php +++ b/imp/lib/Imap/Tree.php @@ -51,12 +51,11 @@ class IMP_Imap_Tree const FLIST_CONTAINER = 1; const FLIST_UNSUB = 2; const FLIST_VFOLDER = 4; - const FLIST_OB = 8; - const FLIST_ELT = 16; - const FLIST_NOCHILDREN = 32; - const FLIST_ANCESTORS = 64; - const FLIST_SAMELEVEL = 128; - const FLIST_EXPANDED = 256; + const FLIST_ELT = 8; + const FLIST_NOCHILDREN = 16; + const FLIST_ANCESTORS = 32; + const FLIST_SAMELEVEL = 64; + const FLIST_EXPANDED = 128; /* Add null to folder key since it allows us to sort by name but * never conflict with an IMAP mailbox. */ @@ -179,27 +178,6 @@ class IMP_Imap_Tree protected $_trackdiff = true; /** - * See $open parameter in build(). - * - * @var boolean - */ - protected $_forceopen = false; - - /** - * Mailbox icons cache. - * - * @var array - */ - protected $_mboxIcons; - - /** - * Element cache for element(). - * - * @var array - */ - protected $_eltCache; - - /** * Constructor. */ public function __construct() @@ -525,7 +503,7 @@ class IMP_Imap_Tree $curr = $this->current(); if ($GLOBALS['prefs']->getValue('tree_view') && $this->isNamespace($curr) && - !$this->_isNonIMAPElt($curr) && + !$this->isNonImapElt($curr) && ($this->_tree[$curr['p']] && self::ELT_NOSHOW)) { $this->next($mask); } @@ -588,19 +566,24 @@ class IMP_Imap_Tree /** * Determines if there are more elements in the current tree level. * + * @param string $name The name of the tree element. + * * @return boolean True if there are more elements, false if this is the * last element. */ - public function peek() + public function peek($name) { - for ($i = ($this->_currkey + 1);; ++$i) { - if (!isset($this->_parent[$this->_currparent][$i])) { - return false; - } - if ($this->_activeElt($this->_tree[$this->_parent[$this->_currparent][$i]])) { + if (!($elt = $this->get($name))) { + return false; + } + + foreach (array_slice($this->_parent[$elt['p']], array_search($elt['v'], $this->_parent[$elt['p']]) + 1) as $val) { + if ($this->_activeElt($this->_tree[$val])) { return true; } } + + return false; } /** @@ -613,7 +596,10 @@ class IMP_Imap_Tree public function get($name) { $name = $this->_convertName($name); - return isset($this->_tree[$name]) ? $this->_tree[$name] : false; + + return isset($this->_tree[$name]) + ? $this->_tree[$name] + : false; } /** @@ -1098,7 +1084,7 @@ class IMP_Imap_Tree * * @return integer True if the element is a non-IMAP element. */ - protected function _isNonIMAPElt($elt) + public function isNonImapElt($elt) { return $elt['a'] & self::ELT_NONIMAP; } @@ -1397,7 +1383,7 @@ class IMP_Imap_Tree $basesort = $othersort = array(); foreach ($mbox as $val) { - if ($this->_isNonIMAPElt($this->_tree[$val])) { + if ($this->isNonImapElt($this->_tree[$val])) { $othersort[$val] = $this->_tree[$val]['l']; } else { $basesort[$val] = $this->_tree[$val]['l']; @@ -1555,83 +1541,6 @@ class IMP_Imap_Tree } /** - * Builds a list of folders, suitable to render a folder tree. - * - * @param integer $mask The mask to pass to next(). - * @param boolean $open If using the base folder icons, display a - * different icon whether the folder is opened or - * closed. - * - * @return array An array with two elements: the folder list and the - * total number of new messages. - * The folder list array contains the following added - * entries on top of the entries provided by element(): - *
-     * 'display' - The mailbox name run through IMP::displayFolder().
-     * 'peek' - See peek().
-     * 
- */ - public function build($mask = 0, $open = true) - { - $newmsgs = $rows = array(); - $this->_forceopen = $open; - - /* Start iterating through the list of mailboxes, displaying them. */ - $mailbox = $this->reset(); - do { - $row = $this->element($mailbox['v']); - - $row['display'] = $this->_isNonIMAPElt($mailbox) - ? $mailbox['l'] - : IMP::displayFolder($mailbox['v']); - $row['peek'] = $this->peek(); - - if (!empty($row['recent'])) { - $newmsgs[$row['value']] = $row['recent']; - } - - /* Hide folder prefixes from the user. */ - if ($row['level'] >= 0) { - $rows[] = $row; - } - } while (($mailbox = $this->next($mask))); - - $this->_forceopen = false; - - return array($rows, $newmsgs); - } - - /** - * Get any custom icon configured for the given element. - * - * @param array $elt A tree element. - * - * @return array An array with the 'icon', 'icondir', and 'alt' - * information for the element, or false if no icon - * available. - */ - public function getCustomIcon($elt) - { - if (!isset($this->_mboxIcons)) { - try { - $this->_mboxIcons = Horde::callHook('mbox_icons', array(), 'imp'); - } catch (Horde_Exception_HookNotSet $e) { - $this->_mboxIcons = array(); - } - } - - if (isset($this->_mboxIcons[$elt['v']])) { - return array( - 'icon' => $this->_mboxIcons[$elt['v']]['icon'], - 'icondir' => $this->_mboxIcons[$elt['v']]['icondir'], - 'alt' => $this->_mboxIcons[$elt['v']]['alt'] - ); - } - - return false; - } - - /** * Returns whether this element is a virtual folder. * * @param array $elt A tree element. @@ -1672,8 +1581,7 @@ class IMP_Imap_Tree * IMP_Imap_Tree::FLIST_CONTAINER - Show container elements. * IMP_Imap_Tree::FLIST_UNSUB - Show unsubscribed elements. * IMP_Imap_Tree::FLIST_VFOLDER - Show Virtual Folders. - * IMP_Imap_Tree::FLIST_OB - Return full tree object. - * IMP_Imap_Tree::FLIST_ELT - Return element object. + * IMP_Imap_Tree::FLIST_ELT - Return IMP_Imap_Tree_Element object. * IMP_Imap_Tree::FLIST_NOCHILDREN - Don't show child elements. * IMP_Imap_Tree::FLIST_ANCESTORS - Include ancestors. * IMP_Imap_Tree::FLIST_SAMELEVEL - Also return mailboxes at the same @@ -1684,8 +1592,8 @@ class IMP_Imap_Tree * @param string $base Return all mailboxes below this element. * * @return array Either an array of IMAP mailbox names or an array of - * objects (if FLIST_OB ot FLIST_ELT is specified). Keys - * are the mailbox name. + * IMP_Imap_Tree_Elt elements (if FLIST_ELT is specified). + * Keys are the mailbox name. */ public function folderList($mask = 0, $base = null) { @@ -1747,9 +1655,9 @@ class IMP_Imap_Tree !$this->isContainer($mailbox)) && (($mask & self::FLIST_VFOLDER) || !$this->isVFolder($mailbox))) { - $ret_array[$mailbox['v']] = ($mask & self::FLIST_OB) - ? $mailbox - : (($mask & self::FLIST_ELT) ? $this->element($mailbox['v']) : $mailbox['v']); + $ret_array[$mailbox['v']] = ($mask & self::FLIST_ELT) + ? $this->element($mailbox) + : $mailbox['v']; } } while (($mailbox = $this->next($nextmask))); } @@ -1763,16 +1671,6 @@ class IMP_Imap_Tree : $ret_array; } - /** - * Init frequently used element() data. - */ - protected function _initElement() - { - if (!isset($this->_eltCache)) { - $this->_eltCache = $this->getSpecialMailboxes(); - $this->_eltCache['image_dir'] = Horde_Themes::img(); - } - } /** * Return the list of 'special' mailboxes. @@ -1783,12 +1681,15 @@ class IMP_Imap_Tree */ public function getSpecialMailboxes() { + global $prefs; + $identity = $GLOBALS['injector']->getInstance('IMP_Identity'); + return array( - 'draft' => IMP::folderPref($GLOBALS['prefs']->getValue('drafts_folder'), true), + 'draft' => IMP::folderPref($prefs->getValue('drafts_folder'), true), 'sent' => $identity->getAllSentmailFolders(), - 'spam' => IMP::folderPref($GLOBALS['prefs']->getValue('spam_folder'), true), - 'trash' => IMP::folderPref($GLOBALS['prefs']->getValue('trash_folder'), true) + 'spam' => IMP::folderPref($prefs->getValue('spam_folder'), true), + 'trash' => IMP::folderPref($prefs->getValue('trash_folder'), true) ); } @@ -1797,37 +1698,8 @@ class IMP_Imap_Tree * * @param mixed $name The name of the tree element or a tree element. * - * @return array Returns the element with extended information, or false - * if not found. The information returned is as follows: - *
-     * 'alt' - (string) The alt text for the icon.
-     * 'base_elt' - (array) The return from get().
-     * 'children' - (boolean) Does the element have children?
-     * 'class' - (string) The CSS class name.
-     * 'container' - (boolean) Is this a container element?
-     * 'editvfolder' - (boolean) Can this virtual folder be edited?
-     * 'icon' - (string) The name of the icon graphic to use.
-     * 'icondir' - (string) The path of the icon directory.
-     * 'iconopen' - ???
-     * 'level' - (integer) The deepness level of this element.
-     * 'mbox_val' - (string) A html-ized version of 'value'.
-     * 'msgs' - (integer) The number of total messages in the element (if
-     *          polled).
-     * 'name' - (string) A html-ized version of 'label'.
-     * 'nonimap' - (boolean) Is this a non-IMAP element?
-     * 'parent' - (array) The parent element value.
-     * 'polled' - (boolean) Show polled information?
-     * 'recent' - (integer) The number of new messages in the element (if
-     *            polled).
-     * 'sub' - (boolean) Is folder subscribed to?
-     * 'special' - (boolean) Is this is a "special" element?
-     * 'specialvfolder' - (boolean) Is this a "special" virtual folder?
-     * 'unseen' - (integer) The number of unseen messages in the element (if
-     *            polled).
-     * 'user_icon' - (boolean) Use a user defined icon?
-     * 'value' - (string) The value of this element (i.e. element id).
-     * 'vfolder' - (boolean) Is this a virtual folder?
-     * 
+ * @return IMP_Imap_Tree_Element Returns the mailbox element or false if + * not found. */ public function element($mailbox) { @@ -1835,157 +1707,9 @@ class IMP_Imap_Tree $mailbox = $this->get($mailbox); } - if (!$mailbox) { - return false; - } - - $this->_initElement(); - - $row = array( - 'base_elt' => $mailbox, - 'children' => $this->hasChildren($mailbox), - 'container' => false, - 'editvfolder' => false, - 'icondir' => $this->_eltCache['image_dir'], - 'iconopen' => null, - 'level' => $mailbox['c'], - 'mbox_val' => htmlspecialchars($mailbox['v']), - 'name' => htmlspecialchars($mailbox['l']), - 'nonimap' => $this->_isNonIMAPElt($mailbox), - 'parent' => $mailbox['p'], - 'polled' => false, - 'recent' => 0, - 'special' => false, - 'specialvfolder' => false, - 'sub' => $this->isSubscribed($mailbox), - 'user_icon' => false, - 'value' => $mailbox['v'], - 'vfolder' => false, - ); - - $icon = $this->getCustomIcon($mailbox); - - if (!$this->isContainer($mailbox)) { - /* We are dealing with mailboxes here. - * Determine if we need to poll this mailbox for new messages. */ - if ($this->isPolled($mailbox)) { - /* If we need message information for this folder, update - * it now. */ - try { - if ($msgs_info = $GLOBALS['injector']->getInstance('IMP_Imap')->getOb()->status($mailbox['v'], Horde_Imap_Client::STATUS_RECENT | Horde_Imap_Client::STATUS_UNSEEN | Horde_Imap_Client::STATUS_MESSAGES)) { - $row['polled'] = true; - if (!empty($msgs_info['recent'])) { - $row['recent'] = $msgs_info['recent']; - } - $row['msgs'] = $msgs_info['messages']; - $row['unseen'] = $msgs_info['unseen']; - } - } catch (Horde_Imap_Client_Exception $e) {} - } - - switch ($mailbox['v']) { - case 'INBOX': - $row['icon'] = 'folders/inbox.png'; - $row['alt'] = _("Inbox"); - $row['class'] = 'inboxImg'; - $row['special'] = true; - break; - - case $this->_eltCache['trash']: - if ($GLOBALS['prefs']->getValue('use_vtrash')) { - $row['icon'] = ($this->isOpen($mailbox)) ? 'folders/open.png' : 'folders/folder.png'; - $row['alt'] = _("Mailbox"); - } else { - $row['icon'] = 'folders/trash.png'; - $row['alt'] = _("Trash folder"); - $row['class'] = 'trashImg'; - $row['special'] = true; - } - break; - - case $this->_eltCache['draft']: - $row['icon'] = 'folders/drafts.png'; - $row['alt'] = _("Draft folder"); - $row['class'] = 'draftsImg'; - $row['special'] = true; - break; - - case $this->_eltCache['spam']: - $row['icon'] = 'folders/spam.png'; - $row['alt'] = _("Spam folder"); - $row['class'] = 'spamImg'; - $row['special'] = true; - break; - - default: - if (in_array($mailbox['v'], $this->_eltCache['sent'])) { - $row['icon'] = 'folders/sent.png'; - $row['alt'] = _("Sent mail folder"); - $row['class'] = 'sentImg'; - $row['special'] = true; - } else { - if ($this->isOpen($mailbox)) { - $row['icon'] = 'folders/open.png'; - $row['class'] = 'folderopenImg'; - } else { - $row['icon'] = 'folders/folder.png'; - $row['class'] = 'folderImg'; - } - $row['alt'] = _("Mailbox"); - } - break; - } - - /* Virtual folders. */ - if ($this->isVFolder($mailbox)) { - $imp_search = $GLOBALS['injector']->getInstance('IMP_Search'); - - $row['vfolder'] = true; - $row['editvfolder'] = $imp_search->isEditableVFolder($mailbox['v']); - if ($imp_search->isVTrashFolder($mailbox['v'])) { - $row['specialvfolder'] = true; - $row['icon'] = 'folders/trash.png'; - $row['alt'] = _("Virtual Trash Folder"); - $row['class'] = 'trashImg'; - } elseif ($imp_search->isVINBOXFolder($mailbox['v'])) { - $row['specialvfolder'] = true; - $row['icon'] = 'folders/inbox.png'; - $row['alt'] = _("Virtual INBOX Folder"); - $row['class'] = 'inboxImg'; - } - } - } else { - /* We are dealing with folders here. */ - $row['container'] = true; - if ($this->_forceopen && $this->isOpen($mailbox)) { - $row['icon'] = 'folders/open.png'; - $row['alt'] = _("Opened Folder"); - $row['class'] = 'folderopenImg'; - } else { - $row['icon'] = 'folders/folder.png'; - $row['iconopen'] = 'folders/open.png'; - $row['alt'] = ($this->_forceopen) ? _("Closed Folder") : _("Folder"); - $row['class'] = 'folderImg'; - } - if ($this->isVFolder($mailbox)) { - $row['vfolder'] = true; - } - } - - /* Overwrite the icon information now. */ - if (!empty($icon)) { - $row['icon'] = $icon['icon']; - $row['icondir'] = $icon['icondir']; - if (!empty($icon['alt'])) { - $row['alt'] = $icon['alt']; - } - $row['iconopen'] = isset($icon['iconopen']) - ? $icon['iconopen'] - : null; - $row['user_icon'] = true; - } - - return $row; + return $mailbox + ? new IMP_Imap_Tree_Element($mailbox, $this) + : false; } /** diff --git a/imp/lib/Imap/Tree/Element.php b/imp/lib/Imap/Tree/Element.php new file mode 100644 index 000000000..755a7fee7 --- /dev/null +++ b/imp/lib/Imap/Tree/Element.php @@ -0,0 +1,335 @@ + + * @category Horde + * @license http://www.fsf.org/copyleft/gpl.html GPL + * @package IMP + */ +class IMP_Imap_Tree_Element +{ + /** + * A mailbox element array. + * + * @see IMP_Imap_Tree#_makeElt(). + * + * @var array + */ + protected $_mbox; + + /** + * A reference to the IMP_Imap_Tree object. + * + * @var IMP_Imap_Tree + */ + protected $_treeob; + + /** + * Element cache. + * + * @var array + */ + static protected $_eltCache; + + /** + * Mailbox icons cache. + * + * @var array + */ + static protected $_mboxIcons; + + /** + * Constructor. + * + * @var array $mbox A mailbox element array. + * @var IMP_Imap_Tree $treeob A tree object. + */ + public function __construct($mbox, $treeob) + { + $this->_mbox = $mbox; + $this->_treeob = $treeob; + } + + /** + * Return information on a mailbox. + * + * @param strimg $key The data item to return. + *
+     * 'base_elt' - (array) A mailbox element array. See IMP_Imap_Tree#get().
+     * 'children' - (boolean) Does the element have children?
+     * 'container' - (boolean) Is this a container element?
+     * 'display' - (string) The mailbox name run through IMP::displayFolder().
+     * 'editvfolder' - (boolean) Can this virtual folder be edited?
+     * 'is_open' - (boolean) Is this level expanded?
+     * 'icon' - (object) Icon information for the mailbox. Properties:
+     *   'alt' - (string) The alt text for the icon.
+     *   'class' - (string) The CSS class name.
+     *   'icon' - (string) The name of the icon graphic to use.
+     *   'icondir' - (string) The path of the icon directory.
+     *   'iconopen' - (string) The name of the openicon to use.
+     *   'user_icon' - (boolean) Use a user defined icon?
+     * 'level' - (integer) The deepness level of this element.
+     * 'mbox_val' - (string) A html-ized version of 'value'.
+     * 'name' - (string) A html-ized version of 'label'.
+     * 'nonimap' - (boolean) Is this a non-IMAP element?
+     * 'parent' - (array) The parent element value.
+     * 'peek' - (boolean) Are there more elements in the current tree level?
+     * 'polled' - (boolean) Show polled information?
+     * 'poll_info' - (object) Poll information for the mailbox. Properties:
+     *   'msgs' - (integer) The number of total messages in the element (if
+     *            polled).
+     *   'recent' - (integer) The number of new messages in the element (if
+     *              polled).
+     *   'unseen' - (integer) The number of unseen messages in the element (if
+     *              polled).
+     * 'sub' - (boolean) Is folder subscribed to?
+     * 'special' - (boolean) Is this is a "special" element?
+     * 'specialvfolder' - (boolean) Is this a "special" virtual folder?
+     * 'value' - (string) The value of this element (i.e. element id).
+     * 'vfolder' - (boolean) Is this a virtual folder?
+     * 
+ * + * @return mixed The information. + */ + public function __get($key) + { + switch ($key) { + case 'base_elt': + return $this->_mbox; + + case 'children': + return $this->_treeob->hasChildren($this->_mbox); + + case 'container': + return $this->_treeob->isContainer($this->_mbox); + + case 'display': + return $this->nonimap + ? $this->_mbox['l'] + : IMP::displayFolder($this->_mbox['v']); + + case 'editvfolder': + return ($this->vfolder && + $GLOBALS['injector']->getInstance('IMP_Search')->isEditableVFolder($this->_mbox['v'])); + + case 'is_open': + return $this->_treeob->isOpen($this->_mbox); + + case 'icon': + return $this->_getIcon(); + + case 'label': + return $this->_mbox['l']; + + case 'level': + return $this->_mbox['c']; + + case 'mbox_val': + return htmlspecialchars($this->_mbox['v']); + + case 'name': + return htmlspecialchars($this->_mbox['l']); + + case 'nonimap': + return $this->_treeob->isNonImapElt($this->_mbox); + + case 'parent': + return $this->_mbox['p']; + + case 'peek': + return $this->_treeob->peek($this->_mbox['v']); + + case 'poll_info': + $info = new stdClass; + $info->msgs = 0; + $info->recent = 0; + $info->unseen = 0; + + try { + if ($msgs_info = $GLOBALS['injector']->getInstance('IMP_Imap')->getOb()->status($this->_mbox['v'], Horde_Imap_Client::STATUS_RECENT | Horde_Imap_Client::STATUS_UNSEEN | Horde_Imap_Client::STATUS_MESSAGES)) { + if (!empty($msgs_info['recent'])) { + $info->recent = intval($msgs_info['recent']); + } + $info->msgs = intval($msgs_info['messages']); + $info->unseen = intval($msgs_info['unseen']); + } + } catch (Horde_Imap_Client_Exception $e) {} + + return $info; + + case 'polled': + return $this->_treeob->isPolled($this->_mbox); + + case 'special': + $this->_initCache(); + + switch ($this->_mbox['v']) { + case 'INBOX': + case $this->_eltCache['draft']: + case $this->_eltCache['spam']: + return true; + + case $this->_eltCache['trash']: + return (!$GLOBALS['prefs']->getValue('use_vtrash')); + + default: + return in_array($this->_mbox['v'], $this->_eltCache['sent']); + } + + return false; + + case 'specialvfolder': + if (!$this->vfolder) { + return false; + } + $imp_search = $GLOBALS['injector']->getInstance('IMP_Search'); + return ($imp_search->isVTrashFolder($this->_mbox['v']) || + $imp_search->isVINBOXFolder($this->_mbox['v'])); + + case 'sub': + return $this->_treeob->isSubscribed($this->_mbox); + + case 'value': + return $this->_mbox['v']; + + case 'vfolder': + return $this->_treeob->isVFolder($this->_mbox); + } + + return false; + } + + /** + * Return icon information. + * + * TODO + */ + protected function _getIcon() + { + $this->_initCache(); + + $info = new stdClass; + $info->icondir = $this->_eltCache['image_dir']; + $info->iconopen = null; + $info->user_icon = false; + + if ($this->container) { + /* We are dealing with folders here. */ + if ($this->is_open) { + $info->alt = _("Opened Folder"); + $info->class = 'folderopenImg'; + $info->icon = 'folders/open.png'; + } else { + $info->alt = _("Folder"); + $info->class = 'folderImg'; + $info->icon = 'folders/folder.png'; + $info->iconopen = 'folders/open.png'; + } + } else { + switch ($this->_mbox['v']) { + case 'INBOX': + $info->alt = _("Inbox"); + $info->class = 'inboxImg'; + $info->icon = 'folders/inbox.png'; + break; + + case $this->_eltCache['trash']: + if ($GLOBALS['prefs']->getValue('use_vtrash')) { + $info->alt = _("Mailbox"); + $info->icon = $this->is_open + ? 'folders/open.png' + : 'folders/folder.png'; + } else { + $info->alt = _("Trash folder"); + $info->class = 'trashImg'; + $info->icon = 'folders/trash.png'; + } + break; + + case $this->_eltCache['draft']: + $info->alt = _("Draft folder"); + $info->class = 'draftsImg'; + $info->icon = 'folders/drafts.png'; + break; + + case $this->_eltCache['spam']: + $info->alt = _("Spam folder"); + $info->class = 'spamImg'; + $info->icon = 'folders/spam.png'; + break; + + default: + if (in_array($this->_mbox['v'], $this->_eltCache['sent'])) { + $info->alt = _("Sent mail folder"); + $info->class = 'sentImg'; + $info->icon = 'folders/sent.png'; + } else { + $info->alt = _("Mailbox"); + if ($this->is_open) { + $info->class = 'folderopenImg'; + $info->icon = 'folders/open.png'; + } else { + $info->class = 'folderImg'; + $info->icon = 'folders/folder.png'; + } + } + break; + } + + /* Virtual folders. */ + if ($this->vfolder) { + $imp_search = $GLOBALS['injector']->getInstance('IMP_Search'); + if ($imp_search->isVTrashFolder($this->_mbox['v'])) { + $info->alt = _("Virtual Trash Folder"); + $info->class = 'trashImg'; + $info->icon = 'folders/trash.png'; + } elseif ($imp_search->isVINBOXFolder($this->_mbox['v'])) { + $info->alt = _("Virtual INBOX Folder"); + $info->class = 'inboxImg'; + $info->icon = 'folders/inbox.png'; + } + } + } + + /* Overwrite the icon information now. */ + if (!isset($this->_mboxIcons)) { + try { + $this->_mboxIcons = Horde::callHook('mbox_icons', array(), 'imp'); + } catch (Horde_Exception_HookNotSet $e) { + $this->_mboxIcons = array(); + } + } + + if (isset($this->_mboxIcons[$this->_mbox['v']])) { + $mi = $this->_mboxIcons[$this->_mbox['v']]; + + if (isset($mi['alt'])) { + $info->alt = $mi['alt']; + } + $info->icon = $mi['icon']; + $info->icondir = $mi['icondir']; + $info->user_icon = true; + } + + return $info; + } + + /** + * Init frequently used element() data. + */ + protected function _initCache() + { + if (!isset($this->_eltCache)) { + $this->_eltCache = $this->_treeob->getSpecialMailboxes(); + $this->_eltCache['image_dir'] = Horde_Themes::img(); + } + } + +} diff --git a/imp/lib/Ui/Folder.php b/imp/lib/Ui/Folder.php index 5ef3d40bd..e5d35e632 100644 --- a/imp/lib/Ui/Folder.php +++ b/imp/lib/Ui/Folder.php @@ -25,7 +25,7 @@ class IMP_Ui_Folder /** * Create the tree images for a list of folder elements. * - * @param array $rows Folder rows returned from IMP_Imap_Tree::build(). + * @param array $rows A list of IMP_Imap_Tree_Element objects. * @param array $options Additional options: *
      * 'expand_url' - (Horde_Url) The URL to use for expand/collapse links.
@@ -49,8 +49,8 @@ class IMP_Ui_Folder
     /**
      * Create a tree image from a folder element entry.
      *
-     * @param array $elt      An entry returned from IMP_Imap_Tree::element().
-     * @param array $options  See self::getTreeImages().
+     * @param IMP_Imap_Tree_Elt $elt  A mailbox element object.
+     * @param array $options          See self::getTreeImages().
      *
      * @return string  The image string.
      */
@@ -59,27 +59,32 @@ class IMP_Ui_Folder
         global $registry;
 
         $alt = $dir = null;
-        $dir2 = $elt['user_icon']
-            ? Horde::img($elt['icon'], $elt['alt'], null, $elt['icondir'])
-            : '';
+        $line = '';
+
+        $icon = $elt->icon;
+        $peek = $elt->peek;
+
+        $dir2 = $icon->user_icon
+            ? Horde::img($icon->icon, $icon->alt, null, $icon->icondir)
+            : '';
 
-        if ($elt['children'] && isset($options['expand_url'])) {
-            $dir = $options['expand_url']->copy()->add('folder', $elt['value']);
+        if ($elt->children && isset($options['expand_url'])) {
+            $dir = $options['expand_url']->copy()->add('folder', $elt->value);
 
-            if ($GLOBALS['injector']->getInstance('IMP_Imap_Tree')->isOpen($elt['base_elt'])) {
+            if ($elt->is_open) {
                 if (!is_null($dir)) {
                     $dir->add('actionID', 'collapse_folder');
                     $alt = _("Collapse Folder");
                 }
 
                 if (empty($registry->nlsconfig['rtl'][$GLOBALS['language']])) {
-                    $tree_img = ($elt['value'] == 'INBOX')
+                    $tree_img = ($elt->value == 'INBOX')
                         ? 9
-                        : ($elt['peek'] ? 10 : 11);
+                        : ($peek ? 10 : 11);
                 } else {
-                    $tree_img = ($elt['value'] == 'INBOX')
+                    $tree_img = ($elt->value == 'INBOX')
                         ? 12
-                        : ($elt['peek'] ? 13 : 14);
+                        : ($peek ? 13 : 14);
                 }
             } else {
                 if (!is_null($dir)) {
@@ -88,13 +93,13 @@ class IMP_Ui_Folder
                 }
 
                 if (empty($registry->nlsconfig['rtl'][$GLOBALS['language']])) {
-                    $tree_img = ($elt['value'] == 'INBOX')
+                    $tree_img = ($elt->value == 'INBOX')
                         ? 15
-                        : ($elt['peek'] ? 16 : 17);
+                        : ($peek ? 16 : 17);
                 } else {
-                    $tree_img = ($elt['value'] == 'INBOX')
+                    $tree_img = ($elt->value == 'INBOX')
                         ? 18
-                        : ($elt['peek'] ? 19 : 20);
+                        : ($peek ? 19 : 20);
                 }
             }
 
@@ -102,30 +107,27 @@ class IMP_Ui_Folder
                 $dir = Horde::link($dir, $alt) . '' . $dir2;
             }
         } else {
-            if (($elt['value'] == 'INBOX') && !$elt['peek']) {
+            if (($elt->value == 'INBOX') && !$peek) {
                 $dir = '' . $dir2;
             } else {
                 if (empty($registry->nlsconfig['rtl'][$GLOBALS['language']])) {
-                    $tree_img = ($elt['value'] == 'INBOX')
+                    $tree_img = ($elt->value == 'INBOX')
                         ? 3
-                        : ($elt['peek'] ? 2 : 4);
+                        : ($peek ? 2 : 4);
                 } else {
-                    $tree_img = ($elt['value'] == 'INBOX')
+                    $tree_img = ($elt->value == 'INBOX')
                         ? 7
-                        : ($elt['peek'] ? 6 : 8);
+                        : ($peek ? 6 : 8);
                 }
                 $dir = '' . $dir2;
             }
         }
 
-        $line = '';
-        $this->_moreMbox[$elt['level']] = $elt['peek'];
-        for ($i = 0; $i < $elt['level']; $i++) {
-            if ($this->_moreMbox[$i]) {
-                $line .= '';
-            } else {
-                $line .= '';
-            }
+        $this->_moreMbox[$elt->level] = $peek;
+        for ($i = 0; $i < $elt->level; ++$i) {
+            $line .= $this->_moreMbox[$i]
+                ? ''
+                : '';
         }
 
         return $line . $dir;
diff --git a/imp/search.php b/imp/search.php
index e4ae4603f..db8fc2fd5 100644
--- a/imp/search.php
+++ b/imp/search.php
@@ -91,13 +91,14 @@ if (!empty($criteria)) {
 
 /* Generate master folder list. */
 $imp_imap_tree = $injector->getInstance('IMP_Imap_Tree');
-$mask = IMP_Imap_Tree::NEXT_SHOWCLOSED;
+$mask = IMP_Imap_Tree::FLIST_ELT;
+
 $subscribe = $prefs->getValue('subscribe');
-if ($subscribe || !Horde_Util::getFormData('show_unsub')) {
-    $mask |= IMP_Imap_Tree::NEXT_SHOWSUB;
+if (!$subscribe || Horde_Util::getFormData('show_unsub')) {
+    $mask |= IMP_Imap_Tree::FLIST_UNSUB;
 }
 
-list($raw_rows,) = $imp_imap_tree->build($mask);
+$raw_rows = $imp_imap_tree->folderList($mask);
 
 $imp_ui_folder = new IMP_Ui_Folder();
 $tree_imgs = $imp_ui_folder->getTreeImages($raw_rows);
@@ -105,9 +106,9 @@ $tree_imgs = $imp_ui_folder->getTreeImages($raw_rows);
 $folders = array();
 foreach ($raw_rows as $key => $val) {
     $folders[] = array(
-        'c' => intval($val['container']),
-        'l' => $tree_imgs[$key] . ' ' . $val['name'],
-        'v' => $val['value']
+        'c' => intval($val->container),
+        'l' => $tree_imgs[$key] . ' ' . $val->name,
+        'v' => $val->value
     );
 }