Login   Register  
PHP Classes
elePHPant
Icontem

File: CachedArray.class.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Ingvar Stepanyan  >  Cached Virtual Array  >  CachedArray.class.php  >  Download  
File: CachedArray.class.php
Role: Class source
Content type: text/plain
Description: Class file
Class: Cached Virtual Array
Base class for implementing persistent arrays
Author: By
Last change: - Speed increased
- Some fixes to code (now can work after flush, better iterator)
- Better readability of code
- Now only getItem, setItem, addItem are abstract; other methods use them by default but can be overridden
- Countable is no more part of the class
Date: 3 years ago
Size: 5,602 bytes
 

Contents

Class file image Download
<?php
// Name: CachedArray.class.php
// Author: RReverser
// Description: Cached virtual array for PHP
// Version: 1.1
// Created: 27.03.2011

class CachedArrayIterator implements Iterator
{
    private 
$indexArray$cachedArray;
    
    function 
__construct(CachedArray $ca)
    {
        
$this->cachedArray $ca;
        
$this->indexArray $ca->items();
    }
    
    function 
current() { return $this->valid() ? $this->cachedArray[$this->key()] : NULL; }
    function 
key() { return current($this->indexArray); }
    function 
next() { next($this->indexArray); return $this->current(); }
    function 
rewind() { reset($this->indexArray); return $this->current(); }
    function 
valid() { return key($this->indexArray) !== NULL; }
}

// Cached array class - implements full array-style or object-style access to elements

abstract class CachedArray implements ArrayAccessSerializableIteratorAggregate
{
    const 
sDELETED = -2sEXISTS = -1sUNCHANGED 0sMODIFIED 1sNEW 2;

    protected 
$cache = array(), $addCount 0$listed FALSE$autoFlush TRUE;

    
// Your functions (for overriding)
    
abstract function getItem($index);
    abstract function 
setItem($index$value);
    abstract function 
addItem($value NULL);
    function 
delItem($index) { $this->setItem($indexNULL); }
    function 
hasItem($index) { return $this[$index] !== NULL; }
    function 
getList() { return array(); }

    function 
__construct($autoFlush TRUE) { $this->autoFlush $autoFlush; }
    function 
__destruct() { $this->autoFlush $this->flush() : FALSE; }

    
// Functions for object-style access
    
function __get($index) { return $this[$index]; }
    function 
__set($index$value) { $this[$index] = $value; }
    function 
__isset($index) { return isset($this[$index]); }
    function 
__unset($index) { unset($this[$index]); }

    
// Functions for array-style access
    
function offsetGet($index)
    {
        if (!isset(
$this->cache[$index]) || $this->cache[$index][0] == self::sEXISTS)
        {
            
$this->cache[$index] = array(self::sUNCHANGED$this->getItem($index));
        }

        return 
$this->cache[$index][0] >= $this->cache[$index][1] : NULL;
    }

    function 
offsetSet($index$value)
    {
        if (
$index === NULL)
        {
            
$index 'new_' $this->addCount++;
            
$State self::sNEW;
        } else
        {
            
$State = isset($this[$index]) ? self::sMODIFIED self::sNEW;
        }

        
$this->cache[$index] = array($State$value);
    }

    function 
offsetExists($index)
    {
        if (isset(
$this->cache[$index]) && $this->cache[$index][0] != self::sDELETED)
        {
            return isset(
$this->cache[$index][1]);
        } else
        {
            
$exists $this->hasItem($index);
            
$this->cache[$index] = array($exists self::sEXISTS self::sUNCHANGEDNULL);
            return 
$exists;
        }
    }

    function 
offsetUnset($index)
    {
        
$this->cache[$index][0] = self::sDELETED;
    }

    
// Functions for serialization
    
function serialize() { return serialize(array($this->cache$this->addCount$this->listed$this->autoFlush)); }
    function 
unserialize($str) { list($this->cache$this->addCount$this->listed$this->autoFlush) = unserialize($str); }

    
// Returning iterator object
    
function getIterator() { return new CachedArrayIterator($this); }

    
// Flushing procedure
    
function flush()
    {
        
$movements = array();

        foreach (
$this->cache as $index => &$data)
        {
            switch (
$data[0])
            {
                case 
self::sDELETED:
                    
$this->delItem($index);
                    
$data = array(self::sUNCHANGEDNULL);
                    break;
                
                case 
self::sMODIFIED:
                    
$this->setItem($index$data[1]);
                    
$data[0] = self::sUNCHANGED;
                    break;
                
                case 
self::sNEW:
                    
$newIndex $this->addItem($data[1]);
                    
$movements[$index] = $newIndex;
                    break;
            }
        }

        foreach (
$movements as $from => $to)
        {
            
$this->cache[$to] = array(self::sUNCHANGED$this->cache[$from][1]);
            unset(
$this->cache[$from]);
        }

        
$this->addCount 0;
    }

    function 
drop()
    {
        
$this->cache = array();
        
$this->addCount 0;
        
$this->listed FALSE;
    }

    
// Listing of real and unflushed items
    
function items()
    {
        if (!
$this->listed)
        {
            
$result $this->getList();

            foreach (
$result as $innerIndex => $index)
            {
                if (!isset(
$this->cache[$index])) { $this->cache[$index] = array(self::sEXISTSNULL); }
                elseif (
$this->cache[$index][0] == self::sDELETED) { unset($result[$innerIndex]); }
            }
            
            foreach (
$this->cache as $index => $data)
            {
                if (
$data[0] == self::sNEW) { $result[] = $index; }
            }

            
$this->listed TRUE;
        }
        else
        {
            
$result = array();
            
            foreach (
$this->cache as $index => $data)
            {
                if (
$data[0] >= self::sEXISTS) { $result[] = $index; }
            }
        }
        
        return 
$result;
    }

}