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