Merge pull request #5989 from WoltLab/wsc-rpc-api-const
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / system / menu / TreeMenu.class.php
CommitLineData
158bd3ca 1<?php
a9229942 2
158bd3ca 3namespace wcf\system\menu;
a9229942 4
158bd3ca
TD
5use wcf\system\event\EventHandler;
6use wcf\system\SingletonFactory;
7use wcf\system\WCF;
158bd3ca
TD
8
9/**
10 * Basis class for a tree menu.
a9229942
TD
11 *
12 * @author Marcel Werk
13 * @copyright 2001-2019 WoltLab GmbH
14 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
158bd3ca 15 */
a9229942
TD
16abstract class TreeMenu extends SingletonFactory
17{
18 /**
19 * list of visible menu items
20 * @var ITreeMenuItem[]
21 */
22 public $menuItemList = [];
23
24 /**
25 * list of the names of the active menu items
26 * @var string[]
27 */
28 public $activeMenuItems = [];
29
30 /**
31 * list of all menu items
32 * @var ITreeMenuItem[][]
33 */
34 public $menuItems;
35
36 /**
37 * @inheritDoc
38 */
39 protected function init()
40 {
41 // get menu items from cache
42 $this->loadCache();
43
44 // check menu items
45 $this->checkMenuItems();
46
47 // remove items without children
48 $this->removeEmptyItems();
49
50 // build plain menu item list
51 $this->buildMenuItemList();
52
53 // call init event
54 EventHandler::getInstance()->fireAction($this, 'init');
55 }
56
57 /**
58 * Loads cached menu items.
59 */
60 protected function loadCache()
61 {
62 // call loadCache event
63 EventHandler::getInstance()->fireAction($this, 'loadCache');
64
65 $this->menuItems = [];
66 }
67
68 /**
69 * Checks the options and permissions of given menu item.
70 *
71 * @param ITreeMenuItem $item
72 * @return bool
73 */
74 protected function checkMenuItem(ITreeMenuItem $item)
75 {
76 // check the options of this item
77 $hasEnabledOption = true;
78 if (!empty($item->options)) {
79 $hasEnabledOption = false;
80 $options = \explode(',', \strtoupper($item->options));
81 foreach ($options as $option) {
82 if (\defined($option) && \constant($option)) {
83 $hasEnabledOption = true;
84 break;
85 }
86 }
87 }
88 if (!$hasEnabledOption) {
89 return false;
90 }
91
92 // check the permission of this item for the active user
93 $hasPermission = true;
94 if (!empty($item->permissions)) {
95 $hasPermission = false;
96 $permissions = \explode(',', $item->permissions);
97 foreach ($permissions as $permission) {
98 if (WCF::getSession()->getPermission($permission)) {
99 $hasPermission = true;
100 break;
101 }
102 }
103 }
104 if (!$hasPermission) {
105 return false;
106 }
107
108 return true;
109 }
110
111 /**
112 * Checks the options and permissions of the menu items.
113 *
114 * @param string $parentMenuItem
115 */
116 protected function checkMenuItems($parentMenuItem = '')
117 {
118 if (!isset($this->menuItems[$parentMenuItem])) {
119 return;
120 }
121
122 foreach ($this->menuItems[$parentMenuItem] as $key => $item) {
123 if ($this->checkMenuItem($item)) {
124 // check children
125 $this->checkMenuItems($item->menuItem);
126 } else {
127 // remove this item
128 unset($this->menuItems[$parentMenuItem][$key]);
129 }
130 }
131 }
132
133 /**
134 * Removes items without children.
135 *
136 * @param string $parentMenuItem
137 */
138 protected function removeEmptyItems($parentMenuItem = '')
139 {
140 if (!isset($this->menuItems[$parentMenuItem])) {
141 return;
142 }
143
144 foreach ($this->menuItems[$parentMenuItem] as $key => $item) {
145 $this->removeEmptyItems($item->menuItem);
146 if (
147 empty($item->menuItemLink)
148 && empty($item->menuItemController)
149 && (!isset($this->menuItems[$item->menuItem]) || empty($this->menuItems[$item->menuItem]))
150 ) {
151 // remove this item
152 unset($this->menuItems[$parentMenuItem][$key]);
153 }
154 }
155 }
156
157 /**
158 * Builds a plain menu item list.
159 *
160 * @param string $parentMenuItem
161 */
162 protected function buildMenuItemList($parentMenuItem = '')
163 {
164 if (!isset($this->menuItems[$parentMenuItem])) {
165 return;
166 }
167
168 foreach ($this->menuItems[$parentMenuItem] as $item) {
169 $this->menuItemList[$item->menuItem] = $item;
170 $this->buildMenuItemList($item->menuItem);
171 }
172 }
173
174 /**
175 * Sets the active menu item.
176 * This should be done before the menu.tpl template calls the function getMenu().
177 *
178 * This function should be used in each script which uses a template that includes the menu.tpl.
179 *
180 * @param string $menuItem name of the active menu item
181 */
182 public function setActiveMenuItem($menuItem)
183 {
184 $newActiveMenuItems = [];
185 while (isset($this->menuItemList[$menuItem])) {
186 $newActiveMenuItems[] = $menuItem;
187 $menuItem = $this->menuItemList[$menuItem]->parentMenuItem;
188
189 if ($menuItem && !isset($this->menuItemList[$menuItem])) {
190 return;
191 }
192 }
193
194 if (!empty($newActiveMenuItems)) {
195 $this->activeMenuItems = $newActiveMenuItems;
196 }
197 }
198
199 /**
200 * Returns a list of the active menu items.
201 *
202 * @return array
203 */
204 public function getActiveMenuItems()
205 {
206 return $this->activeMenuItems;
207 }
208
209 /**
210 * Returns the active menu item.
211 *
212 * @param int $level
5227ebc7 213 * @return string|null
a9229942
TD
214 */
215 public function getActiveMenuItem($level = 0)
216 {
217 if ($level < \count($this->activeMenuItems)) {
218 return $this->activeMenuItems[\count($this->activeMenuItems) - ($level + 1)];
219 }
5227ebc7
MS
220
221 return null;
a9229942
TD
222 }
223
224 /**
225 * Returns the list of menu items.
226 *
227 * @param string $parentMenuItem
228 * @return array
229 */
230 public function getMenuItems($parentMenuItem = null)
231 {
232 if ($parentMenuItem === null) {
233 return $this->menuItems;
234 }
235 if (isset($this->menuItems[$parentMenuItem])) {
236 return $this->menuItems[$parentMenuItem];
237 }
238
239 return [];
240 }
dcb3a44c 241}