Sources for file plugins/cache/file.php in version 4.0 Beta 1



Click on a comment to hide it. Click here to show all comments.

/**
 * Project:     
 * File:        
 *
 * Version:     
 * SVN Id:      $Id: file.php 5 2007-05-18 03:49:07Z bok $
 * SVN URL:     $HeadURL: http://svn.syd.wholesalebroadband.com.au/xnyo/trunk/plugins/cache/file.php
$
 * Authors:     Robert Amos <bok[at]odynia.org>
 *
 * Copyright (c) 2001-2007 Robert Amos <bok[at]odynia.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/

class XnyoCacheFile implements XnyoClassPlugin
{
    
// Plugin Information
    
public $_plugin_info = array
    (
        
'name' => 'Xnyo File Cache',
        
'description' => 'Stores cached copies of data for quick retrieval',
        
'action' => XNYO_PLUGIN_ACTION_RETURN
    
);

    
/**
     * Information Storage
    **/
    
private $fp;
    private 
$headers;
    private 
$xnyo;

    
/**
     * Constructor
    **/
    
public function __construct ()
    {
        
$this->xnyo $GLOBALS['xnyo_parent'];
    }

    
/**
     * Get Filename
    **/
    
private function get_file ()
    {
        
$file '';

        
// and the cache id if one is specified
        
if (!empty($this->xnyo->cache->id))
            
$file .= $this->xnyo->cache->id;

        
// otherwise, use the filename
        
else
            
$file .= dirname($_SERVER['SCRIPT_NAME']);

        return 
$file;
    }
    private function 
get_subdirs ()
    {
        
$dirs = array();

        
// store it inside the language folder
        
if (!empty($this->xnyo->session->language))
            
$dirs[] = $this->xnyo->session->language.DIRSEP;
        
        
// and if we're logged in
        
if (!empty($this->xnyo->user->username))
            
$dirs[] = $this->xnyo->user->username.DIRSEP;

        
// do we have a cache id with "groups"?
        
if (!empty($this->xnyo->cache->id))
        {
            
$d explode(':'$this->xnyo->cache->id);
            if (
count($d))
                
$dirs += $d;
        } else
        {
            
$d explode('/'substr($_SERVER['SCRIPT_NAME'], 01));
            if (
count($d))
                
$dirs += $d;
        }

        return 
$dirs;
    }

    
/**
     * Write a buffer to the cache file.
    **/
    
