fix text output of Diogenes_Tree_Node
[diogenes.git] / include / Plugins.php
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 // dependency on PEAR
22 require_once 'System.php';
23 require_once 'Tree/Node.php';
24 require_once 'Plugin/Skel.php';
25
26
27 /** This class describes Diogenes' plugins.
28 */
29 class Diogenes_Plugins
30 {
31 /** Directory that holds the plugins cache files */
32 var $cachedir;
33
34 /** Directory that holds the plugins */
35 var $plugdir;
36
37 /** Plugins that will be sent to trace */
38 var $log = array();
39
40 /** Constructs a new holder for Diogenes plugins.
41 *
42 * @param $dbh
43 * @param $plugdir
44 * @param $cachedir
45 */
46 function Diogenes_Plugins(&$dbh, $plugdir, $cachedir)
47 {
48 $this->dbh =& $dbh;
49 $this->plugdir = $plugdir;
50 $this->cachedir = $cachedir;
51 }
52
53
54 /** Return the path of the cache file
55 *
56 * @param $barrel
57 */
58 function cacheFile($barrel)
59 {
60 $cachefile = $this->cachedir . "/" . ($barrel ? $barrel : "__diogenes__") . ".plugins";
61 return $cachefile;
62 }
63
64 /** Return the cache entry for specified plugin
65 *
66 * @param $cache
67 * @param $barrel
68 * @param $page
69 * @param $plugin
70 */
71 function cacheGet($cache, $barrel, $page, $plugin)
72 {
73 $p_node = $this->cacheGetPageNode($cache, $barrel, $page);
74 return $p_node->data[$plugin];
75 }
76
77
78 /** Return the cache entry for a plugin at a specified position
79 *
80 * @param $cache
81 * @param $barrel
82 * @param $page
83 * @param $pos
84 */
85 function cacheGetAtPos($cache, $barrel, $page, $pos)
86 {
87 $p_node = $this->cacheGetPageNode($cache, $barrel, $page);
88 foreach ($p_node->data as $plugname => $plugentry)
89 {
90 if ($plugentry['pos'] == $pos)
91 {
92 $plugentry['plugin'] = $plugname;
93 return $plugentry;
94 }
95 }
96 }
97
98
99 /** Return the cache entry for specified plugin
100 *
101 * @param $cache
102 * @param $barrel
103 * @param $page
104 * @param $plugin
105 */
106 function cacheGetPageNode($cache, $barrel, $page)
107 {
108 if ($page) {
109 $p_node = $cache->getChild($page);
110 } else {
111 $p_node = $cache;
112 }
113 return $p_node;
114 }
115
116
117 /** List the plugins that are active in a given context
118 *
119 * @param $cache
120 * @param $barrel
121 * @param $page
122 */
123 function cachedActive($cache, $barrel, $page)
124 {
125 $p_node = $this->cacheGetPageNode($cache, $barrel, $page);
126 $plugins = array();
127 return $plugins;
128 }
129
130
131 /** Returns an array of cache entries representing the available plugins
132 * in a given context
133 *
134 * @param $cache
135 * @param $barrel
136 * @param $page
137 */
138 function cachedAvailable($cache, $barrel, $page)
139 {
140 $p_node = $this->cacheGetPageNode($cache, $barrel, $page);
141 //echo "<pre>".var_encode_text($p_node)."</pre>";
142 foreach ($p_node->data as $plugname => $plugentry)
143 {
144 $plugfile = $this->plugdir."/".$plugname.".php";
145 if (file_exists($plugfile) and (!$barrel || ($plugentry['status'] != PLUG_DISABLED)))
146 {
147 $available[$plugname] = $plugentry;
148 }
149 }
150 return $available;
151 }
152
153
154 /** Remove database references to plugins that are not available.
155 */
156 function clean_database(&$page)
157 {
158 /*
159 $res = $this->dbh->query("select distinct plugin from diogenes_plugin");
160 while (list($plugname) = mysql_fetch_row($res))
161 {
162 $page->info("examining $plugname..");
163 $plug = $this->load($plugname);
164 if (!is_object($plug)) {
165 $page->info("plugin $plugname is broken, removing");
166 $this->dbh->query("delete from diogenes_plugin where plugin='$plugname'");
167 }
168 }
169 mysql_free_result($res);
170 */
171 }
172
173
174 /** Build view for current level.
175 */
176 function compileNode($node, &$outparent, $index)
177 {
178 $outvals = array();
179 foreach ($outparent->data as $plugin => $parentval)
180 {
181 //echo "Processing plugin '$plugin' for &lt;{$node->name}&gt;<br/>\n";
182 $outval = '';
183 if ($parentval['status'] != PLUG_DISABLED)
184 {
185 //echo "* plugin available/enabled at parent level<br/>\n";
186 $outval = $parentval;
187 if (is_array($node->data[$plugin]))
188 {
189 //echo "** plugin set at current level<br/>\n";
190 $outval['pos'] = $node->data[$plugin]['pos'];
191 $outval['params'] = $node->data[$plugin]['params'];
192 if ($parentval['status'] == PLUG_AVAILABLE) {
193 //echo "*** plugin status set to DB-specified value<br/>\n";
194 $outval['status'] = $node->data[$plugin]['status'];
195 } else {
196 //echo "*** plugin forced on at parent level<br/>\n";
197 }
198 } else {
199 //echo "** plugin unset at current level<br/>\n";
200 }
201 }
202
203 // add the plugin to output
204 if (is_array($outval))
205 {
206 $outvals[$plugin] = $outval;
207 }
208 }
209 $outnode = new Diogenes_Tree_Node($outvals, $node->name);
210 //echo "<hr/>";
211
212 // recurse into children
213 foreach ($node->children as $cindex => $child)
214 {
215 $this->compileNode($child, $outnode, $cindex);
216 }
217
218 // add the produced node
219 $outparent->setChild($index, $outnode);
220 }
221
222
223 /** Compile plugin cache.
224 *
225 * @param $barrel
226 */
227 function compileCache($barrel, &$caller)
228 {
229 $caller->info("Recompiling " .($barrel ? "plugin cache for barrel '$barrel'" : "global plugin cache"));
230
231 // get the list of all plugins present on the system
232 $allplugins = array();
233 $plugfiles = System::find($this->plugdir.' -type f -name *.php');
234 foreach ($plugfiles as $file) {
235 $name = basename($file);
236 $name = substr($name, 0, -4);
237 array_push($allplugins, $name);
238 }
239
240 $defcache = array();
241 // fill initial values
242 foreach ($allplugins as $plugin)
243 {
244 $plug_h = $this->load($plugin);
245 $defcache[$plugin] = $plug_h->toArray();
246 }
247
248 // get DB values
249 $dbcache = array();
250
251 $sql_limit = $barrel ? " where barrel='{$barrel}' or barrel=''" : "";
252 $sql = "select barrel, page, plugin, status, pos, params from diogenes_plugin" . $sql_limit;
253 $res = $this->dbh->query($sql);
254 while($row = mysql_fetch_row($res))
255 {
256 $c_barrel = array_shift($row);
257 $c_page = array_shift($row);
258 $plugin = array_shift($row);
259 $plugentry = array(
260 'status' => $row[0],
261 'pos' => $row[1],
262 'params' => ($row[2] ? var_decode_bin($row[2]) : array())
263 );
264 $plug_h = $this->load($plugin, $plugentry);
265 //echo "Got params from DB for '$plugin', barrel '$c_barrel', page '$c_page' : ".$row[2]."<br/>";
266 $dbcache[$c_barrel][$c_page][$plugin] = $plug_h->toArray();
267 }
268 mysql_free_result($res);
269
270 // build the input tree
271 $globals_node = new Diogenes_Tree_Node($dbcache[''][0], 'globals defaults');
272 $sql_limit = $barrel ? " where alias='{$barrel}'" : " where alias!=''";
273 $res = $this->dbh->query("select alias from diogenes_site" . $sql_limit);
274 while(list($c_barrel) = mysql_fetch_row($res))
275 {
276 $barrel_node = new Diogenes_Tree_Node($dbcache[$c_barrel][0], "barrel '$c_barrel' defaults");
277 $res2 = $this->dbh->query("select PID from {$c_barrel}_page");
278 while(list($page) = mysql_fetch_row($res2))
279 {
280 $page_node = new Diogenes_Tree_Node($dbcache[$c_barrel][$page], "barrel '$c_barrel' page $page");
281 $barrel_node->setChild($page, $page_node);
282 }
283 mysql_free_result($res2);
284 $globals_node->setChild($c_barrel, $barrel_node);
285 }
286 mysql_free_result($res);
287
288 // compile the cache
289 $top_out_node = new Diogenes_Tree_Node($defcache, 'plugin defaults');
290 $this->compileNode($globals_node, $top_out_node, 'globals');
291 $globals_out_node = $top_out_node->getChild('globals');
292 //echo "<pre>" . $top_out_node->dump() . "</pre><hr/>";
293
294 // produce dump(s)
295 if ($barrel) {
296 $dump_node = $globals_out_node->getChild($barrel);
297 $dump_node->writeFile($this->cachefile($barrel));
298 } else {
299 $globals_out_node->writeFile($this->cachefile($barrel), NODE_DUMP_NOCHILDREN);
300 $globals_out_node->writeFile($this->cachefile($barrel).".txt", NODE_DUMP_NOCHILDREN | NODE_DUMP_TEXT);
301 foreach ($globals_out_node->children as $c_barrel => $dump_node)
302 {
303 $dump_node->writeFile($this->cachefile($c_barrel));
304 }
305 }
306 }
307
308
309 /** Load the specified plugin
310 *
311 * @param $plugentry
312 */
313 function load($plugin, $plugentry = '')
314 {
315 $plugfile = $this->plugdir."/$plugin.php";
316 if (!file_exists($plugfile)) {
317 trigger_error("could not find plugin file '$plugfile'", E_USER_WARNING);
318 return;
319 }
320 include_once($plugfile);
321 if (!class_exists($plugin)) {
322 trigger_error("could not find class '$plugin'", E_USER_WARNING);
323 return;
324 }
325
326 // load and register plugin
327 $plug_h = new $plugin();
328 if (is_array($plugentry))
329 $plug_h->fromArray($plugentry);
330
331 $plug_log = $plug_h->toArray();
332 //$pluglog['name'] = 'foo';
333 array_push($this->log, $plug_log);
334 return $plug_h;
335 }
336
337
338 /** Read the compiled plugin cache
339 *
340 * @param $cachefile
341 * @param $barrel
342 */
343 function readCache($cachefile, $barrel)
344 {
345 if (!file_exists($cachefile)) {
346 return array();
347 }
348
349 return Diogenes_Tree_Node::readFile($cachefile);
350 }
351
352
353 /** Prepare plugins trace for output
354 */
355 function trace_format()
356 {
357 $out = '<table class="light" style="width: 100%; font-family: monospace">'."\n";
358 $odd = 0;
359 foreach ($this->log as $key => $val)
360 {
361 $trclass = $odd ? ' class="odd"' : '';
362 $out .= "<tr><th colspan=\"2\">{$val['name']} v{$val['version']}</th></tr>\n";
363 if (isset($val['pos'])) {
364 $out .= "<tr><td>position</td><td>{$val['pos']}</td></tr>\n";
365 }
366 $out .= "<tr$trclass><td>type</td><td>{$val['type']}</td></tr>\n";
367 $out .= "<tr$trclass><td>description</td><td>{$val['description']}</td></tr>\n";
368 if (!empty($val['params'])) {
369 $out .= "<tr$trclass><td>parameters</td><td>".var_encode_html($val['params'])."</td></tr>\n";
370 }
371 $odd = ($odd+1) % 2;
372 }
373 $out .= "</table>\n";
374 return $out;
375 }
376
377 }
378
379 ?>