<?php 
/** 
 * class oLimit implements Iterator 
 * @author johan <[email protected]> 
 * @version 20061205 
 */ 
abstract class oLimit implements Iterator { 
 
    /** 
     * Number of items to retrieve 
     * 
     * @var integer 
     */ 
    protected $iCount; 
 
    /** 
     * Starting offset 
     * 
     * @var integer 
     */ 
    protected $iOffset; 
 
    /** 
     * Total number of items for the request 
     * 
     * @var unknown_type 
     */ 
    protected $iMax; 
 
    /** 
     * Current internal position 
     * @var integer 
     */ 
    protected $iPos = 0; 
 
    /** 
     * Exception messages 
     * 
     */ 
    const ERROR_COUNT_EMPTY = 'iCount cannot be equal to 0'; 
    const ERROR_NO_INTEGER = 'iCount and iOffset parameters must be integer'; 
    const ERROR_NEGATIVE = 'iOffset cannot be negative'; 
 
    /** 
     * Constructor 
     * set some parameters 
     * 
     * @param integer $iOffset 
     * @param integer $iCount 
     */ 
    protected function __construct ($iOffset = 0, $iCount = -1) { 
        if (!is_int ($iOffset) || !is_int ($iCount)) { 
            throw new Exception (self::ERROR_NO_INTEGER); 
        } 
        if ($iOffset < 0) { 
            throw new Exception (self::ERROR_NEGATIVE); 
        } 
        if ($iCount === 0) { 
            throw new Exception (self::ERROR_COUNT_EMPTY); 
        } 
        $this -> iOffset = $iOffset; 
        $this -> iCount = $iCount; 
        $this -> iMax = $this -> countMax (); 
    } 
 
    /** 
     * Iterator method 
     * Moves the internal cursor to the next position 
     * 
     */ 
    public function next () { 
        $this -> iPos ++; 
    } 
 
    /** 
     * Iterator method 
     * Checks the validity of the current position 
     * If iCount === -1, then we go up to the end of the request (total number of items iMax) 
     * If not, we check if the current position iPos is equal or greater than the number of items to retrieve (iCount) 
     * 
     * @return boolean 
     */ 
    public function valid () { 
        if (($this -> iOffset + $this -> iPos) > $this -> iMax) { 
            return false; 
        } 
        if ($this -> iCount > -1 && $this -> iPos >= $this -> iCount) { 
            return false; 
        } 
        return true; 
    } 
 
    /** 
     * Returns the current internal position 
     * 
     * @return integer 
     */ 
    public function getInternalPos () { 
        return $this -> iPos; 
    } 
 
    /** 
     * Returns the current request position 
     * 
     * @return integer 
     */ 
    public function getExternalPos () { 
        return $this -> iPos + $this -> iOffset; 
    } 
 
    /** 
     * Returns the total number of items in the request 
     * 
     * @return integer 
     */ 
    public function getExternalCount () { 
        return $this -> iMax + 1; 
    } 
 
    abstract protected function countMax (); 
} 
 
/** 
 * class mysqlLimit extends oLimit 
 * @author johan <[email protected]> 
 * @version 20061205 
 */ 
class mysqlLimit extends oLimit { 
 
    /** 
     * request resource 
     * 
     * @var mysql result resource (comes from mysql_query) 
     */ 
    private $rRes; 
 
    /** 
     * Exception messages 
     * 
     */ 
    const ERROR_NO_RESOURCE = 'rRes must be a valid mysql resource'; 
 
    /** 
     * Constructor 
     * Sets some parameters, and set the current position via data_seek 
     * 
     * @param mysql result resource $rRes 
     * @param integer $iOffset 
     * @param integer $iCount 
     */ 
    public function __construct ($rRes, $iOffset = 0, $iCount = -1) { 
        if (!is_resource ($rRes) || 'mysql result' !== get_resource_type ($rRes)) { 
            throw new Exception (self::ERROR_NO_RESOURCE); 
        } 
        $this -> rRes = $rRes; 
        parent::__construct ($iOffset, $iCount); 
        mysql_data_seek ($this -> rRes, $this -> iOffset + $this -> iPos); 
    } 
 
    /** 
     * Returns the current result array at the current position 
     * 
     * @return array 
     */ 
    public function current () { 
        return mysql_fetch_assoc ($this -> rRes); 
    } 
 
    /** 
     * Checks validity of the current position 
     * 
     * @return boolean 
     */ 
    public function valid () { 
        return parent::valid (); 
    } 
 
