Bug #9368: Refactor menu handling in dimp
authorMichael M Slusarz <slusarz@curecanti.org>
Fri, 5 Nov 2010 17:38:47 +0000 (11:38 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Tue, 9 Nov 2010 02:17:15 +0000 (19:17 -0700)
Remove support for 'action' menu config parameter.
Use Horde_Menu (and the new IMP_Menu_Dimp class) to generate the menu
code.

imp/config/menu.php.dist
imp/docs/UPGRADING
imp/index-dimp.php
imp/js/dimpbase.js
imp/lib/Dimp.php
imp/lib/Menu/Dimp.php [new file with mode: 0644]
imp/templates/dimp/index.inc
imp/templates/dimp/javascript_defs_dimp.php

index f8b2f03..5d3d82b 100644 (file)
@@ -3,19 +3,20 @@
  * This file lets you extend IMP's menu with your own items.
  *
  * To add a new menu item, simply add a new entry to the $_menu array.
- * Valid attributes for a new menu item are:
  *
- *  'url'       The URL value for the menu item.
- *  'text'      The text to accompany the menu item.
+ * REQUIRED attributes for a menu item are:
  *
- * These attributes are optional:
+ *  'url'   The URL value for the menu item.
+ *  'text'  The text to accompany the menu item.
  *
- *  'action'    The javascript code for the menu item (dimp only).
- *  'icon'      The filename of an icon to use for the menu item.
- *  'icon_path' The path to the icon if it doesn't exist in the graphics/
- *              directory.
- *  'target'    The "target" of the link (e.g. '_top', '_blank').
- *  'onclick'   Any JavaScript to execute on the "onclick" event.
+ * These attributes are OPTIONAL:
+ *
+ *  'icon'       The filename of an icon to use for the menu item.
+ *  'icon_path'  The path to the icon if it doesn't exist in the graphics/
+ *               directory.
+ *  'onclick'    Javascript to execute on the "onclick" event (standard view
+                 only).
+ *  'target'     The "target" of the link (e.g. '_top', '_blank').
  *
  * Here's an example entry:
  *
@@ -24,9 +25,7 @@
  *      'text' =>       'Example, Inc.',
  *      'icon' =>       'example.png',
  *      'icon_path' =>  'http://www.example.com/images/',
- *      'target' =>     '_blank',
- *      'onclick' =>    '',
- *      'action' =>     ''
+ *      'target' =>     '_blank'
  *  );
  *
  * You can also add a "separator" (a spacer) between menu items.  To add a
index 9e4bf22..c29823a 100644 (file)
@@ -140,6 +140,13 @@ CSS
 TODO
 
 
+Menu
+----
+
+The dynamic view (DIMP) no longer supports the 'action' parameter located
+in config/menu.php.
+
+
 
 Upgrading IMP From 4.1.x To 4.2.x
 =================================
index 81ca4bc..b53af3f 100644 (file)
 require_once dirname(__FILE__) . '/lib/Application.php';
 Horde_Registry::appInit('imp', array('impmode' => 'dimp'));
 
-$scripts = array(
+/* Get site specific menu items. */
+$dimp_menu = new IMP_Menu_Dimp(Horde_Menu::MASK_BASE);
+$render_sidebar = $dimp_menu->render('sidebar');
+$render_tabs = $dimp_menu->render('tabs');
+$dimp_menu->addJs();
+
+Horde::noDnsPrefetch();
+IMP_Dimp::header('', array(
     array('dimpbase.js', 'imp'),
     array('viewport.js', 'imp'),
     array('dialog.js', 'imp'),
@@ -28,28 +35,7 @@ $scripts = array(
     array('popup.js', 'horde'),
     array('redbox.js', 'horde'),
     array('slider2.js', 'horde')
-);
-
-/* Get site specific menu items. */
-$js_code = $site_menu = array();
-if (is_readable(IMP_BASE . '/config/menu.php')) {
-    include IMP_BASE . '/config/menu.php';
-}
-
-/* Add the site specific javascript now. */
-if (!empty($site_menu)) {
-    foreach ($site_menu as $key => $menu_item) {
-        if ($menu_item != 'separator') {
-            foreach (array('menu', 'tab') as $val) {
-                $js_code[] = 'DimpCore.clickObserveHandler({ d: $(\'' . $val . $key . '\'), f: function() { ' . $menu_item['action'] . ' } })';
-            }
-        }
-    }
-}
-
-Horde::addInlineScript($js_code, 'load');
-Horde::noDnsPrefetch();
-IMP_Dimp::header('', $scripts);
+));
 
 echo "<body>\n";
 require IMP_TEMPLATES . '/dimp/index.inc';
index 3dac3f3..94af48e 100644 (file)
@@ -212,12 +212,22 @@ var DimpBase = {
                 this.go('folder:INBOX');
                 return;
             }
-            this.highlightSidebar('app' + app);
+            this.highlightSidebar();
             this.setHash(loc);
             if (data) {
                 this.iframeContent(loc, data);
-            } else if (DIMP.conf.app_urls[app]) {
-                this.iframeContent(loc, DIMP.conf.app_urls[app]);
+            } else if (DIMP.conf.portal_urls[app]) {
+                this.iframeContent(loc, DIMP.conf.portal_urls[app]);
+            }
+            return;
+        }
+
+        if (loc.startsWith('menu:')) {
+            app = loc.substr(5);
+            this.highlightSidebar();
+            this.setHash(loc);
+            if (DIMP.conf.menu_urls[app]) {
+                this.iframeContent(loc, DIMP.conf.menu_urls[app]);
             }
             return;
         }
