770328885ea1b5a4f250ddba99286117b5087553
[diogenes.git] / include / Barrel / Menu.php
1 <?php
2 /*
3 * Copyright (C) 2003-2005 Polytechnique.org
4 * http://opensource.polytechnique.org/
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21
22 /** This class is used to generate the menu of a Diogenes barrel page.
23 */
24 class Diogenes_Barrel_Menu
25 {
26 /** Database handle */
27 var $dbh;
28
29 /** The database table holding the menus */
30 var $table_menu;
31
32 /** Constructs a Smarty-derived object to display contents within a barrel.
33 *
34 * @param $override_pathinfo
35 */
36 function Diogenes_Barrel_Menu(&$dbh, $table_menu)
37 {
38 $this->dbh =& $dbh;
39 $this->table_menu = $table_menu;
40 }
41
42 /** Delete the specified entry.
43 *
44 * @param $MID
45 * @param $parent
46 * @param $caller
47 */
48 function deleteEntry($MID, $parent, &$caller)
49 {
50 if (mysql_num_rows($this->dbh->query("SELECT MID FROM {$this->table_menu} WHERE MIDpere=$MID")) > 0) {
51 $caller->info(__("The selected menu has child items, please remove them first."));
52 return;
53 }
54
55 /* erase the current entry */
56 $this->dbh->query("DELETE FROM {$this->table_menu} WHERE MID=$MID");
57
58 /* renumber the other menu entries so that they are between 1 and the number of entries */
59 $res = $this->dbh->query("SELECT MID FROM {$this->table_menu} WHERE MIDpere=$parent ORDER BY ordre");
60 $i = 0;
61 while (list($MIDtoorder) = mysql_fetch_row($res)) {
62 $i++;
63 $this->dbh->query("UPDATE {$this->table_menu} SET ordre=$i WHERE MID=$MIDtoorder");
64 }
65 mysql_free_result($res);
66 }
67
68
69 /** Build the user-defined part of the menu.
70 *
71 * @param $PID
72 * @param $pid_to_url
73 */
74 function makeMenu($PID, $min_level, $pid_to_url)
75 {
76 // all menu entries from database
77 $mcache = $this->menuRead();
78
79 // try to figure out the current MID from the current PID
80 // and build filiation
81 $filiation = array();
82 foreach ($mcache as $mid => $mentry)
83 {
84 if ($mentry['pid'] == $PID)
85 $filiation = $this->menuToRoot($mcache, $mid, $filiation);
86 }
87
88 $menu = $this->menuRecurse($mcache, 0, $filiation, 0, $min_level, $pid_to_url);
89
90 return $menu;
91 }
92
93
94 /** Return the maximum index for children of a given entry.
95 *
96 * @param $parent
97 */
98 function maxChildIndex($parent)
99 {
100 $res=$this->dbh->query("SELECT MAX(ordre) from {$this->table_menu} where MIDpere=$parent");
101 list($maxOrdre)=mysql_fetch_row($res);
102 mysql_free_result($res);
103 return $maxOrdre;
104 }
105
106
107 /** Return the filiation to get to the root element.
108 *
109 * @param mcache
110 * @param MID
111 * @param path
112 */
113 function menuToRoot($mcache, $MID, $path) {
114 /* add ourself to the path */
115 array_push($path,$MID);
116
117 if ($MID) {
118 /* recursion */
119 return $this->menuToRoot($mcache, $mcache[$MID]['parent'], $path);
120 } else {
121 /* termination */
122 return $path;
123 }
124 }
125
126
127 /** Recursively add menu entries
128 *
129 * @param mcache
130 * @param MIDpere
131 * @param filiation
132 * @param level
133 * @param min_level
134 * @param pid_to_url
135 */
136 function menuRecurse($mcache, $MIDpere, $filiation, $level, $min_level, $pid_to_url) {
137 // the produced output
138 $out = array();
139
140 foreach ($mcache[$MIDpere]['children'] as $mid)
141 {
142 $mentry = $mcache[$mid];
143 // echo "pid : $pid, location : $location<br/>";
144 $entry = htmlentities(stripslashes($mentry['title']), ENT_QUOTES);
145 if ($mentry['pid'])
146 {
147 $link = call_user_func($pid_to_url, $mentry['pid']);
148 } else {
149 $link = $mentry['link'];
150 }
151 // decide whether this menu should be expanded
152 $expanded = ($min_level == 0) ||
153 ($level+1 < $min_level) ||
154 in_array($mid, $filiation);
155 array_push($out, array($level, $entry, $link, $expanded));
156 $out = array_merge($out, $this->menuRecurse($mcache, $mid, $filiation, $level+1, $min_level, $pid_to_url));
157 }
158
159 return $out;
160 }
161
162
163 /** Read this barrel's menu entries from database.
164 */
165 function menuRead()
166 {
167 $menu = array();
168 $menu[0]['children'] = array();
169 $res = $this->dbh->query("select MID,MIDpere,title,link,PID,ordre from {$this->table_menu} order by ordre");
170 while (list($mid, $parent, $title, $link, $pid, $ordre) = mysql_fetch_row($res))
171 {
172 $menu[$mid]['parent'] = $parent;
173 $menu[$mid]['title'] = $title;
174 $menu[$mid]['link'] = $link;
175 $menu[$mid]['title'] = $title;
176 $menu[$mid]['pid'] = $pid;
177 $menu[$mid]['ordre'] = $ordre;
178 if (!is_array($menu[$mid]['children']))
179 $menu[$mid]['children'] = array();
180
181 // register this entry with its parent
182 if (!is_array($menu[$parent]['children']))
183 $menu[$parent]['children'] = array();
184 array_push($menu[$parent]['children'], $mid);
185 }
186 mysql_free_result($res);
187 return $menu;
188 }
189
190
191 /**
192 * Swap entries $a and $b within $parent.
193 *
194 * @param $parent
195 * @param $a
196 * @param $b
197 */
198 function swapEntries($parent, $a, $b)
199 {
200 $res = $this->dbh->query("SELECT MID from {$this->table_menu} where MIDpere=$parent and (ordre=$a or ordre=$b) ORDER BY ordre");
201 /* make sure that $a <= $b */
202 if ($a > $b)
203 {
204 $c = $a;
205 $a = $b;
206 $b = $c;
207 }
208 /* perform swap */
209 list($MIDa) = mysql_fetch_row($res);
210 list($MIDb) = mysql_fetch_row($res);
211 mysql_free_result($res);
212
213 $this->dbh->query("UPDATE {$this->table_menu} SET ordre=$b WHERE MID=$MIDa");
214 $this->dbh->query("UPDATE {$this->table_menu} SET ordre=$a WHERE MID=$MIDb");
215 }
216
217
218 /**
219 * Write an entry to database. If $mid is 0, a new entry is created.
220 *
221 * @param $mid
222 * @param $props
223 */
224 function writeEntry($mid, $props)
225 {
226 if ($mid == 0) {
227 $props['ordre'] = $this->maxChildIndex($props['parent']) + 1;
228 }
229
230 // build SQL string
231 $nprops = array('parent' => 'MIDpere', 'ordre' => 'ordre', 'title' => 'title', 'link' => 'link', 'pid' => 'pid');
232 $sprops = "";
233 foreach($nprops as $prop => $dbkey)
234 {
235 if (isset($props[$prop]))
236 {
237 $val = $props[$prop];
238 $sprops .= "$dbkey='$val', ";
239 }
240 }
241 if (!$sprops)
242 return;
243 $sprops = substr($sprops, 0, -2);
244 if ($mid == 0) {
245 $this->dbh->query("INSERT INTO {$this->table_menu} SET $sprops");
246 $mid = mysql_insert_id();
247 } else {
248 $this->dbh->query("UPDATE {$this->table_menu} SET $sprops WHERE MID=$mid");
249 }
250 return $mid;
251 }
252
253 }
254
255 ?>