1<?php 2/** 3 * webtrees: online genealogy 4 * Copyright (C) 2017 webtrees development team 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16namespace Fisharebest\Webtrees; 17 18/** 19 * System for generating menus. 20 */ 21class Menu { 22 /** @var string The text to be displayed in the mneu */ 23 private $label; 24 25 /** @var string The target URL or href*/ 26 private $link; 27 28 /** @var string The CSS class used to style this menu item */ 29 private $class; 30 31 /** @var string[] A list of optional HTML attributes, such as onclick or data-xxx */ 32 private $attrs; 33 34 /** @var Menu[] An optional list of sub-menus. */ 35 private $submenus; 36 37 /** @var string Used internally to create javascript menus */ 38 private $parentmenu; 39 40 /** @var string Used to format javascript menus */ 41 private $submenuclass; 42 43 /** @var string Used to format javascript menus */ 44 private $menuclass; 45 46 /** 47 * Constructor for the menu class 48 * 49 * @param string $label The label for the menu item 50 * @param string $link The target URL 51 * @param string $class A CSS class 52 * @param string[] $attrs Optional attributes, such as onclick or data-xxx 53 * @param Menu[] $submenus Any submenus 54 */ 55 public function __construct($label, $link = '#', $class = '', array $attrs = [], array $submenus = []) { 56 $this 57 ->setLabel($label) 58 ->setLink($link) 59 ->setClass($class) 60 ->setAttrs($attrs) 61 ->setSubmenus($submenus); 62 } 63 64 /** 65 * Render this menu using Bootstrap4 markup 66 * 67 * @return string 68 */ 69 public function bootstrap4() { 70 if ($this->submenus) { 71 $submenus = ''; 72 foreach ($this->submenus as $submenu) { 73 $attrs = ''; 74 foreach ($submenu->attrs as $key => $value) { 75 $attrs .= ' ' . $key . '="' . Filter::escapeHtml($value) . '"'; 76 } 77 78 $class = trim('dropdown-item ' . $submenu->class); 79 $submenus .= '<a class="' . $class . '" href="' . $submenu->link . '"' . $attrs . '>' . $submenu->label . '</a>'; 80 } 81 82 $class = trim('nav-item dropdown ' . $this->class); 83 84 return 85 '<li class="' . $class . '">' . 86 '<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">' . 87 $this->label . 88 '<span class="caret"></span></a>' . 89 '<div class="dropdown-menu" role="menu">' . 90 $submenus . 91 '</div>' . 92 '</li>'; 93 } else { 94 $attrs = ''; 95 foreach ($this->attrs as $key => $value) { 96 $attrs .= ' ' . $key . '="' . Filter::escapeHtml($value) . '"'; 97 } 98 99 $class = trim('nav-item ' . $this->class); 100 101 return '<li class="' . $class . '"><a class="nav-link" href="' . $this->link . '"' . $attrs . '>' . $this->label . '</a></li>'; 102 } 103 } 104 105 /** 106 * Get the optional attributes. 107 * 108 * @return string[] 109 */ 110 public function getAttrs() { 111 return $this->attrs; 112 } 113 114 /** 115 * Set the optional attributes. 116 * 117 * @param string[] $attrs 118 * 119 * @return $this 120 */ 121 public function setAttrs(array $attrs) { 122 $this->attrs = $attrs; 123 124 return $this; 125 } 126 127 /** 128 * Set the CSS classes for the (legacy) javascript menus 129 * 130 * @param string $menuclass 131 * @param string $submenuclass 132 */ 133 public function addClass($menuclass, $submenuclass = '') { 134 $this->menuclass = $menuclass; 135 $this->submenuclass = $submenuclass; 136 } 137 138 /** 139 * Get the class. 140 * 141 * @return string 142 */ 143 public function getClass() { 144 return $this->class; 145 } 146 147 /** 148 * Set the class. 149 * 150 * @param string $class 151 * 152 * @return $this 153 */ 154 public function setClass($class) { 155 $this->class = $class; 156 157 return $this; 158 } 159 160 /** 161 * Get the label. 162 * 163 * @return string 164 */ 165 public function getLabel() { 166 return $this->label; 167 } 168 169 /** 170 * Set the label. 171 * 172 * @param string $label 173 * 174 * @return $this 175 */ 176 public function setLabel($label) { 177 $this->label = $label; 178 179 return $this; 180 } 181 182 /** 183 * Get the link. 184 * 185 * @return string 186 */ 187 public function getLink() { 188 return $this->link; 189 } 190 191 /** 192 * Set the link. 193 * 194 * @param string $link 195 * 196 * @return $this 197 */ 198 public function setLink($link) { 199 $this->link = $link; 200 201 return $this; 202 } 203 204 /** 205 * Add a submenu to this menu 206 * 207 * @param Menu $menu 208 * 209 * @return $this 210 */ 211 public function addSubmenu($menu) { 212 $this->submenus[] = $menu; 213 214 return $this; 215 } 216 217 /** 218 * Render this menu as an HTML list 219 * 220 * @return string 221 */ 222 public function getMenuAsList() { 223 $attrs = ''; 224 foreach ($this->attrs as $key => $value) { 225 $attrs .= ' ' . $key . '="' . Filter::escapeHtml($value) . '"'; 226 } 227 if ($this->link) { 228 $link = ' href="' . $this->link . '"'; 229 } else { 230 $link = ''; 231 } 232 $html = '<a' . $link . $attrs . '>' . $this->label . '</a>'; 233 if ($this->submenus) { 234 $html .= '<ul>'; 235 foreach ($this->submenus as $submenu) { 236 $html .= $submenu->getMenuAsList(); 237 } 238 $html .= '</ul>'; 239 } 240 241 return '<li class="' . $this->class . '">' . $html . '</li>'; 242 } 243 244 /** 245 * Get the sub-menus. 246 * 247 * @return Menu[] 248 */ 249 public function getSubmenus() { 250 return $this->submenus; 251 } 252 253 /** 254 * Set the sub-menus. 255 * 256 * @param Menu[] $submenus 257 * 258 * @return $this 259 */ 260 public function setSubmenus(array $submenus) { 261 $this->submenus = $submenus; 262 263 return $this; 264 } 265} 266