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