view CacheTimeCheck.inc @ 68:4dfa3f6a2dc1

Modify CacheTimeCheck to have a common parent, and two different implementations for script caches and file caches. Support for linkedcaches.
author Tom Fredrik "BFG" Klaussen <bfg@blenning.no>
date Thu, 11 Oct 2012 23:16:53 +0200
parents 7b87ec8b0842
children dd4ddedca4c5
line wrap: on
line source

<?php
$baseDir = dirname(__FILE__);

include_once 'Logger.inc';
include_once 'common-functions.inc';
$cache = ScriptIncludeCache::instance(__FILE__);
$cache->cache_time("${baseDir}/Logger.inc");
$cache->cache_time("${baseDir}/common-functions.inc");

class FileCacheSet {
  private $newest = 0;
  private $files = array();
  private $parentCaches = array();

  protected function __construct($parent = null) {
    if ($parent) {
      $this->addParent($parent);
    }
  }

  protected function addParent($parent)
  {
    array_push($this->parentCaches, $parent);
  }

  /**
   * List a set of files which contributes to this pages cacheset.
   *
   * @param $humanReadable If the timestamp should be humand readable.
   *
   * @return an associative array of file, and timestamp
   */
  function cacheSet($humanReadable = False)
  {
    $retVal = array();
    foreach ($this->parentCaches as $parent) {
      $retVal = array_merge($retVal, $parent->cacheSet($humanReadable));
    }
    foreach($this->files as $file) {
      $mtime = filemtime($file);
      if ($humanReadable)
	$mtime = gmdate('D, d M Y H:i:s', $mtime) . ' GMT';

      $retVal[$file] = $mtime;
    }
    return $retVal;
  }

  /**
   * Include a file in the cacheset
   *
   * @param $path the path of the file
   */
  function cache_time($path)
  {
    if (!file_exists($path)) {
      Logger::warn("${path} does not exist");
      errorPage("Resource is not available");
    }

    array_push($this->files, $path);
    $mtime = filemtime($path);
    if ($mtime > $this->newest) {
      $this->newest = $mtime;
    }
  }

  function getNewest()
  {
    $newest = 0;
    foreach ($this->parentCaches as $parent) {
      $newest = max($newest, $parent->getNewest());
    }
    $newest = max($newest, $this->newest);
    return $newest;
  }
}

class ScriptIncludeCache extends FileCacheSet
{
  private static $myInstance = 0;

  protected function __construct($filename = False)
  {
    parent::__construct();
    if ($filename)
      $this->cache_time($filename);
    $this->cache_time(__FILE__);
  }

  /**
   * Generates a singleton instance of this CacheTimeCheck
   *
   * @param $filename an optional file to include in the cacheset
   *
   * @return a CacheTimeCheck object
   */
  function instance($filename = False)
  {
    if (! self::$myInstance)
      self::$myInstance = new self($filename);
    elseif ($filename)
      self::$myInstance->cache_time($filename);
    return self::$myInstance;
  }

  /**
   * Convenience function to include a file, and add it to the cacheset.
   *
   * @param $path path of the file
   * @param $basedir a directory to prepend to the path
   */
  function includeOnce($path, $basedir = false)
  {
    if ($basedir)
      $path = $basedir . "/" . $path;
    $this->cache_time($path);
    include_once($path);
  }
}

/**
 * CacheTimeCheck provides a set of functions to enable generating a
 * correct time for the latest update for a given file.
 *
 * @author Tom Fredrik Blenning Klaussen
 */
class CacheTimeCheck extends FileCacheSet
{
  function __construct($filename = False)
  {
    parent::__construct();
    if ($filename)
      $this->cache_time($filename);
    $this->cache_time(__FILE__);
  }

  public function addParent($cache)
  {
    parent::addParent($cache);
  }

  /**
   * Checks if a HTTP_IF_MODIFIED_SINCE header is set, if this file is
   * newer, set a Last-Modified header, otherwise abort with an 304
   * status code
   */
  function CheckHttpModified()
  {
    if (DEBUG_LEVEL >= VERBOSITY_DEBUG)
      var_dump($_SERVER);

    $gmdate_mod = gmdate('D, d M Y H:i:s', $this->getNewest()) . ' GMT';

    if(array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)) {
      $HTTP_IF_MODIFIED_SINCE = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
      $if_modified_since = preg_replace('/;.*$/', '', $HTTP_IF_MODIFIED_SINCE);

      if (strtotime($if_modified_since) >= $this->getNewest()) {
	header("HTTP/1.0 304 Not Modified");
	exit;
      }
    }

    header("Last-Modified: $gmdate_mod");
  }

  /**
   * Convenience function to load a file, and add it to the cacheset
   *
   * @param $path path of the file
   * @return the contents of the file
   */
  function loadFile($path)
  {
    $this->cache_time($path);
    return loadFile($path);
  }
}
?>