xref: /webtrees/app/Menu.php (revision ed53a9c0a479c5871db36fde10b575b33b9a209b)
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 to format javascript menus */
38	private $submenuclass;
39
40	/** @var string Used to format javascript menus */
41	private $menuclass;
42
43	/**
44	 * Constructor for the menu class
45	 *
46	 * @param string   $label    The label for the menu item
47	 * @param string   $link     The target URL
48	 * @param string   $class    A CSS class
49	 * @param string[] $attrs    Optional attributes, such as onclick or data-xxx
50	 * @param Menu[]   $submenus Any submenus
51	 */
52	public function __construct($label, $link = '#', $class = '', array $attrs = [], array $submenus = []) {
53		$this
54			->setLabel($label)
55			->setLink($link)
56			->setClass($class)
57			->setAttrs($attrs)
58			->setSubmenus($submenus);
59	}
60
61	/**
62	 * Render this menu using Bootstrap4 markup
63	 *
64	 * @return string
65	 */
66	public function bootstrap4() {
67		if ($this->submenus) {
68			$submenus = '';
69			foreach ($this->submenus as $submenu) {
70				$attrs = '';
71				foreach ($submenu->attrs as $key => $value) {
72					$attrs .= ' ' . $key . '="' . Html::escape($value) . '"';
73				}
74
75				$class = trim('dropdown-item ' . $submenu->class);
76				$submenus .= '<a class="' . $class . '" href="' . $submenu->link . '"' . $attrs . '>' . $submenu->label . '</a>';
77			}
78
79			$class = trim('nav-item dropdown ' . $this->class);
80
81			return
82				'<li class="' . $class . '">' .
83				'<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">' .
84				$this->label .
85				'<span class="caret"></span></a>' .
86				'<div class="dropdown-menu" role="menu">' .
87				$submenus .
88				'</div>' .
89				'</li>';
90		} else {
91			$attrs = '';
92			foreach ($this->attrs as $key => $value) {
93				$attrs .= ' ' . $key . '="' . Html::escape($value) . '"';
94			}
95
96			$class = trim('nav-item ' . $this->class);
97
98			return '<li class="' . $class . '"><a class="nav-link" href="' . $this->link . '"' . $attrs . '>' . $this->label . '</a></li>';
99		}
100	}
101
102	/**
103	 * Get the optional attributes.
104	 *
105	 * @return string[]
106	 */
107	public function getAttrs() {
108		return $this->attrs;
109	}
110
111	/**
112	 * Set the optional attributes.
113	 *
114	 * @param string[] $attrs
115	 *
116	 * @return $this
117	 */
118	public function setAttrs(array $attrs) {
119		$this->attrs = $attrs;
120
121		return $this;
122	}
123
124	/**
125	 * Set the CSS classes for the (legacy) javascript menus
126	 *
127	 * @param string $menuclass
128	 * @param string $submenuclass
129	 */
130	public function addClass($menuclass, $submenuclass = '') {
131		$this->menuclass    = $menuclass;
132		$this->submenuclass = $submenuclass;
133	}
134
135	/**
136	 * Get the class.
137	 *
138	 * @return string
139	 */
140	public function getClass() {
141		return $this->class;
142	}
143
144	/**
145	 * Set the class.
146	 *
147	 * @param string $class
148	 *
149	 * @return $this
150	 */
151	public function setClass($class) {
152		$this->class = $class;
153
154		return $this;
155	}
156
157	/**
158	 * Get the label.
159	 *
160	 * @return string
161	 */
162	public function getLabel() {
163		return $this->label;
164	}
165
166	/**
167	 * Set the label.
168	 *
169	 * @param string $label
170	 *
171	 * @return $this
172	 */
173	public function setLabel($label) {
174		$this->label = $label;
175
176		return $this;
177	}
178
179	/**
180	 * Get the link.
181	 *
182	 * @return string
183	 */
184	public function getLink() {
185		return $this->link;
186	}
187
188	/**
189	 * Set the link.
190	 *
191	 * @param string $link
192	 *
193	 * @return $this
194	 */
195	public function setLink($link) {
196		$this->link = $link;
197
198		return $this;
199	}
200
201	/**
202	 * Add a submenu to this menu
203	 *
204	 * @param Menu $menu
205	 *
206	 * @return $this
207	 */
208	public function addSubmenu($menu) {
209		$this->submenus[] = $menu;
210
211		return $this;
212	}
213
214	/**
215	 * Render this menu as an HTML list
216	 *
217	 * @return string
218	 */
219	public function getMenuAsList() {
220		$attrs = '';
221		foreach ($this->attrs as $key => $value) {
222			$attrs .= ' ' . $key . '="' . Html::escape($value) . '"';
223		}
224		if ($this->link) {
225			$link = ' href="' . $this->link . '"';
226		} else {
227			$link = '';
228		}
229		$html = '<a' . $link . $attrs . '>' . $this->label . '</a>';
230		if ($this->submenus) {
231			$html .= '<ul>';
232			foreach ($this->submenus as $submenu) {
233				$html .= $submenu->getMenuAsList();
234			}
235			$html .= '</ul>';
236		}
237
238		return '<li class="' . $this->class . '">' . $html . '</li>';
239	}
240
241	/**
242	 * Get the sub-menus.
243	 *
244	 * @return Menu[]
245	 */
246	public function getSubmenus() {
247		return $this->submenus;
248	}
249
250	/**
251	 * Set the sub-menus.
252	 *
253	 * @param Menu[] $submenus
254	 *
255	 * @return $this
256	 */
257	public function setSubmenus(array $submenus) {
258		$this->submenus = $submenus;
259
260		return $this;
261	}
262}
263