Location: PHPKode > scripts > PHP Cached Array > CachedArray.class.php
<?php
// Name: CachedArray.class.php
// Author: RReverser
// Description: Cached virtual array for PHP
// Created: 25.02.2010

// Iterator for CachedArray
class CachedArrayIterator implements Iterator
{
  protected $CArray, $CList;

  function __construct(& $CArray)
  {
    $this->CArray = & $CArray;
    $this->CList = $CArray->itemsList();
  }

  function current()
  {
    return $this->CArray[$this->key()];
  }

  function key()
  {
    return current($this->CList);
  }

  function next()
  {
    next($this->CList);
  }

  function rewind()
  {
    reset($this->CList);
  }

  function valid()
  {
    return (current($this->CList)!==FALSE);
  }

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

abstract class CachedArray implements ArrayAccess, Serializable, IteratorAggregate, Countable
{
  const sDELETED = - 2, sLISTED = - 1, sUNCHANGED = 0, sMODIFIED = 1, sNEW = 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);
  abstract function delItem($Index);

  function hasItem($Index)
  {
    return is_null($this->$Index);
  }

  function count()
  {
  }

  abstract function listItems();
  
  function __construct($AutoFlush = true)
  {
    $this->autoflush=$AutoFlush;
  }
  
  function __destruct()
  {
    if($this->autoflush) $this->flush();
  }

  // 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 ((!array_key_exists($Index, $this->cache)) || ($this->cache[$Index][0]==self::sLISTED))
      $this->cache[$Index] = array(self::sUNCHANGED, $this->getItem($Index));
    if ($this->cache[$Index][0] >= 0)
      return $this->cache[$Index][1];
  }

  function offsetSet($Index, $Value)
  {
    $this->cache[is_null($Index)?('new::'.$this->addcount++):$Index] = array((!is_null($Index)) && isset ($this->$Index)?self::sMODIFIED:self::sNEW, $Value);
  }

  function offsetExists($Index)
  {
    return (array_key_exists($Index, $this->cache) && $this->cache[$Index][0]!=self::sDELETED) || $this->hasItem($Index);
  }

  function offsetUnset($Index)
  {
    $this->cache[$Index] = array(self::sDELETED, NULL);
  }

  // Functions for serialization
  function serialize()
  {
    return serialize(array($this->cache, $this->addcount, $this->listed, $this->autoflush));
  }

  function unserialize($s_cache)
  {
    list($this->cache, $this->addcount, $this->listed, $this->autoflush) = unserialize($s_cache);
  }

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

  // Flushing procedure
  function flush()
  {
    foreach ($this->cache as $Index => $Data)
      switch ($Data[0])
      {
        case self::sDELETED:
          $this->delItem($Index);
          break;
        case self::sMODIFIED:
          $this->setItem($Index, $Data[1]);
          break;
        case self::sNEW:
          $newIndex = $this->addItem($Data[1]);
          unset ($this->cache[$Index]);
          $this->cache[$newIndex] = array(self::sUNCHANGED, $Data[1]);
          break;
      }
    $this->addcount = 0;
  }

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

  // Listing of real and unflushed items
  function itemsList()
  {
    if (!$this->listed)
    {
      $result = $this->listItems();
      foreach ($result as $InnerIndex => $Index)
        if (!array_key_exists($Index, $this->cache))
          $this->cache[$Index] = array(self::sLISTED, NULL);
        elseif ($this->cache[$Index][0] == self::sDELETED)
          unset ($result[$InnerIndex]);
        foreach ($this->cache as $Index => & $Data)
          if ($Data[0] == self::sNEW)
            $result[] = $Index;
          unset ($Data);
      $this->listed = true;
    }
    else
    {
      $result = array();
      foreach ($this->cache as $Index => & $Data)
        if ($Data[0] >= self::sLISTED)
          $result[] = $Index;
        unset ($Data);
    }
    return $result;
  }

}

?>
Return current item: PHP Cached Array