xref: /webtrees/app/Menu.php (revision 3cf92ae205660ec36316541b9e23f2ecbf0af8bb)
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