Test Failed
Pull Request — master (#236)
by
unknown
04:56
created

Menu::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 3
rs 10
1
<?php
2
3
/**
4
 * Copyright (c) 2018 Justin Kuenzel (jukusoft.com)
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
20
/**
21
 * Project: RocketCMS
22
 * License: Apache 2.0 license
23
 * User: Justin
24
 * Date: 10.03.2018
25
 * Time: 20:52
26
 */
27
28
class Menu {
29
30
	//menu ID (table menu_names)
31
	protected $menuID = -1;
32
33
	//name of template
34
	protected $template = "";
35
36
	//menu structure
37
	protected static $menuID_array = array();
38
39
	protected $menus = array();
40
41
	public function __construct (int $menuID = -1, string $template = "menu") {
42
		$this->menuID = (int) $menuID;
43
		$this->template = $template;
44
	}
45
46
	public function loadMenu (int $menuID = -1, Folder $folder) {
47
		if ($menuID == -1) {
48
			$menuID = $this->menuID;
49
		}
50
51
		if ($menuID == -1) {
52
			//we dont need to load anything, because no menu is selected
53
			$this->menus = array();
54
		}
55
56
		Events::throwEvent("before_load_menu", array(
57
			'menuID' => &$menuID,
58
			'instance' => &$this
59
		));
60
61
		//load menuID if absent
62
		self::loadMenuID($menuID);
63
64
		if (Cache::contains("menus", "menu_" . $menuID . "_" . User::current()->getID())) {
65
			$this->menus = Cache::get("menus", "menu_" . $menuID . "_" . User::current()->getID());
66
		} else {
67
			$menu_cache = self::$menuID_array[$menuID];
68
69
			//get menu by parent -y, this means root menu
70
			$this->menus = $this->getMenuByParent($menu_cache, -1, $folder);
71
72
			Events::throwEvent("after_load_menu", array(
73
				'menuID' => &$menuID,
74
				'instance' => &$this,
75
				'menus' => &$this->menus,
76
				'menu_cache' => $menu_cache
77
			));
78
79
			Cache::put("menus", "menu_" . $menuID . "_" . User::current()->getID(), $this->menus);
80
		}
81
82
		$this->menuID = $menuID;
83
	}
84
85
	protected function getMenuByParent (array &$menu_array, int $parentID, Folder $folder) : array {
86
		if (!isset($menu_array[$parentID])) {
87
			//menu doesnt have submenus
88
			return array();
89
		}
90
91
		$array = array();
92
93
		foreach ($menu_array[$parentID] as $row) {
94
			//check login_required
95
			if ($row['login_required'] == 1 && !User::current()->isLoggedIn()) {
96
				//dont show this menu
97
				continue;
98
			}
99
100
			//check permissions
101
			$permissions = explode("|", $row['permissions']);
102
			$has_permission = false;
103
104
			foreach ($permissions as $permission) {
105
				if (PermissionChecker::current()->hasRight($permission)) {
106
					$has_permission = true;
107
					break;
108
				}
109
			}
110
111
			if (!$has_permission) {
112
				//dont show this menu, because user doesnt have permission for this menu
113
				continue;
114
			}
115
116
			$entry = array();
117
118
			//translate title
119
			if ($folder->isTitleTranslationEnabled()) {
120
				$row['title'] = Translator::translateTitle($row['title']);
121
			}
122
123
			$href = "";
124
			$entry['append'] = "";
125
			$entry['title'] = $row['title'];
126
			$entry['text'] = $row['title'];
127
			$entry['icon'] = $row['icon'];
128
			$entry['icon_class'] = " " . $row['icon'];
129
			$entry['permissions'] = explode("|", $row['permissions']);
130
			$entry['append'] = "";
131
			$entry['extension_code'] = "";
132
133
			if (strpos($row['url'], "LOGIN_URL") !== FALSE) {
134
				$row['url'] = Registry::singleton()->getSetting("login_url");
135
			}
136
137
			if (strpos($row['url'], "LOGOUT_URL") !== FALSE) {
138
				$row['url'] = Registry::singleton()->getSetting("logout_url");
139
			}
140
141
			if ($row['type'] == "page") {
142
				$href = DomainUtils::generateURL($row['url']);
143
			} else if ($row['type'] == "link") {
144
				//TODO: add base url
145
				$href = $row['url'];
146
			} else if ($row['type'] == "external_link") {
147
				$href = $row['url'];
148
			} else if ($row['type'] == "js_link") {
149
				$href = "#";
150
				$entry['append'] = " onclick=\"" . $row['url'] . "\"";
151
			} else if ($row['type'] == "no_link") {
152
				$href = "#";
153
			} else if ($row['type'] == "dynamic_link") {
154
				$href = "#";
155
156
				if (PHPUtils::startsWith($row['url'], "settings:")) {
157
					$array1 = explode(":", $row['url']);
158
					$href = Settings::get($array1[1], "#");
159
				} else if (PHPUtils::startsWith($row['url'], "registry:")) {
160
					$array1 = explode(":", $row['url']);
161
					$href = Registry::singleton()->getSetting($array1[1], "#");
162
				}
163
			} else {
164
				throw new IllegalStateException("Unknown menu type: " . $row['type']);
165
			}
166
167
			$entry['href'] = $href;
168
169
			if (!empty($row['icon']) && $row['icon'] != "none") {
170
				$entry['text'] = "<img src=\"" . $row['icon'] . "\" alt=\"" . $row['title'] . "\" title=\"" . $row['title'] . "\" style=\"max-width:32px; max-height:32px; \" /> " . $row['title'];
171
			}
172
173
			//get submenus
174
			$entry['submenus'] = $this->getMenuByParent($menu_array, $row['id'], $folder);
175
			$entry['has_submenus'] = sizeof($entry['submenus']) > 0;
176
177
			$array[] = $entry;
178
		}
179
180
		return $array;
181
	}
182
183
	/**
184
	 * get HTML code of menu
185
	 */
186
	public function getCode () : string {
187
		$template = new DwooTemplate($this->template);
188
189
		$template->assign("menu_array", $this->menus);
190
191
		/*$template = new Template($this->template);
192
193
		$this->parseMenu($this->menus, $template);
194
195
		//parse main block
196
		$template->parse("main");*/
197
198
		$html = $template->getCode();
199
200
		Events::throwEvent("get_menu_code", array(
201
			'menuID' => $this->menuID,
202
			'menus' => &$this->menus,
203
			'html' => &$html
204
		));
205
206
		return $html;
207
	}
208
209
	protected static function loadMenuID (int $menuID) {
210
		if (isset(self::$menuID_array[$menuID])) {
211
			return;
212
		}
213
214
		if (Cache::contains("menus", "menuID_" . $menuID)) {
215
			self::$menuID_array[$menuID] = Cache::get("menus", "menuID_" . $menuID);
216
		} else {
217
			$rows = Database::getInstance()->listRows("SELECT * FROM `{praefix}menu` WHERE `menuID` = :menuID AND `activated` = '1' ORDER BY `order`; ", array('menuID' => array(
218
				'type' => PDO::PARAM_INT,
219
				'value' => $menuID
220
			)));
221
222
			$array = array();
223
224
			foreach ($rows as $row) {
225
				$parentID = $row['parent'];
226
227
				if (!isset($array[$parentID])) {
228
					$array[$parentID] = array();
229
				}
230
231
				$array[$parentID][] = $row;
232
			}
233
234
			self::$menuID_array[$menuID] = $array;
235
236
			Cache::put("menus", "menuID_" . $menuID, $array);
237
		}
238
239
		//var_dump(self::$menuID_array);
240
	}
241
242
	public static function createMenuName (string $title, string $unique_name = null) : int {
243
		Events::throwEvent("before_create_menu_name", array(
244
			'title' => &$title
245
		));
246
247
		if ($unique_name == null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $unique_name of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
248
			$unique_name = md5(PHPUtils::randomString(100));
249
		}
250
251
		$unique_name = Validator_String::get($unique_name);
252
253
		Database::getInstance()->execute("INSERT INTO `{praefix}menu_names` (
254
			`menuID`, `title`, `unique_name`, `activated`
255
		) VALUES (
256
			NULL, :title, :name, '1'
257
		) ON DUPLICATE KEY UPDATE `title` = :title, `activated` = '1'; ", array(
258
			'title' => $title,
259
			'name' => $unique_name
260
		));
261
262
		Cache::clear("menus");
263
264
		//get menuID of inserted menu name
265
		$menuID = Database::getInstance()->lastInsertId();
266
267
		Events::throwEvent("after_created_menu_name", array(
268
			'menuID' => $menuID,
269
			'title' => &$title
270
		));
271
272
		return $menuID;
273
	}
