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