Commit | Line | Data |
---|---|---|
6855525e JL |
1 | <?php |
2 | /* | |
3 | * Copyright (C) 2003-2004 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 | require_once 'Barrel/Page.php'; | |
22 | require_once 'Barrel/Options.php'; | |
23 | require_once 'diogenes/diogenes.flagset.inc.php'; | |
7aff44b2 | 24 | require_once 'Plugin/Skel.php'; |
6855525e JL |
25 | |
26 | ||
27 | /** This class describes a Diogenes Barrel. | |
28 | */ | |
29 | class Diogenes_Barrel | |
30 | { | |
31 | /** The barrel's alias. */ | |
32 | var $alias; | |
33 | ||
34 | /** The database table holding the menus */ | |
35 | var $table_menu; | |
36 | ||
37 | /** The database table holding the pages */ | |
38 | var $table_page; | |
39 | ||
40 | /** The site's flags. */ | |
41 | var $flags; | |
42 | ||
43 | /** The site's options. */ | |
44 | var $options; | |
45 | ||
46 | /** Cache of the homepage ID */ | |
47 | var $homepage; | |
48 | ||
49 | /** Handle to the spool */ | |
50 | var $spool; | |
51 | ||
52 | /** If the barrel is running on a virtualhost. */ | |
53 | var $vhost; | |
54 | ||
55 | /** Cache of tree */ | |
56 | var $treeCache; | |
57 | ||
58 | /** File containing the tree cache. */ | |
59 | var $treeCacheFile; | |
60 | ||
61 | /** Cache of the plugins */ | |
62 | var $pluginsCache; | |
63 | ||
64 | /** File containing the plugin cache. */ | |
65 | var $pluginsCacheFile; | |
66 | ||
67 | ||
68 | /** Construct a Diogenes Barrel. | |
69 | * | |
70 | * @param $alias | |
71 | */ | |
72 | function Diogenes_Barrel($alias) | |
73 | { | |
74 | global $globals; | |
75 | $webdav = ''; | |
76 | ||
77 | // Retrieve site-wide info from database | |
78 | $res = $globals->db->query("select alias,vhost,flags from diogenes_site where alias='$alias'"); | |
79 | if (!list($this->alias,$this->vhost,$flags) = mysql_fetch_row($res)) { | |
80 | return; | |
81 | } | |
82 | mysql_free_result($res); | |
83 | ||
84 | $this->table_menu = "{$this->alias}_menu"; | |
85 | $this->table_page = "{$this->alias}_page"; | |
86 | $this->treeCacheFile = $globals->spoolroot."/diogenes_c/". $this->alias.".tree"; | |
87 | $this->pluginsCacheFile = $globals->plugins->cacheFile($this->alias); | |
88 | ||
89 | $this->flags = new flagset($flags); | |
90 | $this->options = new Diogenes_Barrel_Options($this->alias); | |
91 | $this->spool = new DiogenesSpool($this,$this->alias); | |
92 | ||
93 | $this->readTree(); | |
94 | } | |
95 | ||
96 | ||
97 | /** Create a new Diogenes barrel. This creates the database, RCS and | |
98 | * spool entries for the new barrel. | |
99 | * | |
100 | * @param $alias | |
101 | * @param $caller | |
102 | */ | |
103 | function create($alias, &$caller) | |
104 | { | |
105 | global $globals; | |
106 | ||
107 | /* sanity check */ | |
108 | if (!preg_match("/^[a-zA-Z0-9_]+$/",$alias) or | |
109 | in_array($alias, $globals->invalidaliases)) | |
110 | { | |
111 | $caller->info("Invalid barrel name!"); | |
112 | return; | |
113 | } | |
114 | ||
115 | $res = $globals->db->query("select alias from diogenes_site where alias='$alias'"); | |
116 | if (mysql_num_rows($res) > 0) { | |
117 | $caller->info("Entry '{$alias}' already exists in table 'diogenes_site'!"); | |
118 | return; | |
119 | } | |
120 | ||
121 | if (file_exists("{$globals->rcsroot}/$alias")) { | |
122 | $caller->info("Directory '{$globals->rcsroot}/$alias' already exists!"); | |
123 | return; | |
124 | } | |
125 | ||
126 | if (!is_dir($globals->rcsroot) || !is_writable($globals->rcsroot)) { | |
127 | $caller->info("Directory '{$globals->rcsroot}' is not writable!"); | |
128 | return; | |
129 | } | |
130 | ||
131 | /* log this event */ | |
132 | $caller->log("barrel_create","$alias:*"); | |
133 | ||
134 | /* create DB entry */ | |
135 | $globals->db->query("insert into diogenes_site set alias='$alias'"); | |
136 | ||
137 | $globals->db->query("CREATE TABLE {$alias}_menu (" | |
138 | . "MID int(10) unsigned NOT NULL auto_increment," | |
139 | . "MIDpere int(10) unsigned NOT NULL," | |
140 | . "ordre int(10) unsigned NOT NULL," | |
141 | . "title tinytext NOT NULL," | |
142 | . "link text NOT NULL," | |
143 | . "PID int(10) unsigned NOT NULL," | |
144 | . "PRIMARY KEY (MID)" | |
145 | . ") TYPE=MyISAM;"); | |
146 | ||
147 | $globals->db->query("CREATE TABLE {$alias}_page (" | |
148 | . "PID int(10) unsigned NOT NULL auto_increment," | |
149 | . "parent INT( 10 ) UNSIGNED NOT NULL default '0'," | |
150 | . "location tinytext NOT NULL," | |
151 | . "title tinytext NOT NULL," | |
152 | . "status tinyint(1) unsigned NOT NULL default '0'," | |
153 | . "perms enum('public','auth','user','admin','forbidden') NOT NULL default 'public'," | |
154 | . "wperms enum('public','auth','user','admin','forbidden') NOT NULL default 'admin'," | |
155 | . "template varchar(255) NOT NULL," | |
156 | . "PRIMARY KEY (PID)" | |
157 | . ") TYPE=MyISAM;"); | |
158 | ||
159 | /* set the barrel's title */ | |
160 | $opt = new Diogenes_Barrel_Options($alias); | |
161 | $opt->updateOption('title',$alias); | |
162 | ||
163 | /* create entry for the homepage */ | |
164 | $globals->db->query("insert into {$alias}_page set location='temp'"); | |
165 | $homepage = mysql_insert_id(); | |
166 | $globals->db->query("update {$alias}_page set location='',title='Home',perms='public' where PID='$homepage'"); | |
167 | ||
168 | /* create home page & copy CSS template */ | |
169 | $rcs = new $globals->rcs($caller,$alias,$_SESSION['session']->username,true); | |
170 | $rcs->newdir("",$homepage); | |
171 | $rcs->commit($homepage,$globals->htmlfile,""); | |
172 | $rcs->commit($homepage,$globals->cssfile, | |
173 | file_get_contents("{$globals->root}/{$globals->cssfile}") ); | |
174 | } | |
175 | ||
176 | ||
177 | /** Destroy a Diogenes barrel. This removes the related database, RCS | |
178 | * and spool entries. | |
179 | * | |
180 | * @param $alias | |
181 | * @param $caller | |
182 | */ | |
183 | function destroy($alias, &$caller) { | |
184 | global $globals; | |
185 | ||
186 | /** Sanity check */ | |
187 | if (!$alias) { | |
188 | $caller->info("Empty alias supplied!"); | |
189 | return; | |
190 | } | |
191 | ||
192 | /* log this event */ | |
193 | $caller->log("barrel_delete","$alias:*"); | |
194 | ||
195 | system(escapeshellcmd("rm -rf ".escapeshellarg("{$globals->spoolroot}/$alias"))); | |
196 | system(escapeshellcmd("rm -rf ".escapeshellarg("{$globals->rcsroot}/$alias"))); | |
197 | system(escapeshellcmd("rm -f ".escapeshellarg("{$globals->spoolroot}/diogenes_c/$alias.tree"))); | |
198 | system(escapeshellcmd("rm -f ".escapeshellarg($globals->plugins->cacheFile($alias)))); | |
199 | $globals->db->query("drop table {$alias}_menu"); | |
200 | $globals->db->query("drop table {$alias}_page"); | |
201 | $globals->db->query("delete from diogenes_perm where alias='$alias'"); | |
202 | $globals->db->query("delete from diogenes_site where alias='$alias'"); | |
203 | $globals->db->query("delete from diogenes_option where barrel='$alias'"); | |
204 | $globals->db->query("delete from diogenes_plugin where barrel='$alias'"); | |
205 | } | |
206 | ||
207 | ||
208 | /** Return the location corresponding to a given page ID | |
209 | * | |
210 | * @param $PID | |
211 | */ | |
212 | function getLocation($PID) | |
213 | { | |
214 | return array_search($PID, $this->treeCache); | |
215 | } | |
216 | ||
217 | ||
218 | ||
219 | /** Return all the barrel's pages. | |
220 | */ | |
221 | function getPages() | |
222 | { | |
223 | global $globals; | |
224 | $bpages = array(); | |
225 | ||
226 | $res = $globals->db->query("select * from {$this->table_page}"); | |
227 | while ($props = mysql_fetch_assoc($res)) { | |
228 | $bpages[$props['PID']] = new Diogenes_Barrel_Page($this, $props); | |
229 | } | |
230 | mysql_free_result($res); | |
231 | return $bpages; | |
232 | } | |
233 | ||
234 | ||
235 | /** Return the page ID matching a given directory location | |
236 | * | |
237 | * @param $dir | |
238 | */ | |
239 | function getPID($dir) | |
240 | { | |
241 | if (isset($this->treeCache[$dir])) | |
242 | return $this->treeCache[$dir]; | |
243 | else | |
244 | return; | |
245 | } | |
246 | ||
247 | ||
6855525e JL |
248 | /** Check whether the barrel has a given flag |
249 | * | |
250 | * @param $flag | |
251 | */ | |
252 | function hasFlag($flag) | |
253 | { | |
254 | return $this->flags->hasFlag($flag); | |
255 | } | |
256 | ||
257 | ||
258 | /** Compile the directory tree | |
259 | */ | |
260 | function compileTree() | |
261 | { | |
262 | global $globals; | |
263 | ||
264 | if (!$fp = fopen($this->treeCacheFile, "w")) { | |
265 | trigger_error("failed to open '{$this->treeCacheFile}' for writing", E_USER_ERROR); | |
266 | return; | |
267 | } | |
268 | ||
269 | // load all the pages | |
270 | $res = $globals->db->query("select * from {$this->table_page}"); | |
271 | $tpages = array(); | |
272 | while ($props = mysql_fetch_assoc($res)) | |
273 | { | |
274 | $tpage = new Diogenes_Barrel_Page($this, $props); | |
275 | $tpages[$props['PID']] = $tpage; | |
276 | if (!strlen($props['location'])) | |
277 | { | |
278 | $homepage = $props['PID']; | |
279 | } | |
280 | } | |
281 | ||
282 | // recursively build the tree, starting at the homepage | |
283 | $str = $this->compilePageTree($tpages, $homepage, ''); | |
284 | fputs($fp, $str); | |
285 | fclose($fp); | |
286 | } | |
287 | ||
288 | ||
289 | /** Compile a single page | |
290 | */ | |
291 | function compilePageTree(&$tpages, $PID, $ploc) | |
292 | { | |
293 | global $globals; | |
294 | ||
295 | $cpage = $tpages[$PID]; | |
296 | $ploc = ($ploc ? "$ploc/" : "") . $cpage->props['location']; | |
297 | ||
298 | // add this page | |
299 | $out = "$ploc\t$PID\t".$cpage->props['parent']."\n"; | |
300 | ||
301 | // add children | |
302 | $res = $globals->db->query("select PID from {$this->table_page} where parent='$PID'"); | |
303 | while (list($child) = mysql_fetch_row($res)) | |
304 | { | |
305 | $out .= $this->compilePageTree($tpages, $child, $ploc); | |
306 | } | |
307 | mysql_free_result($res); | |
308 | return $out; | |
309 | } | |
310 | ||
311 | ||
7aff44b2 | 312 | /** Load all active plugins for the specified page. |
6855525e JL |
313 | * |
314 | * @param $bpage | |
315 | */ | |
316 | function loadPlugins(&$bpage) | |
317 | { | |
318 | global $globals; | |
319 | ||
7aff44b2 | 320 | $plugins = $globals->plugins->cacheGetActive($this->pluginsCache, $this->alias, $page); |
6855525e | 321 | $loaded = array(); |
7aff44b2 | 322 | foreach ($plugins as $plugname => $plugentry) |
6855525e | 323 | { |
7aff44b2 | 324 | $loaded[$plugname] =& $globals->plugins->load($plugname, $plugentry); |
6855525e JL |
325 | } |
326 | return $loaded; | |
327 | } | |
328 | ||
329 | ||
330 | /** Read the compiled plugin cache | |
331 | */ | |
332 | function readPlugins() | |
333 | { | |
334 | global $globals; | |
335 | ||
336 | $this->pluginsCache = $globals->plugins->readCache($this->pluginsCacheFile, $this->alias); | |
337 | } | |
338 | ||
339 | ||
340 | /** Read the compiled directory tree | |
341 | */ | |
342 | function readTree() | |
343 | { | |
344 | global $globals; | |
345 | ||
346 | // if the tree cache does not exits, try to init it | |
347 | if (!file_exists($this->treeCacheFile)) { | |
348 | $this->compileTree(); | |
349 | } | |
350 | ||
351 | if (!$fp = fopen($this->treeCacheFile, "r")) { | |
352 | trigger_error("failed to open '{$this->treeCacheFile}' for reading", E_USER_ERROR); | |
353 | return; | |
354 | } | |
355 | ||
356 | $locations = array(); | |
357 | while ($line = fgets($fp)) | |
358 | { | |
359 | $line = substr($line, 0, -1); | |
360 | $bits = explode("\t", $line); | |
361 | list($loc, $pid, $parent) = $bits; | |
362 | $locations[$loc] = $pid; | |
363 | } | |
364 | fclose($fp); | |
365 | ||
366 | $this->treeCache = $locations; | |
367 | } | |
368 | ||
369 | } |