274
275
	public static function deleteMenuName (int $menuID) {
276
		Database::getInstance()->execute("DELETE FROM `{praefix}menu_names` WHERE `menuID` = :menuID; ", array(
277
			'menuID' => array(
278
				'type' => PDO::PARAM_INT,
279
				'value' => $menuID
280
			)
281
		));
282
283
		//clear cache
284
		Cache::clear("menus", "menuID_" . $menuID);
285
	}
286
287
	public static function listMenuNames () : array {
288
		if (Cache::contains("menus", "menu_names")) {
289
			return Cache::get("menus", "menu_names");
290
		} else {
291
			$rows = Database::getInstance()->listRows("SELECT * FROM `{praefix}menu_names` WHERE `activated` = 1; ");
292
293
			Cache::put("menus", "menu_names", $rows);
294
295
			return $rows;
296
		}
297
	}
298
299
	public static function createMenu (int $id, int $menuID, string $title, string $url, int $parent = -1, string $unique_name = "", $type = "page", $permissions = array("all"), $login_required = false, string $icon = "none", int $order = 100, string $owner = "user") {
300
		if (!is_array($permissions)) {
301
			$permissions = array($permissions);
302
		}
303
304
		//validate values
305
		$id = Validator_Int::get($id);
306
		$menuID = Validator_Int::get($menuID);
307
		$title = Validator_String::get($title);
308
		$parent = Validator_Int::get($parent);
309
		$type = Validator_String::get($type);
310
		$login_required = (bool) $login_required;
311
312
		$permissions = implode("|", $permissions);
313
314
		if (is_null($unique_name) || empty($unique_name)) {
315
			$unique_name = md5(PHPUtils::randomString(100) . time());
316
		}
317
318
		if ($id != null && $id != -1) {
319
			$insertID = Database::getInstance()->execute("INSERT INTO `{praefix}menu` (
320
				`id`, `menuID`, `title`, `url`, `type`, `icon`, `permissions`, `login_required`, `parent`, `unique_name`, `extensions`, `order`, `owner`, `activated`
321
			) VALUES (
322
				:id, :menuID, :title, :url, :url_type, :icon, :permissions, :login_required, :parent, :unique_name, :extensions, :menu_order, :owner, '1'
323
			) ON DUPLICATE KEY UPDATE `menuID` = :menuID, `title` = :title, `url` = :url, `type` = :url_type, `permissions` = :permissions, `login_required` = :login_required, `parent` = :parent, `unique_name` = :unique_name, `extensions` = :extensions, `order` = :menu_order, `owner` = :owner, `icon` = :icon, `activated` = '1'; ", array(
324
				'id' => $id,
325
				'menuID' => $menuID,
326
				'title' => $title,
327
				'url' => $url,
328
				'url_type' => $type,
329
				'icon' => $icon,
330
				'permissions' => $permissions,
331
				'login_required' => ($login_required ? 1 : 0),
332
				'parent' => $parent,
333
				'unique_name' => $unique_name,
334
				'extensions' => "none",
335
				'menu_order' => $order,
336
				'owner' => $owner
337
			));
