<?php
/**
 * Results Iterator for RDO.
 *
 * TODO: implement ArrayAccess as well?
 *
 * $Horde: framework/RDO/RDO/Results.php,v 1.5.2.1 2005/10/18 11:01:23 jan Exp $
 *
 * @package RDO
 */
abstract class RDO_Results implements Iterator {

    protected $storage;
    protected $mapper;
    protected $mode;
    protected $criteria;
    protected $result;
    protected $current;
    protected $index;
    protected $eof;

    /**
     * Results constructor.
     *
     * @param RDO_Storage $storage
     * @param RDO_Mapper  $mapper    Mapping object this result set came from.
     * @param integer     $mode
     * @param mixed       $criteria  Description of query to run when results are requested.
     */
    public function __construct(RDO_Storage $storage, RDO_Mapper $mapper, $mode = RDO::FIND_ALL, $criteria = null)
    {
        $this->storage = $storage;
        $this->mapper = $mapper;
        $this->mode = $mode;
        $this->criteria = $criteria;
    }

    /**
     * Results destructor - release any resources.
     */
    public function __destruct()
    {
        if ($this->result) {
            $this->storage->free($this->result);
        }
    }

    /**
     * Must be defined by the concrete subclass.
     */
    public function rewind()
    {
        throw new RDO_Exception('RDO_Results::rewind() must be implemented by the concrete subclass.');
    }

    /**
     * Implementation of the current() method for iterator.
     *
     * @return mixed The current row, or null if no rows.
     */
    public function current()
    {
        if (is_null($this->result)) {
            $this->rewind();
        }
        return $this->current;
    }

    /**
     * Implementation of the key() method for iterator.
     *
     * @return mixed The current row number (starts at 0), or NULL if no rows
     */
    public function key()
    {
        if (is_null($this->result)) {
            $this->rewind();
        }
        return $this->index;
    }

    /**
     * Must be defined by the concrete subclass.
     *
     * @return mixed The next row, or null if no more rows.
     */
    public function next()
    {
        throw new RDO_Exception('RDO_Results::next() must be implemented by the concrete subclass.');
    }

    /**
     * Implementation of the valid() method for iterator
     *
     * @return boolean Whether the iteration is valid
     */
    public function valid()
    {
        if (is_null($this->result)) {
            $this->rewind();
        }
        return !$this->eof;
    }

}
