Use Horde_Tree to render IMP folder list selection dropdowns.
authorMichael M Slusarz <slusarz@curecanti.org>
Wed, 25 Aug 2010 18:18:11 +0000 (12:18 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Wed, 25 Aug 2010 19:36:46 +0000 (13:36 -0600)
imp/lib/IMP.php
imp/lib/Imap/Tree.php
imp/lib/Tree/Flist.php [new file with mode: 0644]
imp/templates/imp/flist/flist.html

index 517b352..7ecb4d6 100644 (file)
@@ -162,10 +162,8 @@ class IMP
     }
 
     /**
-     * Wrapper around IMP_Folder::flist() which generates the body of a
-     * &lt;select&gt; form input from the generated folder list. The
-     * &lt;select&gt; and &lt;/select&gt; tags are NOT included in the output
-     * of this function.
+     * Generates a select form input from a folder list. The &lt;select&gt;
+     * and &lt;/select&gt; tags are NOT included in the output.
      *
      * @param array $options  Optional parameters:
      * <pre>
@@ -194,105 +192,18 @@ class IMP
      */
     static public function flistSelect($options = array())
     {
-        /* Don't filter here - since we are going to parse through every
-         * member of the folder list below anyway, we can filter at that time.
-         * This allows us the have a single cached value for the folder list
-         * rather than a cached value for each different mailbox we may
-         * visit. */
-        $mailboxes = $GLOBALS['injector']->getInstance('IMP_Folder')->flist();
-
-        $t = $GLOBALS['injector']->createInstance('Horde_Template');
-        $t->setOption('gettext', true);
-
-        if (!empty($options['heading']) && (strlen($options['heading']) > 0)) {
-            $t->set('heading', $options['heading']);
-        }
-
-        if (!empty($options['new_folder']) &&
-            (!empty($GLOBALS['conf']['hooks']['permsdenied']) ||
-             ($GLOBALS['injector']->getInstance('Horde_Perms')->hasAppPermission('create_folders') &&
-              $GLOBALS['injector']->getInstance('Horde_Perms')->hasAppPermission('max_folders')))) {
-            $t->set('new_mbox', true);
-        }
-
-        /* Add the list of mailboxes to the lists. */
-        $filter = empty($options['filter'])
-            ? array()
-            : array_flip($options['filter']);
-        $mbox_list = array();
-
-        foreach ($mailboxes as $mbox) {
-            if (!isset($filter[$mbox['val']])) {
-                $label = (isset($options['abbrev']) && !$options['abbrev'])
-                    ? $mbox['label']
-                    : $mbox['abbrev'];
-
-                $mbox_list[] = array(
-                    'l' => $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($label, 'space2html', array('encode' => true)),
-                    'sel' => (!empty($options['selected']) && ($mbox['val'] === $options['selected'])),
-                    'v' => self::formMbox($mbox['val'], true)
-                );
-            }
-        }
-        $t->set('mbox', $mbox_list);
-
-        /* Add the list of virtual folders to the list. */
-        if (!empty($options['inc_vfolder'])) {
-            $imp_search = $GLOBALS['injector']->getInstance('IMP_Search');
-            $vfolders = $imp_search->listQueries(IMP_Search::LIST_VFOLDER);
-            if (!empty($vfolders)) {
-                $vfolder_list = array();
-                $vfolder_sel = $imp_search->searchMboxID();
-                foreach ($vfolders as $id => $val) {
-                    $vfolder_list[] = array(
-                        'l' => $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($val, 'space2html', array('encode' => true)),
-                        'sel' => ($vfolder_sel == $id),
-                        'v' => self::formMbox($imp_search->createSearchID($id), true)
-                    );
-                }
-                $t->set('vfolder', $vfolder_list);
-            }
-        }
-
-        /* Add the list of editable tasklists to the list. */
-        if (!empty($options['inc_tasklists']) &&
-            !empty($_SESSION['imp']['tasklistavail'])) {
-            try {
-                $tasklists = $GLOBALS['registry']->call('tasks/listTasklists', array(false, Horde_Perms::EDIT));
-
-                if (count($tasklists)) {
-                    $tasklist_list = array();
-                    foreach ($tasklists as $id => $tasklist) {
-                        $tasklist_list[] = array(
-                            'l' => $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($tasklist->get('name'), 'space2html', array('encode' => true)),
-                            'v' => self::formMbox(self::TASKLIST_EDIT . $id, true)
-                        );
-                    }
-                    $t->set('tasklist', $tasklist_list);
-                }
-            } catch (Horde_Exception $e) {}
-        }
-
-        /* Add the list of editable notepads to the list. */
-        if (!empty($options['inc_notepads']) &&
-            !empty($_SESSION['imp']['notepadavail'])) {
-            try {
-                $notepads = $GLOBALS['registry']->call('notes/listNotepads', array(false, Horde_Perms::EDIT));
-
-                if (count($notepads)) {
-                    $notepad_list[] = array();
-                    foreach ($notepads as $id => $notepad) {
-                        $notepad_list[] = array(
-                            'l' => $GLOBALS['injector']->getInstance('Horde_Text_Filter')->filter($notepad->get('name'), 'space2html', array('encode' => true)),
-                            'v' => self::formMbox(self::NOTEPAD_EDIT . $id, true)
-                        );
-                    }
-                    $t->set('notepad', $notepad_list);
-                }
-            } catch (Horde_Exception $e) {}
+        $imaptree = $GLOBALS['injector']->getInstance('IMP_Imap_Tree');
+        $imaptree->setIteratorFilter(IMP_Imap_Tree::FLIST_CONTAINER);
+
+        $tree = $imaptree->createTree('imp_flist_select', array(
+            'render_type' => 'IMP_Tree_Flist'
+        ));
+        if (!empty($options['selected'])) {
+            $tree->addNodeParams($options['selected'], array('selected' => true));
         }
+        $tree->setOption($options);
 
-        return $t->fetch(IMP_TEMPLATES . '/imp/flist/flist.html');
+        return $tree->getTree();
     }
 
     /**
index 79d8245..5d4a9cc 100644 (file)
@@ -1507,15 +1507,25 @@ class IMP_Imap_Tree implements ArrayAccess, Iterator
             : Horde::applicationUrl('mailbox.php');
 
         foreach ($this as $val) {
-            $after = $class = '';
-            $url = null;
+            $after = '';
+            $params = array();
 
-            if ($opts['render_type'] == 'Simplehtml') {
-                $label =  htmlspecialchars(Horde_String::abbreviate($val->label, 30 - ($val->level * 2)));
-                $icon = null;
-            } else {
+            switch ($opts['render_type']) {
+            case 'IMP_Tree_Flist':
+                $label = $val->name;
+                $params['orig_label'] = $val->label;
+                break;
+
+            case 'Javascript':
                 $label = $val->name;
                 $icon = $val->icon;
+                $params['icon'] = $icon->icon;
+                $params['iconopen'] = $icon->iconopen;
+                break;
+
+            case 'Simplehtml':
+                $label = htmlspecialchars(Horde_String::abbreviate($val->label, 30 - ($val->level * 2)));
+                break;
             }
 
             if (!empty($opts['poll_info']) && $val->polled) {
@@ -1534,10 +1544,10 @@ class IMP_Imap_Tree implements ArrayAccess, Iterator
             }
 
             if (!$val->container) {
-                $url = $mailbox_url->add('mailbox', $val->value);
+                $params['url'] = $mailbox_url->add('mailbox', $val->value);
 
                 if ($this->_showunsub && !$val->sub) {
-                    $class = 'folderunsub';
+                    $params['class'] = 'folderunsub';
                 }
             }
 
@@ -1562,13 +1572,8 @@ class IMP_Imap_Tree implements ArrayAccess, Iterator
                 ($val->level) ? strval($parent) . $val->parent : $parent,
                 $label,
                 $indent + $val->level,
-                $val->is_open,
-                array(
-                    'class' => $class,
-                    'icon' => $icon ? $icon->icon : null,
-                    'iconopen' => $icon ? $icon->iconopen : null,
-                    'url' => $url
-                ),
+                ($this->_cache['filter']['mask'] & self::FLIST_EXPANDED) ? $val->is_open : true,
+                $params,
                 $after,
                 empty($opts['checkbox']) ? null : $checkbox . ' />'
             );
diff --git a/imp/lib/Tree/Flist.php b/imp/lib/Tree/Flist.php
new file mode 100644 (file)
index 0000000..6efa47a
--- /dev/null
@@ -0,0 +1,197 @@
+<?php
+/**
+ * The IMP_Tree_Flist class extends the Horde_Tree_Select class to provide
+ * output of an IMP dropdown folder list.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author   Michael Slusarz <slusarz@curecanti.org>
+ * @category IMP
+ * @license  http://www.fsf.org/copyleft/lgpl.html GPL
+ * @package  Tree
+ */
+class IMP_Tree_Flist extends Horde_Tree_Select
+{
+    /**
+     * Allowed parameters for nodes.
+     *
+     * @var array
+     */
+    protected $_allowed = array(
+        'orig_label',
+        'selected'
+    );
+
+    /**
+     * Filter list.
+     *
+     * @var array
+     */
+    protected $_filter = array();
+
+    /**
+     * Constructor.
+     *
+     * @param string $name   The name of this tree instance.
+     * @param array $params  Additional parameters.
+     * <pre>
+     * 'abbrev' - (integer) Abbreviate long mailbox names by replacing the
+     *            middle of the name with '...'? Value is the total length
+     *            of the string.
+     *            DEFAULT: 30
+     * 'filter' - (array) An array of mailboxes to ignore.
+     *            DEFAULT: Display all
+     * 'heading' - (string) The label for an empty-value option at the top of
+     *             the list.
+     *             DEFAULT: ''
+     * 'inc_notepads' - (boolean) Include user's editable notepads in list?
+     *                   DEFAULT: No
+     * 'inc_tasklists' - (boolean) Include user's editable tasklists in list?
+     *                   DEFAULT: No
+     * 'inc_vfolder' - (boolean) Include user's virtual folders in list?
+     *                   DEFAULT: No
+     * 'new_folder' - (boolean) Display an option to create a new folder?
+     *                DEFAULT: No
+     * </pre>
+     */
+    public function __construct($name, array $params = array())
+    {
+        $params = array_merge(array(
+            'abbrev' => 30
+        ), $params);
+
+        parent::__construct($name, $params);
+    }
+
+    /**
+     * Returns the tree.
+     *
+     * @return string  The HTML code of the rendered tree.
+     */
+    public function getTree()
+    {
+        global $conf, $injector, $registry;
+
+        $this->_buildIndents($this->_root_nodes);
+
+        $t = $injector->createInstance('Horde_Template');
+        $t->setOption('gettext', true);
+
+        /* Heading. */
+        if (($heading = $this->getOption('heading')) &&
+            (strlen($heading) > 0)) {
+            $t->set('heading', $heading);
+        }
+
+        /* New folder entry. */
+        if ($this->getOption('new_folder') &&
+            (!empty($conf['hooks']['permsdenied']) ||
+             ($injector->getInstance('Horde_Perms')->hasAppPermission('create_folders') &&
+              $injector->getInstance('Horde_Perms')->hasAppPermission('max_folders')))) {
+            $t->set('new_mbox', true);
+        }
+
+        /* Virtual folders. */
+        if ($this->getOption('inc_vfolder')) {
+            $imp_search = $injector->getInstance('IMP_Search');
+            $vfolders = $imp_search->listQueries(IMP_Search::LIST_VFOLDER);
+            if (!empty($vfolders)) {
+                $vfolder_list = array();
+                $vfolder_sel = $imp_search->searchMboxID();
+                foreach ($vfolders as $id => $val) {
+                    $vfolder_list[] = array(
+                        'l' => $injector->getInstance('Horde_Text_Filter')->filter($val, 'space2html', array('encode' => true)),
+                        'sel' => ($vfolder_sel == $id),
+                        'v' => IMP::formMbox($imp_search->createSearchID($id), true)
+                    );
+                }
+                $t->set('vfolder', $vfolder_list);
+            }
+        }
+
+        /* Add the list of editable tasklists to the list. */
+        if ($this->getOption('inc_tasklists') &&
+            !empty($_SESSION['imp']['tasklistavail'])) {
+            try {
+                $tasklists = $registry->call('tasks/listTasklists', array(false, Horde_Perms::EDIT));
+
+                if (count($tasklists)) {
+                    $tasklist_list = array();
+                    foreach ($tasklists as $id => $tasklist) {
+                        $tasklist_list[] = array(
+                            'l' => $injector->getInstance('Horde_Text_Filter')->filter($tasklist->get('name'), 'space2html', array('encode' => true)),
+                            'v' => IMP::formMbox(IMP::TASKLIST_EDIT . $id, true)
+                        );
+                    }
+                    $t->set('tasklist', $tasklist_list);
+                }
+            } catch (Horde_Exception $e) {}
+        }
+
+        /* Add the list of editable notepads to the list. */
+        if ($this->getOption('inc_notepads') &&
+            !empty($_SESSION['imp']['notepadavail'])) {
+            try {
+                $notepads = $registry->call('notes/listNotepads', array(false, Horde_Perms::EDIT));
+
+                if (count($notepads)) {
+                    $notepad_list[] = array();
+                    foreach ($notepads as $id => $notepad) {
+                        $notepad_list[] = array(
+                            'l' => $injector->getInstance('Horde_Text_Filter')->filter($notepad->get('name'), 'space2html', array('encode' => true)),
+                            'v' => IMP::formMbox(IMP::NOTEPAD_EDIT . $id, true)
+                        );
+                    }
+                    $t->set('notepad', $notepad_list);
+                }
+            } catch (Horde_Exception $e) {}
+        }
+
+        /* Prepare filter list. */
+        $this->_filter = ($filter = $this->getOption('filter'))
+            ? array_flip($filter)
+            : array();
+
+        $tree = '';
+        foreach ($this->_root_nodes as $node_id) {
+            $tree .= $this->_buildTree($node_id);
+        }
+        $t->set('tree', $tree);
+
+        return $t->fetch(IMP_TEMPLATES . '/imp/flist/flist.html');
+    }
+
+    /**
+     * Recursive function to walk through the tree array and build the output.
+     *
+     * @param string $node_id  The Node ID.
+     *
+     * @return string  The tree rendering.
+     */
+    protected function _buildTree($node_id)
+    {
+        if (isset($this->_filter[$node_id])) {
+            return '';
+        }
+
+        if ($abbrev = $this->getOption('abbrev')) {
+            $node = &$this->_nodes[$node_id];
+            $orig_label = $node['label'];
+            $node['label'] = htmlspecialchars(Horde_String::abbreviate($node['orig_label'], $abbrev - ($node['indent'] * 2)));
+        } else {
+            $orig_label = null;
+        }
+
+        $out = parent::_buildTree($node_id);
+
+        if ($orig_label) {
+            $node['label'] = $orig_label;
+        }
+
+        return $out;
+    }
+
+}
index 4e6a7d8..c625776 100644 (file)
@@ -6,9 +6,7 @@
 <option class="flistCreate" value=""><gettext>Create New Mailbox</gettext></option>
 <option value="" disabled="disabled">- - - - - - - -</option>
 </if:new_mbox>
-<loop:mbox>
-<option value="<tag:mbox.v />"<if:mbox.sel> selected="selected"</if:mbox.sel>><tag:mbox.l /></option>
-</loop:mbox>
+<tag:tree />
 <if:vfolder>
 <option value="" disabled="disabled">- - - - - - - -</option>
 <loop:vfolder>