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
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)
12 //require_once "PEAR.php";
15 * Converted PHPLIB Template class
17 * For those who want to use PHPLIB's fine template class,
18 * here's a PEAR conforming class with the original PHPLIB
19 * template code from phplib-stable CVS. Original author
20 * was Kristian Koehntopp <kris@koehntopp.de>
22 * @author Bjoern Schotte <bjoern@rent-a-phpwizard.de>
23 * @author Martin Jansen <mj@php.net> (PEAR conformance)
29 * If set, echo assignments
35 * $file[handle] = "filename";
41 * fallback paths that should be defined in a child class
44 var $file_fallbacks = array();
47 * Relative filenames are relative to this pathname
53 * $_varKeys[key] = "key"
56 var $_varKeys = array();
59 * $_varVals[key] = "value";
62 var $_varVals = array();
65 * "remove" => remove undefined variables
66 * "comment" => replace undefined variables with comments
67 * "keep" => keep undefined variables
70 var $unknowns = "remove";
73 * "yes" => halt, "report" => report error, continue, "no" => ignore error quietly
76 var $haltOnError = "report";
79 * The last error message is retained here
90 * @param string template root directory
91 * @param string how to handle unknown variables
92 * @param array fallback paths
94 function Template_PHPLIB($root = ".", $unknowns = "remove", $fallback="")
96 $this->setRoot($root);
97 $this->setUnknowns($unknowns);
98 if (is_array($fallback)) $this->file_fallbacks
= $fallback;
102 * Sets the template directory
105 * @param string new template directory
108 function setRoot($root)
110 if (!is_dir($root)) {
111 $this->halt("setRoot: $root is not a directory.");
121 * What to do with unknown variables
123 * three possible values:
125 * - "remove" will remove unknown variables
126 * (don't use this if you define CSS in your page)
127 * - "comment" will replace undefined variables with comments
128 * - "keep" will keep undefined variables as-is
131 * @param string unknowns
133 function setUnknowns($unknowns = "keep")
135 $this->unknowns
= $unknowns;
139 * Set appropriate template files
141 * With this method you set the template files you want to use.
142 * Either you supply an associative array with key/value pairs
143 * where the key is the handle for the filname and the value
144 * is the filename itself, or you define $handle as the file name
145 * handle and $filename as the filename if you want to define only
149 * @param mixed handle for a filename or array with handle/name value pairs
150 * @param string name of template file
153 function setFile($handle, $filename = "")
155 if (!is_array($handle)) {
157 if ($filename == "") {
158 $this->halt("setFile: For handle $handle filename is empty.");
162 $this->file
[$handle] = $this->_filename($filename);
167 while (list($h, $f) = each($handle)) {
168 $this->file
[$h] = $this->_filename($f);
174 * Set a block in the appropriate template handle
176 * By setting a block like that:
178 * <!-- BEGIN blockname -->
180 * <!-- END blockname -->
182 * you can easily do repeating HTML code, i.e. output
183 * database data nice formatted into a HTML table where
184 * each DB row is placed into a HTML table row which is
185 * defined in this block.
186 * It extracts the template $handle from $parent and places
187 * variable {$name} instead.
190 * @param string parent handle
191 * @param string block name handle
192 * @param string variable substitution name
194 function setBlock($parent, $handle, $name = "")
196 if (!$this->_loadFile($parent)) {
197 $this->halt("setBlock: unable to load $parent.");
205 $str = $this->getVar($parent);
206 $reg = "/[ \t]*<!--\s+BEGIN $handle\s+-->\s*?\n?(\s*.*?\n?)\s*<!--\s+END $handle\s+-->\s*?\n?/sm";
207 preg_match_all($reg, $str, $m);
208 $str = preg_replace($reg, "{" . "$name}", $str);
210 if (isset($m[1][0])) $this->setVar($handle, $m[1][0]);
211 $this->setVar($parent, $str);
215 * Set corresponding substitutions for placeholders
218 * @param string name of a variable that is to be defined or an array of variables with value substitution as key/value pairs
219 * @param string value of that variable
220 * @param boolean if true, the value is appended to the variable's existing value
222 function setVar($varname, $value = "", $append = false
)
224 if (!is_array($varname)) {
226 if (!empty($varname))
227 if ($this->debug
) print "scalar: set *$varname* to *$value*<br>\n";
229 $this->_varKeys
[$varname] = $this->_varname($varname);
230 ($append) ?
$this->_varVals
[$varname] .= $value : $this->_varVals
[$varname] = $value;
235 while (list($k, $v) = each($varname)) {
237 if ($this->debug
) print "array: set *$k* to *$v*<br>\n";
239 $this->_varKeys
[$k] = $this->_varname($k);
240 ($append) ?
$this->_varVals
[$k] .= $v : $this->_varVals
[$k] = $v;
246 * Substitute variables in handle $handle
249 * @param string name of handle
250 * @return mixed string substituted content of handle
252 function subst($handle)
254 if (!$this->_loadFile($handle)) {
255 $this->halt("subst: unable to load $handle.");
259 return @str_replace
($this->_varKeys
, $this->_varVals
, $this->getVar($handle));
263 * Same as subst but printing the result
267 * @param string handle of template
268 * @return bool always false
270 function pSubst($handle)
272 print $this->subst($handle);
277 * Parse handle into target
279 * Parses handle $handle into $target, eventually
280 * appending handle at $target if $append is defined
284 * @param string target handle to parse into
285 * @param string which handle should be parsed
286 * @param boolean append it to $target or not?
287 * @return string parsed handle
289 function parse($target, $handle, $append = false
)
291 if (!is_array($handle)) {
292 $str = $this->subst($handle);
294 ($append) ?
$this->setVar($target, $this->getVar($target) . $str) : $this->setVar($target, $str);
298 while (list(, $h) = each($handle)) {
299 $str = $this->subst($h);
300 $this->setVar($target, $str);
308 * Same as parse, but printing it.
312 * @param string target to parse into
313 * @param string handle which should be parsed
314 * @param should $handle be appended to $target?
317 function pParse($target, $handle, $append = false
)
319 print $this->finish($this->parse($target, $handle, $append));
324 * Return all defined variables and their values
327 * @return array with all defined variables and their values
331 reset($this->_varKeys
);
333 while (list($k, ) = each($this->_varKeys
)) {
334 $result[$k] = $this->getVar($k);
341 * Return one or more specific variable(s) with their values.
344 * @param mixed array with variable names or one variable name as a string
345 * @return mixed array of variable names with their values or value of one specific variable
347 function getVar($varname)
349 if (!is_array($varname)) {
350 if (isset($this->_varVals
[$varname])) {
351 return $this->_varVals
[$varname];
358 while (list($k, ) = each($varname)) {
359 $result[$k] = (isset($this->_varVals
[$k])) ?
$this->_varVals
[$k] : "";
367 * Get undefined values of a handle
370 * @param string handle name
371 * @return mixed false if an error occured or the undefined values
373 function getUndefined($handle)
375 if (!$this->_loadFile($handle)) {
376 $this->halt("getUndefined: unable to load $handle.");
380 preg_match_all("/{([^ \t\r\n}]+)}/", $this->getVar($handle), $m);
387 while (list(, $v) = each($m)) {
388 if (!isset($this->_varKeys
[$v])) {
393 if (isset($result) && count($result)) {
404 * @param string string to finish
405 * @return finished, i.e. substituted string
407 function finish($str)
409 switch ($this->unknowns
) {
411 $str = preg_replace('/{[^ \t\r\n}]+}/', "", $str);
415 $str = preg_replace('/{([^ \t\r\n}]+)}/', "<!-- Template $handle: Variable \\1 undefined -->", $str);
423 * Print variable to the browser
426 * @param string name of variable to print
430 print $this->finish($this->getVar($varname));
434 * Get finished variable
436 * @access public public
437 * @param string variable to get
438 * @return string string with finished variable
440 function get($varname)
442 return $this->finish($this->getVar($varname));
448 * Complete filename, i.e. testing it for slashes
451 * @param string filename to be completed
452 * @return string completed filename
454 function _filename($filename)
456 // if (substr($filename, 0, 1) != "/") {
457 // $filename = $this->root."/".$filename;
460 if (file_exists($filename)) return $filename;
461 if (is_array($this->file_fallbacks
) && count($this->file_fallbacks
) > 0) {
462 reset($this->file_fallbacks
);
463 while (list(,$v) = each($this->file_fallbacks
)) {
464 if (file_exists($v.basename($filename))) return $v.basename($filename);
466 $this->halt(sprintf("filename: file %s does not exist in the fallback paths %s.",$filename,implode(",",$this->file_fallbacks
)));
469 $this->halt(sprintf("filename: file %s does not exist.",$filename));
477 * Protect a replacement variable
480 * @param string name of replacement variable
481 * @return string replaced variable
483 function _varname($varname)
485 return "{".$varname."}";
489 * load file defined by handle if it is not loaded yet
492 * @param string handle
493 * @return bool FALSE if error, true if all is ok
495 function _loadFile($handle)
497 if (isset($this->_varKeys
[$handle]) and !empty($this->_varVals
[$handle])) {
501 if (!isset($this->file
[$handle])) {
502 $this->halt("loadfile: $handle is not a valid handle.");
506 $filename = $this->file
[$handle];
507 if (function_exists("file_get_contents")) {
508 $str = file_get_contents($filename);
510 if (!$fp = @fopen
($filename,"r")) {
511 $this->halt("loadfile: couldn't open $filename");
515 $str = fread($fp,filesize($filename));
520 $this->halt("loadfile: While loading $handle, $filename does not exist or is empty.");
524 $this->setVar($handle, $str);
530 * Error function. Halt template system with message to show
533 * @param string message to show
538 $this->_lastError
= $msg;
540 if ($this->haltOnError
!= "no") {
541 // return $this->haltMsg($msg);
542 $this->haltMsg($msg);
545 if ($this->haltOnError
== "yes") {
546 die("<b>Halted.</b>");
553 * printf error message to show
556 * @param string message to show
557 * @return object PEAR error object
559 function haltMsg($msg)
561 // PEAR::raiseError(sprintf("<b>Template Error:</b> %s<br>\n", $msg));
562 printf("<b>Template Error:</b> %s<br>\n", $msg);