public function write ($buf)
    {
        
// before we go any further, we cannot cache something with a query string
        
if (empty($this->xnyo->cache->id) && !empty($_SERVER['QUERY_STRING']))
        {
            if (
XNYO_DEBUG$this->xnyo->d('Unable to cache page with a query string.');
            return 
false;
        }

        
// check to make sure we can write to our cache directory
        
if (!is_dir($this->xnyo->cache->location) || is_writable($this->xnyo->cache->location))
            throw new 
XnyoError('Cache directory <b>%s</b> does not exist or is not writable.',
$this->xnyo->cache->location);

        
// get where we're going to put it
        
$dirs $this->get_subdirs();
        
$file $this->get_file();

        
// start our location
        
$loc substr($this->xnyo->cache->location, -1) == DIRSEP $this->xnyo->cache->location :
$this->xnyo->cache->location.DIRSEP;

        
// check that we can write to each
        
foreach ($dirs as $d)
        {
            if (
is_dir($loc.$d))
            {
                
$loc .= $d.DIRSEP;
                if (!
is_writable($loc))
                    throw new 
XnyoError('Cache Subdirectory <b>%s</b> already exists but we cannot write to it.',
$loc);
                continue;
            }
            if (!
mkdir($loc.$d0700))
                throw new 
XnyoError('Unable to create Cache Subdirectory <b>%s</b>.'$loc.$d);
            
$loc .= $d.DIRSEP;
        }

        
// check to see if our filename already exists..
        
if (file_exists($loc.$file) && !is_writable($loc.$file))
            throw new 
XnyoError('Cache file <b>%s</b> already exists but we cannot write to it.',
$loc.$file);

        
// open a pointer and output the cache file
        
$fp fopen($loc.$file'w');

        if (!
$fp)
            throw new 
XnyoError('Unable to open file pointer on cache file <b>%s</b>.'$loc.$file);

        
// calculate expiration/idle times
        
if (!empty($this->xnyo->cache->expiration))
            
fputs($fp'expiration: '.$this->xnyo->cache->expiration."\n");
        elseif (
$this->xnyo->cache->lifetime != 0)
            
fputs($fp'expiration: '.(time() + $this->xnyo->cache->lifetime)."\n");

        if (!empty(
$this->xnyo->cache->idletime))
            
fputs($fp'idletime: '.$this->xnyo->cache->idletime."\n");
        
fputs($fp'created: '.time()."\n\n");

        
// output the page
        
fputs($fp$buf);
        
fclose($fp);

        
// make sure the access time is right
        
touch($loc.$file);

        
// generate Last-Modified headers to make caching nice
        
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');

        
//done
        
return true;
    }

    
/**
     * Is Page Cached?
    **/
    
public function is_cached ()
    {
        
// check the cache dirs
        
if (!is_dir($this->xnyo->cache->location) || !is_readable($this->xnyo->cache->location))
            throw new 
XnyoError('Cache directory <b>%s</b> does not exist or is not readable.',
$this->xnyo->cache->location);

        
// get our subdirs and file
        
$loc substr($this->xnyo->cache->location, -1) == DIRSEP $this->xnyo->cache->location :
$this->xnyo->cache->location.DIRSEP;
        
$loc .= join(DIRSEP$this->get_subdirs()).DIRSEP.$this->get_file();

        
// check to see if our cache file exists
        
if (!file_exists($loc))
            return 
false;

        
// make sure we can read it
        
if (!is_readable($loc) || is_dir($loc))
            throw new 
XnyoError('Cache file <b>%s</b> exists but we cannot read it (or its a directory).',
$loc);

        
// store the file access time before we go stuffing around with it
        
$fileatime fileatime($loc);

        
// are we caching a page? if so has the page changed?
        
if (empty($this->xnyo->cache->id) && filemtime($_SERVER['SCRIPT_FILENAME']) > filemtime($loc))
        {
            if (
XNYO_DEBUG$this->xnyo->d('Script newer than page, removing cache file <b>%s</b>'$loc);
            
unlink($loc);
            return 
false;
        }

        
// open file pointer
        
$fp fopen($loc'r');
        if (!
$fp)
            throw new 
XnyoError('Unable to open file pointer on cache file <b>%s</b>'$loc);

        
// read in headers
        
$h = array();
        while (
$l fgets($fp))
        {
            
// end of headers
            
if ($l == "\n" || $l == "\r\n")
                break;

            
// store header
            
$header explode(': 'chop($l));
            
$h[$header[0]] = $header[1];
        }

        
// have we passed the expiration date?
        
if (isset($h['expiration']) && time() > $h['expiration'])
        {
            
// yep, close the pointer and prepare to regen the file
            
fclose($fp);
            
unlink($loc);
            return 
false;
        }

        
// have we past the idle timeout?
        
if (isset($h['idletime']) && $fileatime > ($h['idletime'] + $h['created']))
        {
            
// yep regen
            
fclose($fp);
            
unlink($loc);
            return 
false;
        }
        
        
// store the fp and headers for later use
        
$this->fp $fp;
        
$this->headers $h;

        
// yep, we're cached!
        
return true;

    }
    
    
/**
     * Display the cache
    **/
    
public function display_cache ()
    {
        
// haven't run is_cache yet?
        
if ((!is_resource($this->fp) || !is_array($this->headers)) && !$this->is_cached())
            throw new 
XnyoError('Trying to call display cache when page not cached.');

        
// support for the If-Modified-Since header
        
if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE']))
        {
            
$mod strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
            if (
$mod != -&& $mod >= $h['created'])
            {
                
header('HTTP/1.0 304 Not Modified');
                exit();
            }
        }

        
// send the Last-Modified header
        
header('Last-Modified: '.gmdate('D, d M Y H:i:s'$h['created']).' GMT');

        
// output the rest of the file
        
fpassthru($fp);

        
// close it and done
        
fclose($fp);

        return 
true;
    }
    
    
/**
     * Clear the cache
    **/
    
public function clear_cache ()
    {
        
// check the cache dirs
        
if (!is_dir($this->xnyo->cache->location) || !is_readable($this->xnyo->cache->location))
            throw new 
XnyoError('Cache directory <b>%s</b> does not exist or is not readable.',
$this->xnyo->cache->location);

        
// get our subdirs and file
        
$loc substr($this->xnyo->cache->location, -1) == DIRSEP $this->xnyo->cache->location :
$this->xnyo->cache->location.DIRSEP;
        
$loc .= join(DIRSEP$this->get_subdirs()).DIRSEP.$this->get_file();

        
// check to see if our cache file exists
        
if (!file_exists($loc))
            return 
false;

        return 
unlink($loc);
    }
}

Website is Copyright © Odynia.org 2000-2005 - Xnyo is released under a BSD license.