<?

/*
        CVS Revision. 1.1.0
*/

class FastTemplate {

        var $FILELIST        =        array();        //        Holds the array of filehandles
                                                                        //        FILELIST[HANDLE] == "fileName"

        var $DYNAMIC        =        array();        //        Holds the array of dynamic
                                                                        //        blocks, and the fileHandles they
                                                                        //        live in.

        var $PARSEVARS        =        array();        //        Holds the array of Variable
                                                                        //        handles.
                                                                        //        PARSEVARS[HANDLE] == "value"

        var        $LOADED                =        array();        //        We only want to load a template
                                                                        //        once - when it's used.
                                                                        //        LOADED[FILEHANDLE] == 1 if loaded
                                                                        //        undefined if not loaded yet.

        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

        var $ERROR                =        "";                        //        Holds the last error message

        var $LAST                =        "";                        //        Holds the HANDLE to the last
                                                                        //        template parsed by parse()

        var $STRICT                =        true;                //        Strict template checking.
                                                                        //        Unresolved vars in templates will
                                                                        //        generate a warning when found.

//        ************************************************************

        function FastTemplate ($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.

        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 (ereg("({[A-Z0-9_]+})",$Line,$unknown))
                {
                        $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");
                                }

                                $template = ereg_replace("{$key}","$val","$template");
                                //$template = str_replace("{$key}","$val","$template");
                        }
                }

                if(!$this->STRICT)
                {
                        // Silently remove anything not already found

                        $template = ereg_replace("{([A-Z0-9_]+)}","",$template);
                }
                else
                {
                        // Warn about unresolved template variables
                        /*if (ereg("({[A-Z0-9_]+})",$template))
                        {
                                $unknown = 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

//Commented By Bimal on 14-04-2003
//        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

?>
