#native_company# #native_desc#
#native_cta#

Cache and Include extension for PHPLIB Templates

By Tom Anderson
on July 16, 2001

Version: 1.3

Type: Class

Category: HTML

License: GNU General Public License

Description: This is an extention of the phplib class template and implements:

caching of pages – store pages for X seconds before re-running the php to build the page

allow of includes for template vars – this is most useful for sites migrating to phplib templates from embedded php as it allows both .ihtml and .inc files to work together in templates.

<?php
/**
* This object implements caching and includes
* of files instead of just reading them in.  This
* is useful for moving an existing site to phplib
* templates from embedded code and for easily
* speeding up sites by caching dynamic pages.
*
* THIS SCRIPT REQUIRES template.inc FROM phplib.
*
* Use:
* // Execute any php in index.php
* // No php will be executed in template.ihtml
* $t = new ta_template;
* if ($t -> set_cache("mysite.index")) exit();
* $t -> set_file("main", "index.php", TRUE);
* $t -> set_file("other", "template.ihtml");
*
* $t -> parse("body", "other");
* $t -> pparse("output", "main");
*
* To set the refresh time or path to some other value, use
* if ($t -> set_cache(array(
* 	'name' => 'mysite.index',
* 	'timeout' => 86400,
*	'path' => '/tmp/subdir'
* ))) exit();
*
* timeout and path are both optional so you can use the array
* call to set_cache with just name and timeout if you'd like.
*
* This will set the cache name as mysite.index and echo out
* the cache and return true if it has been refreshed within
* the default timeout period.  If false is returned from
* set_cache then a new cache file will be written and the
* script continues by including index.php
* into the template var 'main' and loads template.ihtml
* into the template var 'other'.  PHP code in index.php will
* be executed, but PHP code in template.ihtml will show up
* as code in the final output.
*
* Limitations of this script:  This script depends on $template->pparse()
* If you echo out anything in your script before calling pparse at the
* end of your script, this script may not work for you.
*
* Make sure to check the SECURITY NOTE: below.
*
* The latest version of this file can be found at
* http://db.etree.org/wddx/ta_template.phps
*
* Copyright 2000-2001 (c) Tom Anderson

*
* @version ta_template.php 1.3 2001/07/16
* @author Tom Anderson <[email protected]>
*
*/

class ta_Template extends Template {
  var $classname = "ta_Template";

  /* An array used to include files into template vars using output buffering */
  var $bufferedFiles;

  /* for caching pages */
  var $refreshCache = false;
  var $cacheName = '';
  // The $cachePath must be writable by the web user
  var $cachePath = '/tmp/cache/'; ## include trailing /

  /* default = 15 min */
  var $cacheTimeout = 900;

  ## This is the parameter to any ob_start function within this object
  /* Use gzip compression on cached files */
  var $output_callback = 'ob_gzhandler';

  /**
   * string pparse(string target, string handle, boolean append);
   * Override the ancestor function so we can save the parse result
   */
  function pparse($target, $handle, $append = false)
  {
    $str = $this->parse($target, $handle, $append);

    // For caching
    if ($this->refreshCache) {
        @unlink($this->cachePath . $this->cacheName);
        ## Pages are saved as non-gzip for browsers that can't handle it
        error_log($str, 3, $this->cachePath . $this->cacheName);
    }

    print $str;
    return false;
  }

    /**
     * boolean set_cache ( array or string )
     *
     * Parameter:  array or cache file name
     *
     * set_cache(array("name" => "cache file name",
     *       "path" => "cache file path",
     *       "timeout" => seconds before refresh));
     *
     * or set_cache("cache file name");
     */

    function set_cache($cacheParms)
    {
      if (is_string($cacheParms)) {
        $this->cacheName = $cacheParms;
      } else {
        // Set name and the path to the cached file
        $this->cacheName = $cacheParms['name'];
        if ($cacheParms['path']) $this->cachePath = $cacheParms['path'];
        // Set timeout to 15 min. if not specified
        if ($cacheParms['timeout']) $this->cacheTimeout = $cacheParms['timeout'];

      }

      // Get the last modified time for the file
      // FYI: (lstat[9] = FILE_LASTUPDATE)
      $fileProps = lstat($this->cachePath . $this->cacheName);

      // Set the refresh cache to true if time delta is too big
      if ($this -> refreshCache = ((time() - $fileProps[9]) > $this->cacheTimeout)) return false;

      // Use the cached file and use output buffering
      @ob_start($this->output_callback);
      ## SECURITY NOTE:
      ## Using include here is not as safe as reading the file in but works
      ## well if you can trust the cached page.
      //include ($this->cachePath . $this->cacheName);
      ## Uncomment the line above and comment the line below for
      ## less security but possibly faster execution
      echo implode('', @file($this->cachePath . $this->cacheName));
      return true;
    }

	/**
	 * public: boolean set_file(array $filelist)
	 * filelist: array of handle, filename pairs.
	 *
	 * public: set_file(string $handle, string $filename)
	 * handle: handle for a filename,
	 * filename: name of template file
	 */
  function set_file($handle, $filename = '', $bufferOutput = false)
  {
    if (!is_array($handle)) {
      if (!$filename) {
        $this->halt("set_file: For handle $handle filename is empty.");
        return false;
      }
      $this->file[$handle] = $this->filename($filename);
      // Set buffer flag
      $this->bufferedFiles[$this->file[$handle]] = $bufferOutput;

    } else {
		foreach ($handle as $templatevar => $templatefile) {
        $this->file[$templatevar] = $this->filename($templatefile);
        // Set buffer flag
        $this->bufferedFiles[$this->file[$templatevar]] = $bufferOutput;
      }
    }
    return true;
  }

  /**
   * private:  boolen isBuffered(string $handle)
   * handle:   a file defined by handle
   */
  function isBuffered($handle)
  {
      return $this->bufferedFiles[$handle];
  }

  /* private: boolean loadfile(string $handle)
   * handle:  load file defined by handle, if it is not loaded yet.
   *
   * This overrides the function in template.inc
   */
  function loadfile($handle)
  {
    if ($this->varkeys[$handle] and !empty($this->varvals[$handle])) return true;

    if (!isset($this->file[$handle])) {
      $this->halt("loadfile: $handle is not a valid handle.");
      return false;
    }
    $filename = $this->file[$handle];

    // Check for buffer for this handle.  If buffered, use include and capture result into $str
    @ob_start($this->output_callback);
    if ($this->isBuffered($filename)) {
		include ($filename);
		$str = ob_get_contents();
		ob_end_clean();
    } else {
      $str = implode('', @file($filename));
    }
    if (empty($str)) {
      $this->halt("loadfile: While loading $handle, $filename does not exist or is empty.");
      return false;
    }

    $this->set_var($handle, $str);

    return true;
  }

}
/**
 * Below is a complete script for testing this.  index.ihtml must reside in the
 * ../ihtml directory
$t = new ta_template('../ihtml');
if ($t -> set_cache('cache.name')) exit();
$t -> set_file('body', 'index.ihtml');
$t -> pparse('output', 'body');
echo 'This page is not cached';
*/
?>