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