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