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