1<?php 2/** 3 * The Horde_Menu:: class provides standardized methods for creating menus in 4 * Horde applications. 5 * 6 * Copyright 1999-2017 Horde LLC (http://www.horde.org/) 7 * 8 * See the enclosed file COPYING for license information (LGPL). If you 9 * did not receive this file, see http://www.horde.org/licenses/lgpl21. 10 * 11 * @author Chuck Hagenbuch <chuck@horde.org> 12 * @author Jon Parise <jon@horde.org> 13 * @category Horde 14 * @package Core 15 */ 16class Horde_Menu 17{ 18 /** 19 * Menu array. 20 * 21 * @var array 22 */ 23 protected $_menu = array(); 24 25 /** 26 * Add an item to the menu array. 27 * 28 * @param string $url String containing the value for the hyperlink. 29 * @param string $text String containing the label for this menu 30 * item. 31 * @param string $icon String containing the filename of the image 32 * icon to display for this menu item. 33 * @param string $icon_path If the icon lives in a non-default directory, 34 * where is it? 35 * @param string $target If the link needs to open in another frame or 36 * window, what is its name? 37 * @param string $onclick Onclick javascript, if desired. 38 * @param string $class CSS class for the menu item. 39 */ 40 public function add($url, $text, $icon = '', $icon_path = null, 41 $target = '', $onclick = null, $class = null) 42 { 43 $this->_menu[] = array( 44 'url' => ($url instanceof Horde_Url) ? $url : new Horde_Url($url), 45 'text' => $text, 46 'icon' => $icon, 47 'icon_path' => $icon_path, 48 'target' => $target, 49 'onclick' => $onclick, 50 'class' => $class 51 ); 52 } 53 54 /** 55 * Add an item to the menu array. 56 * 57 * @param mixed $item The item to add. Either a string containing the 58 * value 'separator' or an array contianing the 59 * following valid keys: 60 * <pre> 61 * 'class' - (string) CSS classname. 62 * 'icon' - (string) Filename of the image icon. 63 * 'icon_path' - (string) Non-default directory path for icon. 64 * 'onclick' - (string) Onclick javascript. 65 * 'target' - (string) HREF target parameter. 66 * 'text' - (string) Label. 67 * 'url' - (string) Hyperlink. 68 * 'container' - (string) Name of sidebar container to add to, if not the 69 * default. 70 * </pre> 71 */ 72 public function addArray($item) 73 { 74 if (!is_array($item) && $item == 'separator') { 75 $this->_menu[] = $item; 76 return; 77 } 78 79 if (!isset($item['url'])) { 80 $item['url'] = new Horde_Url(); 81 } elseif (!($item['url'] instanceof Horde_Url)) { 82 $item['url'] = new Horde_Url($item['url']); 83 } 84 85 $this->_menu[] = array_merge(array( 86 'class' => null, 87 'icon' => '', 88 'icon_path' => null, 89 'onclick' => null, 90 'target' => '', 91 'text' => '', 92 'container' => '', 93 ), $item); 94 } 95 96 /** 97 * Return the rendered representation of the menu items. 98 * 99 * @return Horde_View_Sidebar Sidebar view of menu elements. 100 */ 101 public function render() 102 { 103 /* Add any custom menu items. */ 104 $this->addSiteLinks(); 105 106 /* Sort to match explicitly set positions. */ 107 ksort($this->_menu); 108 if ($GLOBALS['registry']->nlsconfig->curr_rtl) { 109 $this->_menu = array_reverse($this->_menu); 110 } 111 112 return $this->_render(); 113 } 114 115 /** 116 * Converts the menu to a sidebar view. 117 * 118 * @return Horde_View_Sidebar Sidebar view of menu elements. 119 */ 120 protected function _render() 121 { 122 $sidebar = $GLOBALS['injector']->getInstance('Horde_View_Sidebar'); 123 124 foreach ($this->_menu as $m) { 125 /* Check for separators. */ 126 if ($m == 'separator') { 127 continue; 128 } 129 130 $row = array( 131 'cssClass' => $m['icon'], 132 'url' => $m['url'], 133 'label' => $m['text'], 134 'target' => $m['target'], 135 'onclick' => $m['onclick'], 136 ); 137 138 /* Item class and selected indication. */ 139 if (!isset($m['class'])) { 140 /* Try to match the item's path against the current 141 * script filename as well as other possible URLs to 142 * this script. */ 143 if ($this->isSelected($m['url'])) { 144 $row['selected'] = true; 145 } 146 } elseif ($m['class'] === '__noselection') { 147 unset($m['class']); 148 } elseif ($m['class'] === 'current') { 149 $row['selected'] = true; 150 } else { 151 $row['class'] = $m['class']; 152 } 153 154 $container = !empty($m['container']) 155 ? $m['container'] 156 : ''; 157 158 $sidebar->addRow($row, $container); 159 } 160 161 return $sidebar; 162 } 163 164 /** 165 * Add links found in the application's menu configuration. 166 */ 167 public function addSiteLinks() 168 { 169 foreach ($this->getSiteLinks() as $item) { 170 $this->addArray($item); 171 } 172 } 173 174 /** 175 * Get the list of site links to add to the menu. 176 * 177 * @return array A list of menu items to add. 178 */ 179 public function getSiteLinks() 180 { 181 $menufile = $GLOBALS['registry']->get('fileroot') . '/config/menu.php'; 182 183 if (is_readable($menufile)) { 184 include $menufile; 185 if (isset($_menu) && is_array($_menu)) { 186 return $_menu; 187 } 188 } 189 190 return array(); 191 } 192 193 /** 194 * Checks to see if the current url matches the given url. 195 * 196 * @return boolean Whether the given URL is the current location. 197 */ 198 public static function isSelected($url) 199 { 200 $server_url = parse_url($_SERVER['PHP_SELF']); 201 $check_url = parse_url($url); 202 203 /* Try to match the item's path against the current script 204 filename as well as other possible URLs to this script. */ 205 return isset($check_url['path']) && 206 (($check_url['path'] == $server_url['path']) || 207 ($check_url['path'] . 'index.php' == $server_url['path']) || 208 ($check_url['path'] . '/index.php' == $server_url['path'])); 209 } 210 211} 212