    /** 
     * Reset the resource result to the starting offset 
     * 
     */ 
    public function rewind () { 
        mysql_data_seek ($this -> rRes, $this -> iOffset); 
    } 
 
    /** 
     * Do not know what do return here 
     * 
     * @return void 
     */ 
    public function key () { 
        return false; 
        //return mysql_fetch_assoc ($this -> rRes); 
    } 
 
    /** 
     * Returns the total number of items of the query 
     * 
     * @return integer 
     */ 
    protected function countMax () { 
        return mysql_num_rows ($this -> rRes) - 1; 
    } 
} 
 
/** 
 * class mssqlLimit extends oLimit 
 * see mysqlLimit for documentation 
 * @author johan <[email protected]> 
 * @version 20061205 
 */ 
class mssqlLimit extends oLimit { 
 
    private $rRes; 
 
    const ERROR_NO_RESOURCE = 'rRes must be a valid mssql resource'; 
 
    public function __construct ($rRes, $iOffset = 0, $iCount = -1) { 
        if (!is_int ($rRes) && (!is_resource ($rRes) || 'mssql result' !== get_resource_type ($rRes))) { 
            throw new Exception (self::ERROR_NO_RESOURCE); 
        } 
        $this -> rRes = $rRes; 
        parent::__construct ($iOffset, $iCount); 
        mssql_data_seek ($this -> rRes, $this -> iOffset + $this -> iPos); 
    } 
 
    public function current () { 
        return mssql_fetch_assoc($this -> rRes); 
    } 
 
    public function valid () { 
        return parent::valid (); 
    } 
 
    public function rewind () { 
        mssql_data_seek ($this -> rRes, $this -> iOffset); 
    } 
 
    public function key () { 
        return false; 
        //return mssql_fetch_assoc ($this -> rRes); 
    } 
 
    protected function countMax () { 
        return mssql_num_rows ($this -> rRes) - 1; 
    } 
} 
 
/** 
 * class arrayLimit extends LimitIterator 
 * @author johan <[email protected]> 
 * @version 20061205 
 */ 
class arrayLimit extends LimitIterator { 
 
    /** 
     * Exception messages 
     * 
     */ 
    const ERROR_NO_ARRAY = 'aRes must be an array'; 
 
    /** 
     * Constructor 
     * Sets some parameters and get LimitIterator constructor 
     * 
     * @param array $aRes 
     * @param integer $iOffset 
     * @param integer $iCount 
     */ 
    public function __construct ($aRes, $iOffset = 0, $iCount = -1) { 
        if (!is_array ($aRes)) { 
            throw new Exception (self::ERROR_NO_ARRAY); 
        } 
        $aIt = new ArrayIterator ($aRes); 
        parent::__construct ($aIt, $iOffset, $iCount); 
        $this -> rewind (); 
    } 
} 
 
/** 
 * class LimitFactory 
 * factory for the oLimit package (optional) 
 * @author johan <[email protected]> 
 * @version 20061205 
 */ 
class LimitFactory { 
 
    /** 
     * Array of implemented oLimit classes 
     * 
     * @var array 
     */ 
    private static $aTypes = array ( 
        'MYSQL' => 'mysqlLimit', 
        'MSSQL' => 'mssqlLimit', 
        'ARRAY' => 'arrayLimit' 
    ); 
 
    /** 
     * Exception messages 
     * 
     */ 
    const ERROR_NO_VALID_TYPE = '{__TYPE__} is not a valid type'; 
    const ERROR_CLASS_NOT_FOUND = 'class {__CLASS__} has not been found'; 
 
    /** 
     * Factory : get the correct object given an implemented oLimit class 
     * 
     * @param string $sType 
     * @param mixed $mRes 
     * @param integer $iOffset 
     * @param integer $iCount 
     * @return object 
     */ 
    public static function factory ($sType, $mRes, $iOffset = 0, $iCount = -1) { 
        if (!array_key_exists ($sType, self::$aTypes)) { 
            throw new Exception (str_replace ('{__TYPE__}', $sType, self::ERROR_NO_VALID_TYPE)); 
        } 
        if (!class_exists (self::$aTypes[$sType])) { 
            throw new Exception (str_replace ('{__CLASS__}', self::$aTypes[$sType], self::ERROR_CLASS_NOT_FOUND)); 
        } 
        return new self::$aTypes[$sType] ($mRes, $iOffset, $iCount); 
    } 
} 
?>
 
 |