<? # # Read, understand and follow: # http://www.massassi.com/php/articles/template_engines/ # # "In short, the point of template engines should be to separate your business # logic from your presentation logic, not separate your PHP code from your # HTML code." Amen! # class Template { var $vars; /// Holds all the template variables /** * Constructor * * @param $file string the file name you want to load */ function Template($file = null) { $this->file = $file; } /** * Set a template variable. */ function set($name, $value) { if ( is_object($value) ) { if ( method_exists($value, 'fetch')) { $this->vars[$name] = $value->fetch(); } else { $this->vars[$name] = $value; } } else { $this->vars[$name] = $value; } } /** * Open, parse, and return the template file. * * @param $file string the template file name */ function fetch($file = null) { if(!$file) $file = $this->file; extract($this->vars); // Extract the vars to local namespace ob_start(); // Start output buffering include($file); // Include the file $contents = ob_get_contents(); // Get the contents of the buffer ob_end_clean(); // End buffering and discard return $contents; // Return the contents } } /** * An extension to Template that provides automatic caching of * template contents. */ class CachedTemplate extends Template { var $cache_id; var $expire; var $cached; /** * Constructor. * * @param $cache_id string unique cache identifier * @param $expire int number of seconds the cache will live */ function CachedTemplate($cache_id = null, $expire = 900) { $this->Template(); $this->cache_id = $cache_id ? 'cache/' . md5($cache_id) : $cache_id; $this->expire = $expire; } /** * Test to see whether the currently loaded cache_id has a valid * corrosponding cache file. */ function is_cached() { if($this->cached) return true; // Passed a cache_id? if(!$this->cache_id) return false; // Cache file exists? if(!file_exists($this->cache_id)) return false; // Can get the time of the file? if(!($mtime = filemtime($this->cache_id))) return false; // Cache expired? if(($mtime + $this->expire) < time()) { @unlink($this->cache_id); return false; } else { /** * Cache the results of this is_cached() call. Why? So * we don't have to double the overhead for each template. * If we didn't cache, it would be hitting the file system * twice as much (file_exists() & filemtime() [twice each]). */ $this->cached = true; return true; } } /** * This function returns a cached copy of a template (if it exists), * otherwise, it parses it as normal and caches the content. * * @param $file string the template file */ function fetch_cache($file) { if($this->is_cached()) { $fp = @fopen($this->cache_id, 'r'); $contents = fread($fp, filesize($this->cache_id)); fclose($fp); return $contents; } else { $contents = $this->fetch($file); // Write the cache if($fp = @fopen($this->cache_id, 'w')) { fwrite($fp, $contents); fclose($fp); } else { die('Unable to write cache.'); } return $contents; } } } # Pass by reference to us less memory class RefTemplate extends Template { function RefTemplate ($file=null) { $this->Template($file); } function set($name, &$value) { if ( is_object($value) ) { if ( method_exists($value, 'fetch')) { $this->vars[$name] = $value->fetch(); } else { $this->vars[$name] = $value; } } else { $this->vars[$name] = $value; } } function fetch($file = null) { if(!$file) $file = $this->file; extract($this->vars, EXTR_REFS); // REFERENCE vars in the local namespace ob_start(); // Start output buffering include($file); // Include the file $contents = ob_get_contents(); // Get the contents of the buffer ob_end_clean(); // End buffering and discard return $contents; // Return the contents } } ?>