@@ -2138,7 +2148,8 @@ var DimpBase = {
                     tmp = tmp.up('LI.custom');
                 }
                 if (tmp) {
-                    this.go('app:' + tmp.down('A').identify().substring(3));
+                    // Prefix is 'sidebarapp_'
+                    this.go('menu:' + tmp.down('A').identify().substring(11));
                     e.stop();
                     return;
                 }
@@ -2146,7 +2157,8 @@ var DimpBase = {
 
             case 'tabbar':
                 if (e.element().hasClassName('applicationtab')) {
-                    this.go('app:' + e.element().identify().substring(6));
+                    // Prefix is 'apptab_'
+                    this.go('menu:' + e.element().identify().substring(7));
                     e.stop();
                     return;
                 }
index e389908..e5e05f8 100644 (file)
@@ -126,20 +126,6 @@ class IMP_Dimp
     }
 
     /**
-     * Return a list of DIMP specific menu items.
-     *
-     * @return array  The array of menu items.
-     */
-    static public function menuList()
-    {
-        return (isset($GLOBALS['conf']['menu']['apps']) &&
-                is_array($GLOBALS['conf']['menu']['apps']) &&
-                count($GLOBALS['conf']['menu']['apps']))
-            ? $GLOBALS['conf']['menu']['apps']
-            : array();
-    }
-
-    /**
      * Build data structure needed by DimpCore javascript to display message
      * log information.
      *
diff --git a/imp/lib/Menu/Dimp.php b/imp/lib/Menu/Dimp.php
new file mode 100644 (file)
index 0000000..8600de5
--- /dev/null
@@ -0,0 +1,92 @@
+<?php
+/**
+ * This class builds the menu entries for use within IMP's dynamic view
+ * (dimp).
+ *
+ * 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@horde.org>
+ * @category Horde
+ * @license  http://www.fsf.org/copyleft/gpl.html GPL
+ * @package  IMP
+ */
+class IMP_Menu_Dimp extends Horde_Menu
+{
+    /**
+     * Has render() been called yet?
+     *
+     * @var boolean
+     */
+    protected $_renderCalled = false;
+
+    /**
+     * @param string $type  Either 'sidebar' or 'tabs'.
+     */
+    public function render($type)
+    {
+        if (!$this->_renderCalled) {
+            parent::render();
+
+            foreach ($this->_menu as $k => $v) {
+                if ($v == 'separator') {
+                    unset($this->_menu[$k]);
+                }
+            }
+
+            $this->_renderCalled = true;
+        }
+
+        $out = '';
+
+        foreach ($this->_menu as $k => $m) {
+            switch ($type) {
+            case 'sidebar':
+                $out .= '<li class="custom">' .
+                    Horde::img($m['icon'], Horde::stripAccessKey($m['text']), '', $m['icon_path']) .
+                    '<a id="sidebarapp_' . htmlspecialchars($k) . '">' . htmlspecialchars($m['text']) .
+                    '</a></li>';
+                break;
+
+            case 'tabs':
+                $out .= '<li>' .
+                    '<a class="applicationtab" id="apptab_' . htmlspecialchars($k) . '">' .
+                    Horde::img($m['icon'], Horde::stripAccessKey($m['text']), '', $m['icon_path']) .
+                    htmlspecialchars($m['text']) .
+                    '</a></li>';
+                break;
+            }
+        }
+
+        return $out;
+    }
+
+    /**
+     */
+    protected function _render()
+    {
+    }
+
+    /**
+     * Adds the necessary JS to the output string (list of keys -> URLs used
+     * by DimpBase).
+     */
+    public function addJs()
+    {
+        $out = array();
+
+        foreach ($this->_menu as $k => $v) {
+            $url = new Horde_Url($v['url']);
+            $out[$k] = strval($url->setRaw(true)->add('ajaxui', 1));
+        }
+
+        if (!empty($out)) {
+            Horde::addInlineJsVars(array(
+                'DIMP.conf.menu_urls' => $out
+            ));
+        }
+    }
+
+}
index 7c24a0b..67a2e6f 100644 (file)
@@ -15,20 +15,10 @@ $has_blacklist = $registry->hasMethod('mail/blacklistFrom');
 $has_whitelist = $registry->hasMethod('mail/whitelistFrom');
 
 // Quota information
