<?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 ?>