Location: PHPKode > scripts > SPL and Iterators > spl-and-iterators/limit/package.oLimit.php
<?php
/**
 * class oLimit implements Iterator
 * @author johan <hide@address.com>
 * @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 <hide@address.com>
 * @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 <hide@address.com>
 * @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 <hide@address.com>
 * @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 <hide@address.com>
 * @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);
	}
}
?>
Return current item: SPL and Iterators