1<?php
2	/* libraries/menu.php
3	 *
4	 * Copyright (C) by Hugo Leisink <hugo@leisink.net>
5	 * This file is part of the Banshee PHP framework
6	 * http://www.banshee-php.org/
7	 */
8
9	class menu {
10		private $db = null;
11		private $output = null;
12		private $parent_id = 0;
13		private $depth = 1;
14		private $user = null;
15
16		/* Constructor
17		 *
18		 * INPUT:  object database, object output
19		 * OUTPUT: -
20		 * ERROR:  -
21		 */
22		public function __construct($db, $output) {
23			$this->db = $db;
24			$this->output = $output;
25		}
26
27		/* Set menu start point
28		 *
29		 * INPUT:  string link
30		 * OUTPUT: true
31		 * ERROR:  false
32		 */
33		public function set_start_point($link) {
34			$query = "select id from menu where link=%s limit 1";
35			if (($menu = $this->db->execute($query, $link)) == false) {
36				return false;
37			}
38
39			$this->parent_id = (int)$menu[0]["id"];
40
41			return true;
42		}
43
44		/* Set menu depth
45		 *
46		 * INPUT:  int depth
47		 * OUTPUT: -
48		 * ERROR:  -
49		 */
50		public function set_depth($depth) {
51			if (($this->depth = (int)$depth) < 1) {
52				$this->depth = 1;
53			}
54		}
55
56		/* Set user for access check
57		 *
58		 * INPUT:  object user
59		 * OUTPUT: -
60		 * ERROR:  -
61		 */
62		public function set_user($user) {
63			$this->user = $user;
64		}
65
66		/* Get menu data
67		 *
68		 * INPUT:  int menu identifier[, int menu depth][, string link of active menu item for highlighting]
69		 * OUTPUT: array menu data
70		 * ERROR:  false
71		 */
72		private function get_menu($id, $depth = 1, $current_url = null) {
73			$query = "select * from menu where parent_id=%d order by %S";
74			if (($menu = $this->db->execute($query, $id, "id")) === false) {
75				return false;
76			}
77
78			$result = array(
79				"id"    => $id,
80				"items" => array());
81
82			foreach ($menu as $item) {
83				$element = array();
84
85				if (($this->user !== null) && ($item["link"][0] == "/")) {
86					if (($module = ltrim($item["link"], "/")) != "") {
87						if ($this->user->access_allowed($module) == false) {
88							continue;
89						}
90					}
91				}
92
93				$element["id"] = $item["id"];
94				if ($current_url !== null) {
95					$element["current"] = show_boolean($item["link"] == $current_url);
96				}
97				$element["text"] = $item["text"];
98				$element["link"] = $item["link"];
99				if ($depth > 1) {
100					$element["submenu"] = $this->get_menu($item["id"], $depth - 1, $current_url);
101				}
102
103				array_push($result["items"], $element);
104			}
105
106			return $result;
107		}
108
109		/* Print menu to output
110		 *
111		 * INPUT:  array menu data
112		 * OUTPUT: -
113		 * ERROR:  -
114		 */
115		private function show_menu($menu) {
116			if (count($menu) == 0) {
117				return;
118			}
119
120			$this->output->open_tag("menu", array("id" => $menu["id"]));
121			foreach ($menu["items"] as $item) {
122				$args = array("id" => $item["id"]);
123				if (isset($item["current"])) {
124					$args["current"] = $item["current"];
125				}
126
127				$this->output->open_tag("item", $args);
128				$this->output->add_tag("link", $item["link"]);
129				$this->output->add_tag("text", $item["text"]);
130				if (isset($item["submenu"])) {
131					$this->show_menu($item["submenu"]);
132				}
133				$this->output->close_tag();
134			}
135			$this->output->close_tag();
136		}
137
138		/* Appent menu to XML output
139		 *
140		 * INPUT:  [string link of active menu item for highlighting]
141		 * OUTPUT: true
142		 * ERROR:  false
143		 */
144		public function to_output($current_url = null) {
145			/* Handle menu updates
146			 */
147			$cache = new cache($this->db, "menu");
148			if ($cache->last_updated === null) {
149				$cache->store("last_updated", time(), 365 * DAY);
150			}
151			if (isset($_SESSION["menu_last_updated"]) == false) {
152				$_SESSION["menu_last_updated"] = $cache->last_updated;
153			} else if ($cache->last_updated > $_SESSION["menu_last_updated"]) {
154				$_SESSION["menu_cache"] = array();
155				$_SESSION["menu_last_updated"] = $cache->last_updated;
156			}
157			unset($cache);
158
159			/* Build menu
160			 */
161			if (isset($_SESSION["menu_cache"]) == false) {
162				$_SESSION["menu_cache"] = array();
163			}
164			$cache = &$_SESSION["menu_cache"];
165
166			$username = ($this->user !== null) ? $this->user->username : "";
167			$index = sha1(sprintf("%d-%d-%s-%s", $this->parent_id, $this->depth, $username, $current_url));
168
169			if (isset($cache[$index]) == false) {
170				if (($menu = $this->get_menu($this->parent_id, $this->depth, $current_url)) === false) {
171					return false;
172				}
173				$cache[$index] = json_encode($menu);
174			} else {
175				$menu = json_decode($cache[$index], true);
176			}
177
178			$this->show_menu($menu);
179
180			return true;
181		}
182	}
183?>
184