Code

11be7988d7e60610975959d0a8970f7f727f6ff7
[gosa.git] / trunk / gosa-core / include / utils / layer-menu / lib / PHPLIB.php
1 <?php
2 // vim: set expandtab tabstop=4 shiftwidth=4:
3 // This code that was derived from the original PHPLIB Template class
4 // is copyright by Kristian Koehntopp, NetUSE AG and was released
5 // under the LGPL.
6 //
7 // Authors: Kristian Koehntopp <kris@koehntopp.de> (original from PHPLIB)
8 //          Bjoern Schotte <bjoern@rent-a-phpwizard.de> (PEARification)                
9 //          Martin Jansen <mj@php.net> (PEAR conformance)            
10 //
11 // $Id: PHPLIB.php,v 1.14 2003/06/11 06:03:32 bjoern Exp $
12 //
14 //require_once "PEAR.php";
16 /**
17  * Converted PHPLIB Template class
18  *
19  * For those who want to use PHPLIB's fine template class,
20  * here's a PEAR conforming class with the original PHPLIB
21  * template code from phplib-stable CVS. Original author
22  * was Kristian Koehntopp <kris@koehntopp.de>
23  *
24  * @author  Bjoern Schotte <bjoern@rent-a-phpwizard.de>
25  * @author  Martin Jansen <mj@php.net> (PEAR conformance)
26  * @version 1.0
27  */
28 class Template_PHPLIB
29 {
30     /**
31      * If set, echo assignments
32      * @var bool
33      */
34     var $debug     = false;
36     /**
37      * $file[handle] = "filename";
38      * @var array
39      */
40     var $file  = array();
42     /**
43      * fallback paths that should be defined in a child class
44      * @var array
45      */
46     var $file_fallbacks = array();
48     /**
49      * Relative filenames are relative to this pathname
50      * @var string
51      */
52     var $root   = "";
54     /*
55      * $_varKeys[key] = "key"
56      * @var array
57      */
58     var $_varKeys = array();
59     
60     /**
61      * $_varVals[key] = "value";
62      * @var array
63      */
64     var $_varVals = array();
66     /**
67      * "remove"  => remove undefined variables
68      * "comment" => replace undefined variables with comments
69      * "keep"    => keep undefined variables
70      * @var string
71      */
72     var $unknowns = "remove";
73   
74     /**
75      * "yes" => halt, "report" => report error, continue, "no" => ignore error quietly
76      * @var string
77      */
78     var $haltOnError  = "report";
79   
80     /**
81      * The last error message is retained here
82      * @var string
83      * @see halt
84      */
85     var $_lastError     = "";
88     /**
89      * Constructor
90      *
91      * @access public
92      * @param  string template root directory
93      * @param  string how to handle unknown variables
94      * @param  array fallback paths
95      */
96     function Template_PHPLIB($root = ".", $unknowns = "remove", $fallback="")
97     {
98         $this->setRoot($root);
99         $this->setUnknowns($unknowns);
100         if (is_array($fallback)) $this->file_fallbacks = $fallback;
101     }
103     /**
104      * Sets the template directory
105      *
106      * @access public
107      * @param  string new template directory
108      * @return bool
109      */
110     function setRoot($root)
111     {
112         if (!is_dir($root)) {
113             $this->halt("setRoot: $root is not a directory.");
114             return false;
115         }
116     
117         $this->root = $root;
118     
119         return true;
120     }
122     /**
123      * What to do with unknown variables
124      *
125      * three possible values:
126      *
127      * - "remove" will remove unknown variables
128      *   (don't use this if you define CSS in your page)
129      * - "comment" will replace undefined variables with comments
130      * - "keep" will keep undefined variables as-is
131      *
132      * @access public
133      * @param  string unknowns
134      */
135     function setUnknowns($unknowns = "keep")
136     {
137         $this->unknowns = $unknowns;
138     }
140     /**
141      * Set appropriate template files
142      *
143      * With this method you set the template files you want to use.
144      * Either you supply an associative array with key/value pairs
145      * where the key is the handle for the filname and the value
146      * is the filename itself, or you define $handle as the file name
147      * handle and $filename as the filename if you want to define only
148      * one template.
149      *
150      * @access public
151      * @param  mixed handle for a filename or array with handle/name value pairs
152      * @param  string name of template file
153      * @return bool
154      */
155     function setFile($handle, $filename = "")
156     {
157         if (!is_array($handle)) {
158     
159             if ($filename == "") {
160                 $this->halt("setFile: For handle $handle filename is empty.");
161                 return false;
162             }
163       
164             $this->file[$handle] = $this->_filename($filename);
165       
166         } else {
167     
168             reset($handle);
169             while (list($h, $f) = each($handle)) {
170                 $this->file[$h] = $this->_filename($f);
171             }
172         }
173     }
175     /**
176      * Set a block in the appropriate template handle
177      *
178      * By setting a block like that:
179      *
180      * &lt;!-- BEGIN blockname --&gt;
181      * html code
182      * &lt;!-- END blockname --&gt;
183      *
184      * you can easily do repeating HTML code, i.e. output
185      * database data nice formatted into a HTML table where
186      * each DB row is placed into a HTML table row which is
187      * defined in this block.
188      * It extracts the template $handle from $parent and places
189      * variable {$name} instead.
190      *
191      * @access public
192      * @param  string parent handle
193      * @param  string block name handle
194      * @param  string variable substitution name
195      */
196     function setBlock($parent, $handle, $name = "")
197     {
198         if (!$this->_loadFile($parent)) {
199             $this->halt("setBlock: unable to load $parent.");
200             return false;
201         }
202     
203         if ($name == "") {
204             $name = $handle;
205         }
207         $str = $this->getVar($parent);
208         $reg = "/[ \t]*<!--\s+BEGIN $handle\s+-->\s*?\n?(\s*.*?\n?)\s*<!--\s+END $handle\s+-->\s*?\n?/sm";
209         preg_match_all($reg, $str, $m);
210         $str = preg_replace($reg, "{" . "$name}", $str);
212         if (isset($m[1][0])) $this->setVar($handle, $m[1][0]);
213         $this->setVar($parent, $str);
214     }
216     /**
217      * Set corresponding substitutions for placeholders
218      *
219      * @access public
220      * @param  string name of a variable that is to be defined or an array of variables with value substitution as key/value pairs
221      * @param  string value of that variable
222      * @param  boolean if true, the value is appended to the variable's existing value
223      */
224     function setVar($varname, $value = "", $append = false)
225     {
226         if (!is_array($varname)) {
228             if (!empty($varname))
229                 if ($this->debug) print "scalar: set *$varname* to *$value*<br>\n";
231             $this->_varKeys[$varname] = $this->_varname($varname);
232             ($append) ? $this->_varVals[$varname] .= $value : $this->_varVals[$varname] = $value;
234         } else {
235             reset($varname);
237             while (list($k, $v) = each($varname)) {
238                 if (!empty($k))
239                     if ($this->debug) print "array: set *$k* to *$v*<br>\n";
241                 $this->_varKeys[$k] = $this->_varname($k);
242                 ($append) ? $this->_varVals[$k] .= $v : $this->_varVals[$k] = $v;
243             }
244         }
245     }
247     /**
248      * Substitute variables in handle $handle
249      *
250      * @access public
251      * @param  string name of handle
252      * @return mixed string substituted content of handle
253      */
254     function subst($handle)
255     {
256         if (!$this->_loadFile($handle)) {
257             $this->halt("subst: unable to load $handle.");
258             return false;
259         }
261         return @str_replace($this->_varKeys, $this->_varVals, $this->getVar($handle));
262     }
263   
264     /**
265      * Same as subst but printing the result
266      *
267      * @access  public
268      * @brother subst
269      * @param   string handle of template
270      * @return  bool always false
271      */
272     function pSubst($handle)
273     {
274         print $this->subst($handle);
275         return false;
276     }
278     /**
279      * Parse handle into target
280      *
281      * Parses handle $handle into $target, eventually
282      * appending handle at $target if $append is defined
283      * as TRUE.
284      *
285      * @access public
286      * @param  string target handle to parse into
287      * @param  string which handle should be parsed
288      * @param  boolean append it to $target or not?
289      * @return string parsed handle
290      */
291     function parse($target, $handle, $append = false)
292     {
293         if (!is_array($handle)) {
294             $str = $this->subst($handle);
296             ($append) ? $this->setVar($target, $this->getVar($target) . $str) : $this->setVar($target, $str);
297         } else {
298             reset($handle);
300             while (list(, $h) = each($handle)) {
301                 $str = $this->subst($h);
302                 $this->setVar($target, $str);
303             }
304         }
306         return $str;
307     }
309     /**
310      * Same as parse, but printing it.
311      *
312      * @access  public
313      * @brother parse
314      * @param   string target to parse into
315      * @param   string handle which should be parsed
316      * @param   should $handle be appended to $target?
317      * @return  bool
318      */
319     function pParse($target, $handle, $append = false)
320     {
321         print $this->finish($this->parse($target, $handle, $append));
322         return false;
323     }
324   
325     /**
326      * Return all defined variables and their values
327      *
328      * @access public
329      * @return array with all defined variables and their values
330      */
331     function getVars()
332     {
333         reset($this->_varKeys);
335         while (list($k, ) = each($this->_varKeys)) {
336             $result[$k] = $this->getVar($k);
337         }
339         return $result;
340     }
342     /**
343      * Return one or more specific variable(s) with their values.
344      *
345      * @access public    
346      * @param  mixed array with variable names or one variable name as a string
347      * @return mixed array of variable names with their values or value of one specific variable
348      */
349     function getVar($varname)
350     {
351         if (!is_array($varname)) {
352             if (isset($this->_varVals[$varname])) {
353                 return $this->_varVals[$varname];
354             } else {
355                 return "";
356             }
357         } else {
358             reset($varname);
359     
360             while (list($k, ) = each($varname)) {
361                 $result[$k] = (isset($this->_varVals[$k])) ? $this->_varVals[$k] : "";
362             }
364             return $result;
365         }
366     }
367   
368     /**
369      * Get undefined values of a handle
370      *
371      * @access public
372      * @param  string handle name
373      * @return mixed  false if an error occured or the undefined values
374      */
375     function getUndefined($handle)
376     {
377         if (!$this->_loadFile($handle)) {
378             $this->halt("getUndefined: unable to load $handle.");
379             return false;
380         }
381     
382         preg_match_all("/{([^ \t\r\n}]+)}/", $this->getVar($handle), $m);
383         $m = $m[1];
384         if (!is_array($m)) {
385             return false;
386         }
388         reset($m);
389         while (list(, $v) = each($m)) {
390             if (!isset($this->_varKeys[$v])) {
391                 $result[$v] = $v;
392             }
393         }
394     
395         if (isset($result) && count($result)) {
396             return $result;
397         } else {
398             return false;
399         }
400     }
402     /**
403      * Finish string
404      *
405      * @access public
406      * @param  string string to finish
407      * @return finished, i.e. substituted string
408      */
409     function finish($str)
410     {
411         switch ($this->unknowns) {
412             case "remove":
413                 $str = preg_replace('/{[^ \t\r\n}]+}/', "", $str);
414                 break;
416             case "comment":
417                 $str = preg_replace('/{([^ \t\r\n}]+)}/', "<!-- Template $handle: Variable \\1 undefined -->", $str);
418                 break;
419         }
421         return $str;
422     }
424     /**
425      * Print variable to the browser
426      *
427      * @access public
428      * @param  string name of variable to print
429      */
430     function p($varname)
431     {
432         print $this->finish($this->getVar($varname));
433     }
435     /**
436      * Get finished variable
437      *
438      * @access public public
439      * @param  string variable to get
440      * @return string string with finished variable
441      */
442     function get($varname)
443     {
444         return $this->finish($this->getVar($varname));
445     }
447     /**
448      * Complete filename
449      *
450      * Complete filename, i.e. testing it for slashes
451      *
452      * @access private
453      * @param  string filename to be completed
454      * @return string completed filename
455      */
456     function _filename($filename)
457     {
458 //        if (substr($filename, 0, 1) != "/") {
459 //            $filename = $this->root."/".$filename;
460 //        }
462         if (file_exists($filename)) return $filename;
463         if (is_array($this->file_fallbacks) && count($this->file_fallbacks) > 0) {
464             reset($this->file_fallbacks);
465             while (list(,$v) = each($this->file_fallbacks)) {
466                 if (file_exists($v.basename($filename))) return $v.basename($filename);
467             }
468             $this->halt(sprintf("filename: file %s does not exist in the fallback paths %s.",$filename,implode(",",$this->file_fallbacks)));
469             return false;
470         } else {
471             $this->halt(sprintf("filename: file %s does not exist.",$filename));
472             return false;
473         }
475         return $filename;
476     }
478     /**
479      * Protect a replacement variable
480      *
481      * @access private
482      * @param  string name of replacement variable
483      * @return string replaced variable
484      */
485     function _varname($varname)
486     {
487         return "{".$varname."}";
488     }
490     /**
491      * load file defined by handle if it is not loaded yet
492      *
493      * @access private
494      * @param  string handle
495      * @return bool   FALSE if error, true if all is ok
496      */
497     function _loadFile($handle)
498     {
499         if (isset($this->_varKeys[$handle]) and !empty($this->_varVals[$handle])) {
500             return true;
501         }
503         if (!isset($this->file[$handle])) {
504             $this->halt("loadfile: $handle is not a valid handle.");
505             return false;
506         }
508         $filename = $this->file[$handle];
509         if (function_exists("file_get_contents")) {
510             $str = file_get_contents($filename);
511         } else {
512             if (!$fp = @fopen($filename,"r")) {
513                 $this->halt("loadfile: couldn't open $filename");
514                 return false;
515             }
517             $str = fread($fp,filesize($filename));
518             fclose($fp);
519         }
521         if ($str=='') {
522             $this->halt("loadfile: While loading $handle, $filename does not exist or is empty.");
523             return false;
524         }
526         $this->setVar($handle, $str);
528         return true;
529     }
531     /**
532      * Error function. Halt template system with message to show
533      *
534      * @access public
535      * @param  string message to show
536      * @return bool
537      */
538     function halt($msg)
539     {
540         $this->_lastError = $msg;
542         if ($this->haltOnError != "no") {
543 //            return $this->haltMsg($msg);
544             $this->haltMsg($msg);
545         }
547         if ($this->haltOnError == "yes") {
548             die("<b>Halted.</b>");
549         }
551         return false;
552     }
553   
554     /**
555      * printf error message to show
556      *
557      * @access public
558      * @param  string message to show
559      * @return object PEAR error object
560      */
561     function haltMsg($msg)
562     {
563 //        PEAR::raiseError(sprintf("<b>Template Error:</b> %s<br>\n", $msg));
564         printf("<b>Template Error:</b> %s<br>\n", $msg);
565     }
567 ?>