1a25f0a04SGreg Roach<?php 2a25f0a04SGreg Roach/** 3a25f0a04SGreg Roach * webtrees: online genealogy 4a25f0a04SGreg Roach * Copyright (C) 2015 webtrees development team 5a25f0a04SGreg Roach * This program is free software: you can redistribute it and/or modify 6a25f0a04SGreg Roach * it under the terms of the GNU General Public License as published by 7a25f0a04SGreg Roach * the Free Software Foundation, either version 3 of the License, or 8a25f0a04SGreg Roach * (at your option) any later version. 9a25f0a04SGreg Roach * This program is distributed in the hope that it will be useful, 10a25f0a04SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 11a25f0a04SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12a25f0a04SGreg Roach * GNU General Public License for more details. 13a25f0a04SGreg Roach * You should have received a copy of the GNU General Public License 14a25f0a04SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>. 15a25f0a04SGreg Roach */ 1676692c8bSGreg Roachnamespace Fisharebest\Webtrees; 17a25f0a04SGreg Roach 18fee045eeSGreg Roachuse Rhumsaa\Uuid\Uuid; 19fee045eeSGreg Roach 20a25f0a04SGreg Roach/** 2176692c8bSGreg Roach * System for generating menus. 22a25f0a04SGreg Roach */ 23a25f0a04SGreg Roachclass Menu { 24a25f0a04SGreg Roach /** @var string The text to be displayed in the mneu */ 25a25f0a04SGreg Roach private $label; 26a25f0a04SGreg Roach 27a25f0a04SGreg Roach /** @var string The target URL or href*/ 28a25f0a04SGreg Roach private $link; 29a25f0a04SGreg Roach 303d0a6fa1SGreg Roach /** @var string The CSS class used to style this menu item */ 313d0a6fa1SGreg Roach private $class; 32a25f0a04SGreg Roach 33*3cf92ae2SGreg Roach /** @var string[] A list of optional HTML attributes, such as onclick or data-xxx */ 34*3cf92ae2SGreg Roach private $attrs; 35a25f0a04SGreg Roach 3676692c8bSGreg Roach /** @var Menu[] An optional list of sub-menus. */ 37a25f0a04SGreg Roach private $submenus; 38a25f0a04SGreg Roach 39a25f0a04SGreg Roach /** @var string Used internally to create javascript menus */ 40a25f0a04SGreg Roach private $parentmenu; 41a25f0a04SGreg Roach 42a25f0a04SGreg Roach /** @var string Used to format javascript menus */ 43a25f0a04SGreg Roach private $submenuclass; 44a25f0a04SGreg Roach 45a25f0a04SGreg Roach /** @var string Used to format javascript menus */ 463d0a6fa1SGreg Roach private $menuclass; 47a25f0a04SGreg Roach 48a25f0a04SGreg Roach /** 49a25f0a04SGreg Roach * Constructor for the menu class 50a25f0a04SGreg Roach * 51a25f0a04SGreg Roach * @param string $label The label for the menu item 52a25f0a04SGreg Roach * @param string $link The target URL 53*3cf92ae2SGreg Roach * @param string $class A CSS class 54*3cf92ae2SGreg Roach * @param string[] $attrs Optional attributes, such as onclick or data-xxx 55a25f0a04SGreg Roach * @param Menu[] $submenus Any submenus 56a25f0a04SGreg Roach */ 57*3cf92ae2SGreg Roach public function __construct($label, $link = '#', $class = '', array $attrs = array(), array $submenus = array()) { 58a25f0a04SGreg Roach $this 59a25f0a04SGreg Roach ->setLabel($label) 60a25f0a04SGreg Roach ->setLink($link) 613d0a6fa1SGreg Roach ->setClass($class) 62*3cf92ae2SGreg Roach ->setAttrs($attrs) 63a25f0a04SGreg Roach ->setSubmenus($submenus); 64a25f0a04SGreg Roach } 65a25f0a04SGreg Roach 66a25f0a04SGreg Roach /** 67a25f0a04SGreg Roach * Convert this menu to an HTML list, for easy rendering of 68a25f0a04SGreg Roach * lists of menus/nulls. 69a25f0a04SGreg Roach * 70a25f0a04SGreg Roach * @return string 71a25f0a04SGreg Roach */ 72a25f0a04SGreg Roach public function __toString() { 73a25f0a04SGreg Roach return $this->getMenuAsList(); 74a25f0a04SGreg Roach } 75a25f0a04SGreg Roach 76a25f0a04SGreg Roach /** 77a25f0a04SGreg Roach * Render this menu using Bootstrap markup 78a25f0a04SGreg Roach * 79a25f0a04SGreg Roach * @return string 80a25f0a04SGreg Roach */ 81a25f0a04SGreg Roach public function bootstrap() { 82a25f0a04SGreg Roach if ($this->submenus) { 83a25f0a04SGreg Roach $submenus = ''; 84a25f0a04SGreg Roach foreach ($this->submenus as $submenu) { 85a25f0a04SGreg Roach $submenus .= $submenu->bootstrap(); 86a25f0a04SGreg Roach } 87a25f0a04SGreg Roach 88a25f0a04SGreg Roach return 893d0a6fa1SGreg Roach '<li class="' . $this->class . ' dropdown">' . 90a25f0a04SGreg Roach '<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">' . 91a25f0a04SGreg Roach $this->label . 92a25f0a04SGreg Roach ' <span class="caret"></span></a>' . 93a25f0a04SGreg Roach '<ul class="dropdown-menu" role="menu">' . 94a25f0a04SGreg Roach $submenus . 95a25f0a04SGreg Roach '</ul>' . 96a25f0a04SGreg Roach '</li>'; 97a25f0a04SGreg Roach } else { 98*3cf92ae2SGreg Roach $attrs = ''; 99*3cf92ae2SGreg Roach foreach ($this->attrs as $key => $value) { 100*3cf92ae2SGreg Roach $attrs .= ' ' . $key . '="' . Filter::escapeHtml($value) . '"'; 101a25f0a04SGreg Roach } 102a25f0a04SGreg Roach 103*3cf92ae2SGreg Roach return '<li class="' . $this->class . '"><a href="' . $this->link . '"' . $attrs . '>' . $this->label . '</a></li>'; 104a25f0a04SGreg Roach } 105a25f0a04SGreg Roach } 106a25f0a04SGreg Roach 107a25f0a04SGreg Roach /** 108*3cf92ae2SGreg Roach * Get the optional attributes. 109*3cf92ae2SGreg Roach * 110*3cf92ae2SGreg Roach * @return string[] 111*3cf92ae2SGreg Roach */ 112*3cf92ae2SGreg Roach public function getAttrs() { 113*3cf92ae2SGreg Roach return $this->attrs; 114*3cf92ae2SGreg Roach } 115*3cf92ae2SGreg Roach 116*3cf92ae2SGreg Roach /** 117*3cf92ae2SGreg Roach * Set the optional attributes. 118*3cf92ae2SGreg Roach * 119*3cf92ae2SGreg Roach * @param string[] $attrs 120*3cf92ae2SGreg Roach * 121*3cf92ae2SGreg Roach * @return $this 122*3cf92ae2SGreg Roach */ 123*3cf92ae2SGreg Roach public function setAttrs(array $attrs) { 124*3cf92ae2SGreg Roach $this->attrs = $attrs; 125*3cf92ae2SGreg Roach 126*3cf92ae2SGreg Roach return $this; 127*3cf92ae2SGreg Roach } 128*3cf92ae2SGreg Roach 129*3cf92ae2SGreg Roach /** 1303d0a6fa1SGreg Roach * Set the CSS classes for the (legacy) javascript menus 131a25f0a04SGreg Roach * 132794c6b5bSGreg Roach * @param string $menuclass 133a25f0a04SGreg Roach * @param string $submenuclass 134a25f0a04SGreg Roach */ 135cfd4d92fSGreg Roach public function addClass($menuclass, $submenuclass = '') { 1363d0a6fa1SGreg Roach $this->menuclass = $menuclass; 137a25f0a04SGreg Roach $this->submenuclass = $submenuclass; 138a25f0a04SGreg Roach } 139a25f0a04SGreg Roach 140a25f0a04SGreg Roach /** 14176692c8bSGreg Roach * Get the class. 14276692c8bSGreg Roach * 143a25f0a04SGreg Roach * @return string 144a25f0a04SGreg Roach */ 1453d0a6fa1SGreg Roach public function getClass() { 1463d0a6fa1SGreg Roach return $this->class; 147a25f0a04SGreg Roach } 148a25f0a04SGreg Roach 149a25f0a04SGreg Roach /** 15076692c8bSGreg Roach * Set the class. 15176692c8bSGreg Roach * 1523d0a6fa1SGreg Roach * @param string $class 153a25f0a04SGreg Roach * 154a25f0a04SGreg Roach * @return $this 155a25f0a04SGreg Roach */ 1563d0a6fa1SGreg Roach public function setClass($class) { 1573d0a6fa1SGreg Roach $this->class = $class; 158a25f0a04SGreg Roach 159a25f0a04SGreg Roach return $this; 160a25f0a04SGreg Roach } 161a25f0a04SGreg Roach 162a25f0a04SGreg Roach /** 16376692c8bSGreg Roach * Get the label. 16476692c8bSGreg Roach * 165a25f0a04SGreg Roach * @return string 166a25f0a04SGreg Roach */ 167a25f0a04SGreg Roach public function getLabel() { 168a25f0a04SGreg Roach return $this->label; 169a25f0a04SGreg Roach } 170a25f0a04SGreg Roach 171a25f0a04SGreg Roach /** 17276692c8bSGreg Roach * Set the label. 17376692c8bSGreg Roach * 174a25f0a04SGreg Roach * @param string $label 175a25f0a04SGreg Roach * 176a25f0a04SGreg Roach * @return $this 177a25f0a04SGreg Roach */ 178a25f0a04SGreg Roach public function setLabel($label) { 179a25f0a04SGreg Roach $this->label = $label; 180a25f0a04SGreg Roach 181a25f0a04SGreg Roach return $this; 182a25f0a04SGreg Roach } 183a25f0a04SGreg Roach 184a25f0a04SGreg Roach /** 18576692c8bSGreg Roach * Get the link. 186*3cf92ae2SGreg Roach * 187a25f0a04SGreg Roach * @return string 188a25f0a04SGreg Roach */ 189a25f0a04SGreg Roach public function getLink() { 190a25f0a04SGreg Roach return $this->link; 191a25f0a04SGreg Roach } 192a25f0a04SGreg Roach 193a25f0a04SGreg Roach /** 19476692c8bSGreg Roach * Set the link. 19576692c8bSGreg Roach * 196a25f0a04SGreg Roach * @param string $link 197a25f0a04SGreg Roach * 198a25f0a04SGreg Roach * @return $this 199a25f0a04SGreg Roach */ 200a25f0a04SGreg Roach public function setLink($link) { 201a25f0a04SGreg Roach $this->link = $link; 202a25f0a04SGreg Roach 203a25f0a04SGreg Roach return $this; 204a25f0a04SGreg Roach } 205a25f0a04SGreg Roach 206a25f0a04SGreg Roach /** 207a25f0a04SGreg Roach * Add a submenu to this menu 208a25f0a04SGreg Roach * 209ecb5b5e9SGreg Roach * @param Menu $menu 210ecb5b5e9SGreg Roach * 211ecb5b5e9SGreg Roach * @return $this 212a25f0a04SGreg Roach */ 213a25f0a04SGreg Roach public function addSubmenu($menu) { 214a25f0a04SGreg Roach $this->submenus[] = $menu; 215ecb5b5e9SGreg Roach 216ecb5b5e9SGreg Roach return $this; 217a25f0a04SGreg Roach } 218a25f0a04SGreg Roach 219a25f0a04SGreg Roach /** 220a25f0a04SGreg Roach * Render this menu using javascript popups.. 221a25f0a04SGreg Roach * 222a25f0a04SGreg Roach * @return string 223a25f0a04SGreg Roach */ 224a25f0a04SGreg Roach public function getMenu() { 225fee045eeSGreg Roach $menu_id = 'menu-' . Uuid::uuid4(); 226fee045eeSGreg Roach $sub_menu_id = 'sub-' . $menu_id; 227a25f0a04SGreg Roach 228fee045eeSGreg Roach $html = '<a href="' . $this->link . '"'; 229*3cf92ae2SGreg Roach foreach ($this->attrs as $key => $value) { 230*3cf92ae2SGreg Roach $html .= ' ' . $key . '="' . Filter::escapeHtml($value) . '"'; 231a25f0a04SGreg Roach } 232fee045eeSGreg Roach if (!empty($this->submenus)) { 233fee045eeSGreg Roach $html .= ' onmouseover="show_submenu(\'' . $sub_menu_id . '\', \'' . $menu_id . '\');"'; 234fee045eeSGreg Roach $html .= ' onmouseout="timeout_submenu(\'' . $sub_menu_id . '\');"'; 235fee045eeSGreg Roach } 236fee045eeSGreg Roach $html .= '>' . $this->label . '</a>'; 237a25f0a04SGreg Roach 238fee045eeSGreg Roach if (!empty($this->submenus)) { 239fee045eeSGreg Roach $html .= '<div id="' . $sub_menu_id . '" class="' . $this->submenuclass . '"'; 240fee045eeSGreg Roach $html .= ' style="position: absolute; visibility: hidden; z-index: 100; text-align: ' . (I18N::direction() === 'ltr' ? 'left' : 'right') . '"'; 241fee045eeSGreg Roach $html .= ' onmouseover="show_submenu(\'' . $this->parentmenu . '\'); show_submenu(\'' . $sub_menu_id . '\');"'; 242fee045eeSGreg Roach $html .= ' onmouseout="timeout_submenu(\'' . $sub_menu_id . '\');">'; 243a25f0a04SGreg Roach foreach ($this->submenus as $submenu) { 244fee045eeSGreg Roach $submenu->parentmenu = $sub_menu_id; 245fee045eeSGreg Roach $html .= $submenu->getMenu(); 246a25f0a04SGreg Roach } 247fee045eeSGreg Roach $html .= '</div></div>'; 248a25f0a04SGreg Roach } 249a25f0a04SGreg Roach 250fee045eeSGreg Roach return '<div id="' . $menu_id . '" class="' . $this->menuclass . '">' . $html . '</div>'; 251a25f0a04SGreg Roach } 252a25f0a04SGreg Roach 253a25f0a04SGreg Roach /** 254a25f0a04SGreg Roach * Render this menu as an HTML list 255a25f0a04SGreg Roach * 256a25f0a04SGreg Roach * @return string 257a25f0a04SGreg Roach */ 258a25f0a04SGreg Roach public function getMenuAsList() { 259*3cf92ae2SGreg Roach $attrs = ''; 260*3cf92ae2SGreg Roach foreach ($this->attrs as $key => $value) { 261*3cf92ae2SGreg Roach $attrs .= ' ' . $key . '="' . Filter::escapeHtml($value) . '"'; 262a25f0a04SGreg Roach } 263a25f0a04SGreg Roach if ($this->link) { 264a25f0a04SGreg Roach $link = ' href="' . $this->link . '"'; 265a25f0a04SGreg Roach } else { 266a25f0a04SGreg Roach $link = ''; 267a25f0a04SGreg Roach } 268*3cf92ae2SGreg Roach $html = '<a' . $link . $attrs . '>' . $this->label . '</a>'; 269a25f0a04SGreg Roach if ($this->submenus) { 270a25f0a04SGreg Roach $html .= '<ul>'; 271a25f0a04SGreg Roach foreach ($this->submenus as $submenu) { 272a25f0a04SGreg Roach $html .= $submenu->getMenuAsList(); 273a25f0a04SGreg Roach } 274a25f0a04SGreg Roach $html .= '</ul>'; 275a25f0a04SGreg Roach } 276a25f0a04SGreg Roach 2773d0a6fa1SGreg Roach return '<li class="' . $this->class . '">' . $html . '</li>'; 278a25f0a04SGreg Roach } 279a25f0a04SGreg Roach 280a25f0a04SGreg Roach /** 28176692c8bSGreg Roach * Get the sub-menus. 28276692c8bSGreg Roach * 283a25f0a04SGreg Roach * @return Menu[] 284a25f0a04SGreg Roach */ 285a25f0a04SGreg Roach public function getSubmenus() { 286a25f0a04SGreg Roach return $this->submenus; 287a25f0a04SGreg Roach } 288a25f0a04SGreg Roach 289a25f0a04SGreg Roach /** 29076692c8bSGreg Roach * Set the sub-menus. 29176692c8bSGreg Roach * 292a25f0a04SGreg Roach * @param Menu[] $submenus 293a25f0a04SGreg Roach * 294a25f0a04SGreg Roach * @return $this 295a25f0a04SGreg Roach */ 296a25f0a04SGreg Roach public function setSubmenus(array $submenus) { 297a25f0a04SGreg Roach $this->submenus = $submenus; 298a25f0a04SGreg Roach 299a25f0a04SGreg Roach return $this; 300a25f0a04SGreg Roach } 301a25f0a04SGreg Roach} 302