-$show_quota = $session->get('imp', 'imap_quota');
-
-// Get application folders list.
-$application_folders = array();
-foreach (IMP_Dimp::menuList() as $app) {
-    if (($registry->get('status', $app) != 'inactive') &&
-        $registry->hasPermission($app, Horde_Perms::SHOW)) {
-        $application_folders[] = array(
-            'app' => rawurlencode($app),
-            'icon' => $registry->get('icon', $app),
-            'name' => htmlspecialchars($registry->get('name', $app))
-        );
-    }
-}
+$show_quota = $session->get('imp', 'imap_quota')
+    ? '<span class="used">' . Horde::img('quotauncover.gif') . '</span>'
+    : '';
+
 
 function _simpleButton($id, $text, $image, $nodisplay = false)
 {
@@ -80,36 +70,12 @@ function _simpleButton($id, $text, $image, $nodisplay = false)
    <div id="foldersLoading"><?php echo _("Loading...") ?></div>
    <div id="foldersSidebar" style="display:none">
     <ul class="folderlist" id="specialfolders"></ul>
-<?php if (!empty($application_folders)): ?>
+<?php if ($render_sidebar): ?>
     <div class="sepfull"></div>
     <ul id="sidebar_apps">
-<?php foreach ($application_folders as $val): ?>
-     <li class="custom">
-      <img src="<?php echo $val['icon'] ?>" alt="<?php echo $val['name'] ?>" />
-      <a title="<?php echo $val['name'] ?>" id="app<?php echo $val['app'] ?>"><?php echo $val['name'] ?></a>
-     </li>
-<?php endforeach; ?>
+     <?php echo $render_sidebar ?>
     </ul>
 <?php endif; ?>
-<?php if (!empty($site_menu)): ?>
-    <div id="sitemenu">
-     <div class="sepfull"></div>
-     <ul>
-<?php foreach ($site_menu as $key => $menu_item): ?>
-<?php if ($menu_item == 'separator'): ?>
-     </ul>
-     <div class="sepfull"></div>
-     <ul>
-<?php else: ?>
-      <li class="custom">
-       <img src="<?php echo $menu_item['icon'] ?>" alt="<?php echo $menu_item['text'] ?>" />
-       <a title="<?php echo $menu_item['text'] ?>" id="menu<?php echo $key ?>"><?php echo $menu_item['text'] ?></a>
-      </li>
-<?php endif; ?>
-<?php endforeach; ?>
-     </ul>
-    </div>
-<?php endif; ?>
 <?php if ($session->get('imp', 'protocol') != 'pop'): ?>
     <div class="sepfull"></div>
     <ul class="folderlist" id="normalfolders">
@@ -131,32 +97,23 @@ function _simpleButton($id, $text, $image, $nodisplay = false)
    <div id="dimpmain_folder" style="display:none">
     <div id="dimpmain_folder_top">
      <div id="tabbar">
-<?php if (!empty($application_folders) || !empty($site_menu)): ?>
+<?php if (!empty($render_tabs)): ?>
       <div class="tabset">
        <ul>
         <li>
          <a id="hometab"><img src="<?php echo $registry->get('icon', 'horde') ?>" alt="<?php echo _("Portal") ?>" /><?php echo _("Portal") ?></a>
         </li>
-<?php foreach ($application_folders as $val): ?>
-        <li<?php if ($val['app'] == 'dimp') echo ' class="activeTab"' ?>>
-         <a class="applicationtab" id="apptab<?php echo $val['app'] ?>"><img src="<?php echo $val['icon'] ?>" alt="<?php echo $val['name'] ?>" /><?php echo $val['name'] ?></a>
-        </li>
-<?php endforeach; ?>
-<?php foreach ($site_menu as $key => $menu_item): if ($menu_item == 'separator') continue; ?>
-        <li>
-         <a id="tab<?php echo $key ?>"><img src="<?php echo $menu_item['icon'] ?>" alt="<?php echo $menu_item['text'] ?>" /><?php echo $menu_item['text'] ?></a>
-        </li>
-<?php endforeach; ?>
+        <?php echo $render_tabs ?>
 <?php if ($show_quota): ?>
         <li id="quota">
-         <span class="used"><?php echo Horde::img('quotauncover.gif') ?></span>
+         <?php echo $show_quota ?>
         </li>
 <?php endif; ?>
        </ul>
       </div>
 <?php elseif ($show_quota): ?>
       <div id="quota">
-        <span class="used"><?php echo Horde::img('quotauncover.gif') ?></span>
+        <?php echo $show_quota ?>
       </div>
 <?php endif; ?>
      </div>
index 0b98687..53f6a68 100644 (file)
@@ -8,18 +8,19 @@
  * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
  */
 
-$app_urls = $code = $filters = $flags = array();
-
-foreach (IMP_Dimp::menuList() as $app) {
-    $app_urls[$app] = strval(Horde::url($GLOBALS['registry']->getInitialPage($app), true)->add('ajaxui', 1));
-}
-
-include IMP_BASE . '/config/portal.php';
-foreach ($dimp_block_list as $block) {
-    if ($block['ob'] instanceof Horde_Block) {
-        $app = $block['ob']->getApp();
-        if (empty($app_urls[$app])) {
-            $app_urls[$app] = strval(Horde::url($GLOBALS['registry']->getInitialPage($app), true)->add('ajaxui', 1));
+$code = $filters = $flags = $portal_urls = array();
+
+$compose_page = in_array(basename($_SERVER['PHP_SELF']), array('compose-dimp.php', 'message-dimp.php'));
+
+/* Add portal links - base page only. */
+if (!$compose_page) {
+    include IMP_BASE . '/config/portal.php';
+    foreach ($dimp_block_list as $block) {
+        if ($block['ob'] instanceof Horde_Block) {
+            $app = $block['ob']->getApp();
+            if (empty($portal_urls[$app])) {
+                $portal_urls[$app] = strval(Horde::url($GLOBALS['registry']->getInitialPage($app), true));
+            }
         }
     }
 }
@@ -63,7 +64,6 @@ $code['conf'] = array_filter(array(
     'SESSION_ID' => defined('SID') ? SID : '',
 
     // Other variables
-    'app_urls' => $app_urls,
     'buffer_pages' => intval($GLOBALS['conf']['dimp']['viewport']['buffer_pages']),
     'disable_compose' => !IMP::canCompose(),
     'filter_any' => intval($GLOBALS['prefs']->getValue('filter_any_mailbox')),
@@ -84,6 +84,7 @@ $code['conf'] = array_filter(array(
     'pop3' => intval($GLOBALS['session']->get('imp', 'protocol') == 'pop'),
     'popup_height' => 610,
     'popup_width' => 820,
+    'portal_urls' => $portal_urls,
     'preview_pref' => $GLOBALS['prefs']->getValue('dimp_show_preview'),
     'qsearchid' => IMP_Search::MBOX_PREFIX . IMP_Search::DIMP_QUICKSEARCH,
     'qsearchfield' => $GLOBALS['prefs']->getValue('dimp_qsearch_field'),
@@ -165,7 +166,7 @@ $code['text'] = array(
     'vp_empty' => _("There are no messages in this mailbox."),
 );
 
-if (in_array(basename($_SERVER['PHP_SELF']), array('compose-dimp.php', 'message-dimp.php'))){
+if ($compose_page) {
     $compose_cursor = $GLOBALS['prefs']->getValue('compose_cursor');
 
     /* Variables used in compose page. */