338
		} else {
339
			$insertID = Database::getInstance()->execute("INSERT INTO `{praefix}menu` (
340
				`id`, `menuID`, `title`, `url`, `type`, `icon`, `permissions`, `login_required`, `parent`, `unique_name`, `extensions`, `order`, `owner`, `activated`
341
			) VALUES (
342
				NULL, :menuID, :title, :url, :url_type, :icon, :permissions, :login_required, :parent, :unique_name, :extensions, :menu_order, :owner, '1'
343
			) ON DUPLICATE KEY UPDATE `menuID` = :menuID, `title` = :title, `url` = :url, `type` = :url_type, `permissions` = :permissions, `login_required` = :login_required, `parent` = :parent, `unique_name` = :unique_name, `extensions` = :extensions, `order` = :menu_order, `owner` = :owner, `icon` = :icon, `activated` = '1'; ", array(
344
				'menuID' => $menuID,
345
				'title' => $title,
346
				'url' => $url,
347
				'url_type' => $type,
348
				'icon' => $icon,
349
				'permissions' => $permissions,
350
				'login_required' => ($login_required ? 1 : 0),
351
				'parent' => $parent,
352
				'unique_name' => $unique_name,
353
				'extensions' => "none",
354
				'menu_order' => $order,
355
				'owner' => $owner
356
			));
357
		}
358
359
		//clear cache
360
		Cache::clear("menus", "menuID_" . $menuID);
361
362
		return $insertID;
363
	}
364
365
	public static function deleteMenusByOwner (string $owner) {
366
		//delete menus from database
367
		Database::getInstance()->execute("DELETE FROM `{praefix}menu` WHERE `owner` = :owner; ", array('owner' => $owner));
368
369
		//clear cache
370
		Cache::clear("menus");
371
	}
372
373
}
374
375
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
376