<?php

/*
Class cache:    27 November 2001

Author:            D Gough

Overview:        This is a class to cache the results of database queries in a simple XML format.
                Cache uses a mixture of the query, and the tables involved, to create filenames and directories in which the cached results are stored.

Details:        Cache has two main funcitons, search and create.
                - Search hunts through the cache directory, and if it finds a cached query, returns it for processing
                - Create executes a query, and builds an xml file from the data returned. It also calls the relevant output function.
                - Create should be called once a mysql query that does not exist in the cache has been called. The caller should have dealt with the mysql result before attempting to create the cache.

                Set the cache directory using $this->cache_dir in the search function below.
                DOM XML functions are used, and PHP needs to be compiled accordingly (http://www.php.net/manual/en/ref.domxml.php).
                The directory name used is md5(query_string) and the filename is md5(tables).

Usage:
                You do not need to cache all the queries you make, so only use cacheing when you really need to.
                For a query that you want to cache, first use search to check whether it already exists. If it does,
                then use that data. Otherwise, execute and do whatever you want to with your query, then call create
                so that a cached copy of your query is available. Eg;

                <?
                include ("cache_xml.php");
                $cache = new Cache;

                $query = "SELECT id, name FROM Users";
                $tables = "Users";

                // See if a cached copy exists, if not, process the query and create the cache after
                if($nodes = $cache->search( $query, $tables ) )    {

                    // A cached copy exists, so process it...
                    print_r($nodes);

                } else    {

                    // Retrieve the results and process them...
                    $result = mysql_query( $query, $link_id );

                    // etc

                    // Then create a cached copy of the query
                    $cache->create( $query, $tables, $result );

                } //endif
                ?>
*/

Class cache {

    
// Search the cache directory for a matching result set
    
function search$directory$filename ) {

        
// Setup some variables
        
$this->directory    "cache\\".md5($directory)."\\";
        
$this->filename        $this->directory.md5($filename).'.xml';
        
$this->cache_dir    "C:\\temp\\";

        
// Try to open the relevant directory, then the file, then get the result set.
        
if( !( $this->dir = @opendir"$this->directory) ) )    {

            
// Return false, the calling object should execute the query instead
            
return FALSE;

        } else    {

            
// The directory exists, so open it up (if it fails, return FALSE)
            
if( !( $this->dir = @opendir"$this->directory) ) )    {

                return 
FALSE;

            } else    {

                
// Open the file, and if it fails, return FALSE
                
if( !( $this->fp = @fopen"$this->filename","r" ) ) )    {

                    @
fclose$this->fp );
                    return 
FALSE;

                } else    {

                    
// Open the xml file, note this needs the full path, relative paths do not work
                    
$this->filename $this->cache_dir $this->filename;

                    
// Create a document object
                    
$dom xmldocfile$this->filename );

                    
// Get reference to root node
                    
$root $dom->root();

                    
// Get array of root node's children
                    
$nodes $root->children();

                    
// Iterate through node
                    
for ( $this->0$this->sizeof$nodes ); $this->x++ )    {

                        
// This is to correct whitespace (empty nodes)
                        
if ( $nodes[$this->x]->type == XML_ELEMENT_NODE )    {

                            
$thisNode $nodes[$this->x];

                            
// Get an array of this node's children
                            
$childNodes $thisNode->children();

                            
// Iterate through children
                            
for( $this->y=0$this->sizeof$childNodes ); $this->y++)    {

                                
// Check type again
                                
if ( $childNodes[$this->y]->type == XML_ELEMENT_NODE )    {

                                    
// Create an array of associative arrays to return
                                    // format => array[count][column_name] = value
                                    
$this->ret_array[$this->x][$childNodes[$this->y]->name] = $childNodes[$this->y]->content;

                                } 
//endif

                            
//endfor

                        
//endif

                    
//endfor

                
//endif

            
//endif

        
//endif

        // Return the cached array
        
return $this->ret_array;

    } 
//endfunc search

    
function create$directory$filename$result ) {

        
// Setup some variables
        
$this->result        $result;
        
$this->directory    "cache\\".md5($directory)."\\";
        
$this->filename        $this->directory.md5($filename).'.xml';

        
// Reset the result set
        
@mysql_data_seek($this->result0);

        
// Try to open the directory, if we succeed, something is wrong, so warn and continue
        
if( $this->dir = @opendir$this->directory ) )    {

            
$this->nocache 1;

        } else    {

            
// Create directory, if this fails, return FALSE
            
if( !( @mkdir "$this->directory",0777 ) ) )    {

                
$this->nocache 1;

            } else    {

                
// Open the directory, return FALSE if we can't
                
if( !( $this->dir = @opendir"$this->directory) ) )    {

                    
$this->nocache 1;

                } else    {

                    
// Create file, return FALSE if we can't
                    
if( !( $this->create_xml = @fopen"$this->filename","w+" ) ) )    {

                        
$this->nocache 1;

                    } else    {

                        
// Write contents to file, return FALSE is this fails
                        
fwrite$this->create_xml,"<?xml version=\"1.0\"?>\r\n<table>\r\n" );

                        
// Now process the query and create the xml feed
                        
while( $this->row = @mysql_fetch_array$this->result ) )    {

                            
// Create the xml file
                            
@fwrite$this->create_xml,"<element>\r\n" );

                            for( 
$this->0$value each$this->row ); $this->i++ )    {

                                if( 
$this->i%)    {
                                    
fwrite$this->create_xml,"<$value[0]>$value[1]</$value[0]>\r\n" );
                                } 
//endif

                            
//endfor

                            
@fwrite$this->create_xml,"</element>\r\n" );

                        } 
//endwhile

                        
@fwrite$this->create_xml,"</table>" );

                        
// Tidy up and return
                        
if( !( fclose$this->create_xml ) ) )    {

                            
$this->nocache 1;

                        } 
//endif

                    
//endif

                
//endif

            
//endif

        
//endif

        // If the cacheing failed, return FALSE
        
if( $this->nocache ) {

            return 
FALSE;

        } else {

            return 
TRUE;

        }

    } 
//endfunc create

//endclass cache
?>