<?php
class ubF_templates {
// Holds the array of filehandles FILELIST[HANDLE] == "fileName"
var $FILELIST = array();
// Holds the array of dynamic blocks, and the fileHandles they live in.
var $DYNAMIC = array();
// Holds the array of Variable handles. PARSEVARS[HANDLE] == "value"
var $PARSEVARS = array();
// We only want to load a template once - when it's used. LOADED[FILEHANDLE] == 1 if loaded undefined if not loaded yet.
var $LOADED = array();
var $HANDLE = array();
// Holds the handle names assigned by a call to parse()
var $ROOT = "";
// Holds path-to-templates
var $WIN32 = false;
// Set to true if this is a WIN32 server
// Holds the last error message
var $ERROR = "";
// Holds the HANDLE to the last template parsed by parse()
var $LAST = "";
// Strict template checking. Unresolved vars in templates will generate a warning when found.
var $STRICT = true;
// ************************************************************
function ubF_templates($pathToTemplates = "") {
global $php_errormsg;
if (! empty($pathToTemplates))
$this->set_root($pathToTemplates);
}
// end (new) FastTemplate ()
/**
*
* All templates will be loaded from this "root" directory
* Can be changed in mid-process by re-calling with a new
* value.
*
* @param unknown $root
*/
public function set_root($root) {
$trailer = substr($root, - 1);
if (! $this->WIN32) {
if ((ord($trailer)) != 47)
$root = "$root" . chr(47);
if (is_dir($root))
$this->ROOT = $root;
else {
$this->ROOT = "";
$this->error("Specified ROOT dir [$root] is not a directory");
}
} else {
// WIN32 box - no testing
if ((ord($trailer)) != 92)
$root = "$root" . chr(92);
$this->ROOT = $root;
}
}
// End set_root()
// **************************************************************
// Calculates current microtime
// I throw this into all my classes for benchmarking purposes
// It's not used by anything in this class and can be removed
// if you don't need it.
function utime() {
$time = explode(" ", microtime());
$usec = (double) $time[0];
$sec = (double) $time[1];
return $sec + $usec;
}
// **************************************************************
// Strict template checking, if true sends warnings to STDOUT when
// parsing a template with undefined variable references
// Used for tracking down bugs-n-such. Use no_strict() to disable.
function strict() {
$this->STRICT = true;
}
// ************************************************************
// Silently discards (removes) undefined variable references
// found in templates
function no_strict() {
$this->STRICT = false;
}
// ************************************************************
// A quick check of the template file before reading it.
// This is -not- a reliable check, mostly due to inconsistencies
// in the way PHP determines if a file is readable.
function is_safe($filename) {
if (! file_exists($filename)) {
$this->error("[$filename] does not exist", 0);
return false;
}
return true;
}
// ************************************************************
// Grabs a template from the root dir and
// reads it into a (potentially REALLY) big string
function get_template($template) {
if (empty($this->ROOT)) {
$this->error("Cannot open template. Root not valid.", 1);
return false;
}
$filename = "$this->ROOT" . "$template";
$contents = implode("", (@file($filename)));
if ((! $contents) or (empty($contents))) {
$this->error("get_template() failure: [$filename] $php_errormsg", 1);
}
return $contents;
}
// end get_template
// ************************************************************
// Prints the warnings for unresolved variable references
// in template files. Used if STRICT is true
function show_unknowns($Line) {
$unknown = array();
if (preg_match("({[A-Z0-9_]+})", $Line, $unknown)) {
if (isset($unknown[1]))
$UnkVar = $unknown[1];
if (! (empty($UnkVar))) {
@error_log("[FastTemplate] Warning: no value found for variable: $UnkVar ", 0);
}
}
}
// end show_unknowns()
// ************************************************************
// This routine get's called by parse() and does the actual
// {VAR} to VALUE conversion within the template.
function parse_template($template, $tpl_array) {
while (list ($key, $val) = each($tpl_array)) {
if (! (empty($key))) {
if (gettype($val) != "string") {
settype($val, "string");
}
// php4 doesn't like '{$' combinations.
$key = '{' . "$key" . '}';
// $template = preg_replace("$key","$val","$template");
$template = str_replace("$key", "$val", "$template");
}
}
if (! $this->STRICT) {
// Silently remove anything not already found
$template = preg_replace("{([A-Z0-9_]+)}", "", $template);
} else {
// Warn about unresolved template variables
if (preg_match("({[A-Z0-9_]+})", $template)) {
$unknown = preg_split("/\n/", $template);
while (list ($Element, $Line) = each($unknown)) {
$UnkVar = $Line;
if (! (empty($UnkVar))) {
$this->show_unknowns($UnkVar);
}
}
}
}
return $template;
}
// end parse_template();
// ************************************************************
// The meat of the whole class. The magic happens here.
function parse($ReturnVar, $FileTags) {
$append = false;
$this->LAST = $ReturnVar;
$this->HANDLE[$ReturnVar] = 1;
if (gettype($FileTags) == "array") {
unset($this->$ReturnVar); // Clear any previous data
while (list ($key, $val) = each($FileTags)) {
if ((! isset($this->$val)) || (empty($this->$val))) {
$this->LOADED["$val"] = 1;
if (isset($this->DYNAMIC["$val"])) {
$this->parse_dynamic($val, $ReturnVar);
} else {
$fileName = $this->FILELIST[$val];
$this->$val = $this->get_template($fileName);
}
}
// Array context implies overwrite
$this->$ReturnVar = $this->parse_template($this->$val, $this->PARSEVARS);
// For recursive calls.
$this->assign(array(
$ReturnVar => $this->$ReturnVar
));
}
} // end if FileTags is array()
else {
// FileTags is not an array
$val = $FileTags;
if ((substr($val, 0, 1)) == '.') {
// Append this template to a previous ReturnVar
$append = true;
$val = substr($val, 1);
}
if ((! isset($this->$val)) || (empty($this->$val))) {
$this->LOADED["$val"] = 1;
if (isset($this->DYNAMIC["$val"])) {
$this->parse_dynamic($val, $ReturnVar);
} else {
$fileName = $this->FILELIST[$val];
$this->$val = $this->get_template($fileName);
}
}
if ($append) {
$this->$ReturnVar .= $this->parse_template($this->$val, $this->PARSEVARS);
} else {
$this->$ReturnVar = $this->parse_template($this->$val, $this->PARSEVARS);
}
// For recursive calls.
$this->assign(array(
$ReturnVar => $this->$ReturnVar
));
}
return;
}
// End parse()
// ************************************************************
function FastPrint($template = "") {
if (empty($template)) {
$template = $this->LAST;
}
if ((! (isset($this->$template))) || (empty($this->$template))) {
$this->error("Nothing parsed, nothing printed", 0);
return;
} else {
print $this->$template;
}
return;
}
// ************************************************************
function fetch($template = "") {
if (empty($template))
$template = $this->LAST;
if ((! (isset($this->$template))) || (empty($this->$template))) {
$this->error("Nothing parsed, nothing printed", 0);
return "";
}
return ($this->$template);
}
// ************************************************************
function define_dynamic($Macro, $ParentName) {
// A dynamic block lives inside another template file.
// It will be stripped from the template when parsed
// and replaced with the {$Tag}.
$this->DYNAMIC["$Macro"] = $ParentName;
return true;
}
// ************************************************************
function parse_dynamic($Macro, $MacroName) {
// The file must already be in memory.
$ParentTag = $this->DYNAMIC["$Macro"];
if ((! $this->$ParentTag) or (empty($this->$ParentTag))) {
$fileName = $this->FILELIST[$ParentTag];
$this->$ParentTag = $this->get_template($fileName);
$this->LOADED[$ParentTag] = 1;
}
if ($this->$ParentTag) {
$template = $this->$ParentTag;
$DataArray = split("\n", $template);
$newMacro = "";
$newParent = "";
$outside = true;
$start = false;
$end = false;
while (list ($lineNum, $lineData) = each($DataArray)) {
$lineTest = trim($lineData);
if ("<!-- BEGIN DYNAMIC BLOCK: $Macro -->" == "$lineTest") {
$start = true;
$end = false;
$outside = false;
}
if ("<!-- END DYNAMIC BLOCK: $Macro -->" == "$lineTest") {
$start = false;
$end = true;
$outside = true;
}
if ((! $outside) and (! $start) and (! $end)) {
$newMacro .= "$lineData\n"; // Restore linebreaks
}
if (($outside) and (! $start) and (! $end)) {
$newParent .= "$lineData\n"; // Restore linebreaks
}
if ($end) {
$newParent .= '{' . "$MacroName}\n";
}
// Next line please
if ($end) {
$end = false;
}
if ($start) {
$start = false;
}
} // end While
$this->$Macro = $newMacro;
$this->$ParentTag = $newParent;
return true;
} // $ParentTag NOT loaded - MAJOR oopsie
else {
@error_log("ParentTag: [$ParentTag] not loaded!", 0);
$this->error("ParentTag: [$ParentTag] not loaded!", 0);
}
return false;
}
// ************************************************************
// Strips a DYNAMIC BLOCK from a template.
function clear_dynamic($Macro = "") {
if (empty($Macro)) {
return false;
}
// The file must already be in memory.
$ParentTag = $this->DYNAMIC["$Macro"];
if ((! $this->$ParentTag) or (empty($this->$ParentTag))) {
$fileName = $this->FILELIST[$ParentTag];
$this->$ParentTag = $this->get_template($fileName);
$this->LOADED[$ParentTag] = 1;
}
if ($this->$ParentTag) {
$template = $this->$ParentTag;
$DataArray = split("\n", $template);
$newParent = "";
$outside = true;
$start = false;
$end = false;
while (list ($lineNum, $lineData) = each($DataArray)) {
$lineTest = trim($lineData);
if ("<!-- BEGIN DYNAMIC BLOCK: $Macro -->" == "$lineTest") {
$start = true;
$end = false;
$outside = false;
}
if ("<!-- END DYNAMIC BLOCK: $Macro -->" == "$lineTest") {
$start = false;
$end = true;
$outside = true;
}
if (($outside) and (! $start) and (! $end)) {
$newParent .= "$lineData\n"; // Restore linebreaks
}
// Next line please
if ($end) {
$end = false;
}
if ($start) {
$start = false;
}
} // end While
$this->$ParentTag = $newParent;
return true;
} // $ParentTag NOT loaded - MAJOR oopsie
else {
@error_log("ParentTag: [$ParentTag] not loaded!", 0);
$this->error("ParentTag: [$ParentTag] not loaded!", 0);
}
return false;
}
// ************************************************************
function define($fileList) {
while (list ($FileTag, $FileName) = each($fileList)) {
$this->FILELIST[$FileTag] = $FileName;
}
return true;
}
// ************************************************************
function clear_parse($ReturnVar = "") {
$this->clear($ReturnVar);
}
// ************************************************************
function clear($ReturnVar = "") {
// Clears out hash created by call to parse()
if (! empty($ReturnVar)) {
if ((gettype($ReturnVar)) != "array") {
unset($this->$ReturnVar);
return;
} else {
while (list ($key, $val) = each($ReturnVar)) {
unset($this->$val);
}
return;
}
}
// Empty - clear all of them
while (list ($key, $val) = each($this->HANDLE)) {
$KEY = $key;
unset($this->$KEY);
}
return;
}
// end clear()
// ************************************************************
function clear_all() {
$this->clear();
$this->clear_assign();
$this->clear_define();
$this->clear_tpl();
return;
}
// end clear_all
// ************************************************************
function clear_tpl($fileHandle = "") {
if (empty($this->LOADED)) {
// Nothing loaded, nothing to clear
return true;
}
if (empty($fileHandle)) {
// Clear ALL fileHandles
while (list ($key, $val) = each($this->LOADED)) {
unset($this->$key);
}
unset($this->LOADED);
return true;
} else {
if ((gettype($fileHandle)) != "array") {
if ((isset($this->$fileHandle)) || (! empty($this->$fileHandle))) {
unset($this->LOADED[$fileHandle]);
unset($this->$fileHandle);
return true;
}
} else {
while (list ($Key, $Val) = each($fileHandle)) {
unset($this->LOADED[$Key]);
unset($this->$Key);
}
return true;
}
}
return false;
}
// end clear_tpl
// ************************************************************
function clear_define($FileTag = "") {
if (empty($FileTag)) {
unset($this->FILELIST);
return;
}
if ((gettype($Files)) != "array") {
unset($this->FILELIST[$FileTag]);
return;
} else {
while (list ($Tag, $Val) = each($FileTag)) {
unset($this->FILELIST[$Tag]);
}
return;
}
}
// ************************************************************
// Aliased function - used for compatibility with CGI::FastTemplate
// function clear_parse ()
// {
// $this->clear_assign();
// }
// ************************************************************
// Clears all variables set by assign()
function clear_assign() {
if (! (empty($this->PARSEVARS))) {
while (list ($Ref, $Val) = each($this->PARSEVARS)) {
unset($this->PARSEVARS["$Ref"]);
}
}
}
// ************************************************************
function clear_href($href) {
if (! empty($href)) {
if ((gettype($href)) != "array") {
unset($this->PARSEVARS[$href]);
return;
} else {
while (list ($Ref, $val) = each($href)) {
unset($this->PARSEVARS[$Ref]);
}
return;
}
} else {
// Empty - clear them all
$this->clear_assign();
}
return;
}
// ************************************************************
function assign($tpl_array, $trailer = "") {
if (gettype($tpl_array) == "array") {
while (list ($key, $val) = each($tpl_array)) {
if (! (empty($key))) {
// Empty values are allowed
// Empty Keys are NOT
$this->PARSEVARS["$key"] = $val;
}
}
} else {
// Empty values are allowed in non-array context now.
if (! empty($tpl_array)) {
$this->PARSEVARS["$tpl_array"] = $trailer;
}
}
}
// ************************************************************
// Return the value of an assigned variable.
// Christian Brandel cbrandel@gmx.de
function get_assigned($tpl_name = "") {
if (empty($tpl_name)) {
return false;
}
if (isset($this->PARSEVARS["$tpl_name"])) {
return ($this->PARSEVARS["$tpl_name"]);
} else {
return false;
}
}
// ************************************************************
function error($errorMsg, $die = 0) {
$this->ERROR = $errorMsg;
echo "ERROR: $this->ERROR <BR> \n";
if ($die == 1) {
exit();
}
return;
}
// end error()
// ************************************************************
// ************************************************************
} // End class.FastTemplate.php3
?>