diff options
| author | wei <> | 2006-12-04 00:02:23 +0000 | 
|---|---|---|
| committer | wei <> | 2006-12-04 00:02:23 +0000 | 
| commit | 18ea316c553f7ccfc18b73f0c987de007f11b275 (patch) | |
| tree | b8fa0d14de75582b48c3e4d12050c84f07805920 /framework/Data/SqlMap/DataMapper | |
| parent | b69ca04f50ffd538239342f3bfd1e77ffc6156c0 (diff) | |
Fixed #469
Diffstat (limited to 'framework/Data/SqlMap/DataMapper')
| -rw-r--r-- | framework/Data/SqlMap/DataMapper/TLazyLoadList.php | 145 | ||||
| -rw-r--r-- | framework/Data/SqlMap/DataMapper/TPropertyAccess.php | 130 | ||||
| -rw-r--r-- | framework/Data/SqlMap/DataMapper/TSqlMapCache.php | 230 | ||||
| -rw-r--r-- | framework/Data/SqlMap/DataMapper/TSqlMapException.php | 99 | ||||
| -rw-r--r-- | framework/Data/SqlMap/DataMapper/TSqlMapPagedList.php | 158 | ||||
| -rw-r--r-- | framework/Data/SqlMap/DataMapper/TSqlMapTypeHandlerRegistry.php | 183 | ||||
| -rw-r--r-- | framework/Data/SqlMap/DataMapper/messages.txt | 66 | 
7 files changed, 1011 insertions, 0 deletions
diff --git a/framework/Data/SqlMap/DataMapper/TLazyLoadList.php b/framework/Data/SqlMap/DataMapper/TLazyLoadList.php new file mode 100644 index 00000000..770c217a --- /dev/null +++ b/framework/Data/SqlMap/DataMapper/TLazyLoadList.php @@ -0,0 +1,145 @@ +<?php
 +/**
 + * TLazyLoadList, TObjectProxy classes file.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @link http://www.pradosoft.com/
 + * @copyright Copyright © 2005-2007 PradoSoft
 + * @license http://www.pradosoft.com/license/
 + * @version $Id$
 + * @package System.Data.SqlMap.DataMapper
 + */
 +
 +/**
 + * TLazyLoadList executes mapped statements when the proxy collection is first accessed.
 + *
 + * @author Wei Zhuo <weizho[at]gmail[dot]com>
 + * @version $Id$
 + * @package System.Data.SqlMap.DataMapper
 + * @since 3.1
 + */
 +class TLazyLoadList
 +{
 +	private $_param;
 +	private $_target;
 +	private $_propertyName='';
 +	private $_statement='';
 +	private $_loaded=false;
 +	private $_innerList;
 +	private $_connection;
 +
 +	/**
 +	 * Create a new proxy list that will execute the mapped statement when any
 +	 * of the list's method are accessed for the first time.
 +	 * @param TMappedStatement statement to be executed to load the data.
 +	 * @param mixed parameter value for the statement.
 +	 * @param object result object that contains the lazy collection.
 +	 * @param string property of the result object to set the loaded collection.
 +	 */
 +	protected function __construct($mappedStatement, $param, $target, $propertyName)
 +	{
 +		$this->_param = $param;
 +		$this->_target = $target;
 +		$this->_statement = $mappedStatement;
 +		$this->_connection=$mappedStatement->getManager()->getDbConnection();
 +		$this->_propertyName = $propertyName;
 +	}
 +
 +	/**
 +	 * Create a new instance of a lazy collection.
 +	 * @param TMappedStatement statement to be executed to load the data.
 +	 * @param mixed parameter value for the statement.
 +	 * @param object result object that contains the lazy collection.
 +	 * @param string property of the result object to set the loaded collection.
 +	 * @return TObjectProxy proxied collection object.
 +	 */
 +	public static function newInstance($mappedStatement, $param, $target, $propertyName)
 +	{
 +		$handler = new self($mappedStatement, $param, $target, $propertyName);
 +		$statement = $mappedStatement->getStatement();
 +		$registry=$mappedStatement->getManager()->getTypeHandlers();
 +		$list = $statement->createInstanceOfListClass($registry);
 +		if(!is_object($list))
 +			throw new TSqlMapExecutionException('sqlmap_invalid_lazyload_list',$statement->getID());
 +		return new TObjectProxy($handler, $list);
 +	}
 +
 +	/**
 +	 * Relay the method call to the underlying collection.
 +	 * @param string method name.
 +	 * @param array method parameters.
 +	 */
 +	public function intercept($method, $arguments)
 +	{
 +		return call_user_func_array(array($this->_innerList, $method), $arguments);
 +	}
 +
 +	/**
 +	 * Load the data by executing the mapped statement.
 +	 */
 +	protected function fetchListData()
 +	{
 +		if($this->_loaded == false)
 +		{
 +			$this->_innerList = $this->_statement->executeQueryForList($this->_connection,$this->_param);
 +			$this->_loaded = true;
 +			//replace the target property with real list
 +			TPropertyAccess::set($this->_target, $this->_propertyName, $this->_innerList);
 +		}
 +	}
 +
 +	/**
 +	 * Try to fetch the data when any of the proxy collection method is called.
 +	 * @param string method name.
 +	 * @return boolean true if the underlying collection has the corresponding method name.
 +	 */
 +	public function hasMethod($method)
 +	{
 +		$this->fetchListData();
 +		if(is_object($this->_innerList))
 +			return in_array($method, get_class_methods($this->_innerList));
 +		return false;
 +	}
 +}
 +
 +/**
 + * TObjectProxy sets up a simple object that intercepts method calls to a
 + * particular object and relays the call to handler object.
 + *
 + * @author Wei Zhuo <weizho[at]gmail[dot]com>
 + * @version $Id$
 + * @package System.Data.SqlMap.DataMapper
 + * @since 3.1
 + */
 +class TObjectProxy
 +{
 +	private $_object;
 +	private $_handler;
 +
 +	/**
 +	 * @param object handler to method calls.
 +	 * @param object the object to by proxied.
 +	 */
 +	public function __construct($handler, $object)
 +	{
 +		$this->_handler = $handler;
 +		$this->_object = $object;
 +	}
 +
 +	/**
 +	 * Relay the method call to the handler object (if able to be handled), otherwise
 +	 * it calls the proxied object's method.
 +	 * @param string method name called
 +	 * @param array method arguments
 +	 * @return mixed method return value.
 +	 */
 +	public function __call($method,$params)
 +	{
 +		if($this->_handler->hasMethod($method))
 +			return $this->_handler->intercept($method, $params);
 +		else
 +			return call_user_func_array(array($this->_object, $method), $params);
 +	}
 +}
 +
 +?>
\ No newline at end of file diff --git a/framework/Data/SqlMap/DataMapper/TPropertyAccess.php b/framework/Data/SqlMap/DataMapper/TPropertyAccess.php new file mode 100644 index 00000000..fea94fa4 --- /dev/null +++ b/framework/Data/SqlMap/DataMapper/TPropertyAccess.php @@ -0,0 +1,130 @@ +<?php
 +
 +class TPropertyAccess
 +{
 +	private $_obj;
 +	private $_performance=false;
 +
 +	public function __construct($obj,$performance=false)
 +	{
 +		$this->_obj = $obj;
 +		$this->_performance=$performance;
 +	}
 +
 +	public function __get($name)
 +	{
 +		return self::get($this->_obj,$name,$this->_performance);
 +	}
 +
 +	public function __set($name,$value)
 +	{
 +		self::set($this->_obj,$name,$value,$this->_performance);
 +	}
 +
 +	/**
 +	 * Evaluates the data value at the specified field.
 +	 * - If the data is an array, then the field is treated as an array index
 +	 *   and the corresponding element value is returned;
 +	 * - If the data is a TMap or TList object, then the field is treated as a key
 +	 *   into the map or list, and the corresponding value is returned.
 +	 * - If the data is an object, the field is treated as a property or subproperty
 +	 *   defined with getter methods. For example, if the object has a method called
 +	 *   getMyValue(), then field 'MyValue' will retrive the result of this method call.
 +	 *   If getMyValue() returns an object which contains a method getMySubValue(),
 +	 *   then field 'MyValue.MySubValue' will return that method call result.
 +	 * @param mixed data containing the field value, can be an array, TMap, TList or object.
 +	 * @param mixed field value
 +	 * @return mixed value at the specified field
 +	 * @throw TInvalidDataValueException if field or data is invalid
 +	 */
 +	public static function get($object,$path)
 +	{
 +		if(!is_array($object) && !is_object($object))
 +			return $object;
 +		$properties = explode('.', $path);
 +		foreach($properties as $prop)
 +		{
 +			if(is_array($object) || $object instanceof ArrayAccess)
 +			{
 +				if(array_key_exists($prop, $object))
 +					$object = $object[$prop];
 +				else
 +					throw new TInvalidPropertyException('sqlmap_invalid_property',$path);
 +			}
 +			else if(is_object($object))
 +			{
 +				$getter = 'get'.$prop;
 +				if(is_callable(array($object,$getter)))
 +					$object = $object->{$getter}();
 +				else if(in_array($prop, array_keys(get_object_vars($object))))
 +					$object = $object->{$prop};
 +				else
 +					throw new TInvalidPropertyException('sqlmap_invalid_property',$path);
 +			}
 +			else
 +				throw new TInvalidPropertyException('sqlmap_invalid_property',$path);
 +		}
 +		return $object;
 +	}
 +
 +	public static function has($object, $path)
 +	{
 +		if(!is_array($object) && !is_object($object))
 +			return false;
 +		$properties = explode('.', $path);
 +		foreach($properties as $prop)
 +		{
 +			if(is_array($object) || $object instanceof ArrayAccess)
 +			{
 +				if(array_key_exists($prop, $object))
 +					$object = $object[$prop];
 +				else
 +					return false;
 +			}
 +			else if(is_object($object))
 +			{
 +				$getter = 'get'.$prop;
 +				if(is_callable(array($object,$getter)))
 +					$object = $object->{$getter}();
 +				else if(in_array($prop, array_keys(get_object_vars($object))))
 +					$object = $object->{$prop};
 +				return false;
 +			}
 +			else
 +				return false;
 +		}
 +		return true;
 +	}
 +
 +	public static function set(&$originalObject, $path, $value)
 +	{
 +		$properties = explode('.', $path);
 +		$prop = array_pop($properties);
 +		if(count($properties) > 0)
 +			$object = self::get($originalObject, implode('.',$properties));
 +		else
 +			$object = &$originalObject;
 +
 +		//var_dump($object);
 +		if(is_array($object) || $object instanceof ArrayAccess)
 +		{
 +			$object[$prop] = $value;
 +		}
 +		else if(is_object($object))
 +		{
 +			$setter = 'set'.$prop;
 +			if(is_callable(array($object, $setter)))
 +			{
 +				if($object->{$setter}($value) === null)
 +					$object->{$prop} = $value;
 +			}
 +			else
 +				$object->{$prop} = $value;
 +		}
 +		else
 +			throw new TInvalidPropertyException('sqlmap_invalid_property_type',$path);
 +	}
 +
 +}
 +
 +?>
\ No newline at end of file diff --git a/framework/Data/SqlMap/DataMapper/TSqlMapCache.php b/framework/Data/SqlMap/DataMapper/TSqlMapCache.php new file mode 100644 index 00000000..5cb9cbcb --- /dev/null +++ b/framework/Data/SqlMap/DataMapper/TSqlMapCache.php @@ -0,0 +1,230 @@ +<?php
 +/**
 + * TSqlMapCache class file contains FIFO, LRU, and GLOBAL cache implementations.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @link http://www.pradosoft.com/
 + * @copyright Copyright © 2005-2007 PradoSoft
 + * @license http://www.pradosoft.com/license/
 + * @version $Id$
 + * @package System.DataAccess.SQLMap
 + */
 +
 +interface ISqLMapCache
 +{
 +	public function remove($key);
 +
 +	public function flush();
 +
 +	public function get($key);
 +
 +	public function set($key, $value);
 +}
 +
 +/**
 + * Allow different implementation of caching strategy. See <tt>TSqlMapFifoCache</tt>
 + * for a first-in-first-out implementation. See <tt>TSqlMapLruCache</tt> for
 + * a least-recently-used cache implementation.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @version $Id$
 + * @package System.DataAccess.SQLMap
 + * @since 3.0
 + */
 +abstract class TSqlMapCache implements ISqlMapCache
 +{
 +	protected $_keyList;
 +	protected $_cache;
 +	protected $_cacheSize = 100;
 +
 +	/**
 +	 * Create a new cache with limited cache size.
 +	 * @param integer maxium number of items to cache.
 +	 */
 +	public function __construct($cacheSize=100)
 +	{
 +		$this->_cache = new TMap;
 +		$this->_cacheSize = intval($cacheSize);
 +		$this->_keyList = new TList;
 +	}
 +
 +	public function setCacheSize($value)
 +	{
 +		$this->_cacheSize=TPropertyValue::ensureInteger($value,100);
 +	}
 +
 +	public function getCacheSize()
 +	{
 +		return $this->_cacheSize;
 +	}
 +
 +	/**
 +	 * @return object the object removed if exists, null otherwise.
 +	 */
 +	public function remove($key)
 +	{
 +		$object = $this->get($key);
 +		$this->_cache->remove($key);
 +		$this->_keyList->remove($key);
 +		return $object;
 +	}
 +
 +	/**
 +	 * Clears the cache.
 +	 */
 +	public function flush()
 +	{
 +		$this->_keyList->clear();
 +		$this->_cache->clear();
 +	}
 +
 +}
 +
 +/**
 + * First-in-First-out cache implementation, removes
 + * object that was first added when the cache is full.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @version $Id$
 + * @package System.DataAccess.SQLMap
 + * @since 3.0
 + */
 +class TSqlMapFifoCache extends TSqlMapCache
 +{
 +	/**
 +	 * @return mixed Gets a cached object with the specified key.
 +	 */
 +	public function get($key)
 +	{
 +		return $this->_cache->itemAt($key);
 +	}
 +
 +	/**
 +	 * Adds an item with the specified key and value into cached data.
 +	 * @param string cache key
 +	 * @param mixed value to cache.
 +	 */
 +	public function set($key, $value)
 +	{
 +		$this->_cache->add($key, $value);
 +		$this->_keyList->add($key);
 +		if($this->_keyList->getCount() > $this->_cacheSize)
 +		{
 +			$oldestKey = $this->_keyList->removeAt(0);
 +			$this->_cache->remove($oldestKey);
 +		}
 +	}
 +}
 +
 +/**
 + * Least recently used cache implementation, removes
 + * object that was accessed last when the cache is full.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @version $Id$
 + * @package System.DataAccess.SQLMap
 + * @since 3.0
 + */
 +class TSqlMapLruCache extends TSqlMapCache
 +{
 +	/**
 +	 * @return mixed Gets a cached object with the specified key.
 +	 */
 +	public function get($key)
 +	{
 +		if($this->_keyList->contains($key))
 +		{
 +			$this->_keyList->remove($key);
 +			$this->_keyList->add($key);
 +			return $this->_cache->itemAt($key);
 +		}
 +		else
 +			return null;
 +	}
 +
 +	/**
 +	 * Adds an item with the specified key and value into cached data.
 +	 * @param string cache key
 +	 * @param mixed value to cache.
 +	 */
 +	public function set($key, $value)
 +	{
 +		$this->_cache->add($key, $value);
 +		$this->_keyList->add($key);
 +		if($this->_keyList->getCount() > $this->_cacheSize)
 +		{
 +			$oldestKey = $this->_keyList->removeAt(0);
 +			$this->_cache->remove($oldestKey);
 +		}
 +	}
 +}
 +
 +class TSqlMapApplicationCache implements ISqlMapCache
 +{
 +	private $_cache;
 +	private $_expiry=0;
 +	private $_property=array();
 +	private $_cacheModelID;
 +
 +	public function __sleep()
 +	{
 +		$this->_cache = null;
 +		return array_keys(get_object_vars($this));
 +	}
 +
 +	public function remove($key)
 +	{
 +		$this->getCache()->delete($key);
 +	}
 +
 +	public function flush()
 +	{
 +		$this->getCache()->flush();
 +	}
 +
 +	public function get($key)
 +	{
 +		$result = $this->getCache()->get($key);
 +		return $result === false ? null : $result;
 +	}
 +
 +	public function set($key, $value)
 +	{
 +		$this->getCache()->set($key, $value, $this->_expiry);
 +	}
 +
 +	public function configure($model, $properties)
 +	{
 +		$this->_property = $properties;
 +		$this->_cacheModelID = $model->getID();
 +	}
 +
 +	protected function getCache()
 +	{
 +		if(is_null($this->_cache))
 +			$this->initialize();
 +		return $this->_cache;
 +	}
 +
 +	protected function initialize()
 +	{
 +		if(isset($this->_property['expiry']))
 +			$this->_expiry = intval($this->_property['expiry']);
 +
 +		if(isset($this->_property['cacheModule']))
 +		{
 +			$id = $this->_property['cacheModule'];
 +			$this->_cache = Prado::getApplication()->getModule($id);
 +		}
 +		else
 +		{
 +			$this->_cache = Prado::getApplication()->getCache();
 +		}
 +
 +		if(!($this->_cache instanceof ICache))
 +			throw new TSqlMapConfigurationException(
 +				'sqlmap_invalid_prado_cache', $this->_cacheModelID);
 +	}
 +}
 +
 +?>
\ No newline at end of file diff --git a/framework/Data/SqlMap/DataMapper/TSqlMapException.php b/framework/Data/SqlMap/DataMapper/TSqlMapException.php new file mode 100644 index 00000000..9a2db478 --- /dev/null +++ b/framework/Data/SqlMap/DataMapper/TSqlMapException.php @@ -0,0 +1,99 @@ +<?php
 +
 +class TSqlMapException extends TException
 +{
 +	/**
 +	 * Constructor.
 +	 * @param string error message. This can be a string that is listed
 +	 * in the message file. If so, the message in the preferred language
 +	 * will be used as the error message. Any rest parameters will be used
 +	 * to replace placeholders ({0}, {1}, {2}, etc.) in the message.
 +	 */
 +	public function __construct($errorMessage)
 +	{
 +		$this->setErrorCode($errorMessage);
 +		$errorMessage=$this->translateErrorMessage($errorMessage);
 +		$args=func_get_args();
 +		array_shift($args);
 +		$n=count($args);
 +		$tokens=array();
 +		for($i=0;$i<$n;++$i)
 +		{
 +			if($args[$i] instanceof SimpleXmlElement)
 +				$tokens['{'.$i.'}']=$this->implodeNode($args[$i]);
 +			else
 +				$tokens['{'.$i.'}']=TPropertyValue::ensureString($args[$i]);
 +		}
 +		parent::__construct(strtr($errorMessage,$tokens));
 +	}
 +
 +	protected function implodeNode($node)
 +	{
 +		$attributes=array();
 +		foreach($node->attributes() as $k=>$v)
 +			$attributes[]=$k.'="'.(string)$v.'"';
 +		return '<'.$node->getName().' '.implode(' ',$attributes).'>';
 +	}
 +
 +	/**
 +	 * @return string path to the error message file
 +	 */
 +	protected function getErrorMessageFile()
 +	{
 +		$lang=Prado::getPreferredLanguage();
 +		$dir=dirname(__FILE__);
 +		$msgFile=$dir.'/messages-'.$lang.'.txt';
 +		if(!is_file($msgFile))
 +			$msgFile=$dir.'/messages.txt';
 +		return $msgFile;
 +	}
 +}
 +
 +class TSqlMapConfigurationException extends TSqlMapException
 +{
 +
 +}
 +
 +class TUndefinedAttributeException extends TSqlMapConfigurationException
 +{
 +	public function __construct($attr, $node, $object, $file)
 +	{
 +		parent::__construct(
 +			'sqlmap_undefined_attribute', get_class($object), $attr,
 +			htmlentities($node->asXml()),$file);
 +	}
 +}
 +
 +class TSqlMapExecutionException extends TSqlMapException
 +{
 +}
 +
 +class TSqlMapQueryExecutionException extends TSqlMapExecutionException
 +{
 +	protected $parent;
 +	public function __construct($statement, $exception)
 +	{
 +		$this->parent = $exception;
 +		parent::__construct('sqlmap_query_execution_error',
 +			$statement->getID(), $exception->getMessage());
 +	}
 +}
 +
 +class TSqlMapUndefinedException extends TSqlMapException
 +{
 +
 +}
 +
 +class TSqlMapDuplicateException extends TSqlMapException
 +{
 +}
 +
 +class TSqlMapConnectionException extends TSqlMapException
 +{
 +}
 +
 +class TInvalidPropertyException extends TSqlMapException
 +{
 +
 +}
 +?>
\ No newline at end of file diff --git a/framework/Data/SqlMap/DataMapper/TSqlMapPagedList.php b/framework/Data/SqlMap/DataMapper/TSqlMapPagedList.php new file mode 100644 index 00000000..b15a1d4c --- /dev/null +++ b/framework/Data/SqlMap/DataMapper/TSqlMapPagedList.php @@ -0,0 +1,158 @@ +<?php
 +
 +Prado::using('System.Collections.TPagedList');
 +
 +/**
 + * TSQLMapPagedList
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @version $Id$
 + * @package System.Web.UI.WebControls
 + * @since 3.0
 + */
 +class TSqlMapPagedList extends TPagedList
 +{
 +	private $_statement;
 +	private $_parameter;
 +	private $_prevPageList;
 +	private $_nextPageList;
 +	private $_delegate=null;
 +
 +	public function __construct(IMappedStatement $statement,
 +									$parameter, $pageSize, $delegate=null)
 +	{
 +		parent::__construct();
 +		parent::setCustomPaging(true);
 +		$this->initialize($statement,$parameter, $pageSize);
 +		$this->_delegate=$delegate;
 +	}
 +
 +	protected function initialize($statement, $parameter, $pageSize)
 +	{
 +		$this->_statement = $statement;
 +		$this->_parameter = $parameter;
 +		$this->setPageSize($pageSize);
 +		$this->attachEventHandler('OnFetchData', array($this, 'fetchDataFromStatement'));
 +		$this->gotoPage(0);
 +	}
 +
 +	public function setCustomPaging($value)
 +	{
 +		throw new TDataMapperException('sqlmap_must_enable_custom_paging');
 +	}
 +
 +	protected function fetchDataFromStatement($sender, $param)
 +	{
 +		$limit = $this->getOffsetAndLimit($param);
 +		$connection = $this->_statement->getManager()->getDbConnection();
 +		$data = $this->_statement->executeQueryForList($connection,
 +						$this->_parameter, null, $limit[0], $limit[1], $this->_delegate);
 +		$this->populateData($param, $data);
 +	}
 +
 +	public function nextPage()
 +	{
 +		if($this->getIsNextPageAvailable())
 +			return parent::nextPage();
 +		else
 +			return false;
 +	}
 +
 +	public function previousPage()
 +	{
 +		if($this->getIsPreviousPageAvailable())
 +			return parent::previousPage();
 +		else
 +			return false;
 +	}
 +
 +	protected function populateData($param, $data)
 +	{
 +		$total = $data instanceof TList ? $data->getCount() : count($data);
 +		$pageSize = $this->getPageSize();
 +		if($total < 1)
 +		{
 +			$param->setData($data);
 +			$this->_prevPageList = null;
 +			$this->_nextPageList = null;
 +			return;
 +		}
 +
 +		if($param->getNewPageIndex() < 1)
 +		{
 +			$this->_prevPageList = null;
 +			if($total <= $pageSize)
 +			{
 +				$param->setData($data);
 +				$this->_nextPageList = null;
 +			}
 +			else
 +			{
 +				$param->setData($this->sublist($data, 0, $pageSize));
 +				$this->_nextPageList = $this->sublist($data, $pageSize,$total);
 +			}
 +		}
 +		else
 +		{
 +			if($total <= $pageSize)
 +			{
 +				$this->_prevPageList = $this->sublist($data, 0, $total);
 +				$param->setData(array());
 +				$this->_nextPageList = null;
 +			}
 +			else if($total <= $pageSize*2)
 +			{
 +				$this->_prevPageList = $this->sublist($data, 0, $pageSize);
 +				$param->setData($this->sublist($data, $pageSize, $total));
 +				$this->_nextPageList = null;
 +			}
 +			else
 +			{
 +				$this->_prevPageList = $this->sublist($data, 0, $pageSize);
 +				$param->setData($this->sublist($data, $pageSize, $pageSize*2));
 +				$this->_nextPageList = $this->sublist($data, $pageSize*2, $total);
 +			}
 +		}
 +	}
 +
 +	protected function sublist($data, $from, $to)
 +	{
 +		$array = array();
 +		for($i = $from; $i<$to; $i++)
 +			$array[] = $data[$i];
 +		return $array;
 +	}
 +
 +	protected function getOffsetAndLimit($param)
 +	{
 +		$index = $param->getNewPageIndex();
 +		$pageSize = $this->getPageSize();
 +		if($index < 1)
 +			return array($index, $pageSize*2);
 +		else
 +			return array(($index-1)*$pageSize, $pageSize*3);
 +	}
 +
 +	public function getIsNextPageAvailable()
 +	{
 +		return !is_null($this->_nextPageList);
 +	}
 +
 +	public function getIsPreviousPageAvailable()
 +	{
 +		return !is_null($this->_prevPageList);
 +	}
 +
 +	public function getIsLastPage()
 +	{
 +		return is_null($this->_nextPageList)
 +				|| $this->_nextPageList->getCount() < 1;
 +	}
 +
 +	public function getIsMiddlePage()
 +	{
 +		return !($this->getIsFirstPage() || $this->getIsLastPage());
 +	}
 +}
 +
 +?>
\ No newline at end of file diff --git a/framework/Data/SqlMap/DataMapper/TSqlMapTypeHandlerRegistry.php b/framework/Data/SqlMap/DataMapper/TSqlMapTypeHandlerRegistry.php new file mode 100644 index 00000000..c26c0401 --- /dev/null +++ b/framework/Data/SqlMap/DataMapper/TSqlMapTypeHandlerRegistry.php @@ -0,0 +1,183 @@ +<?php
 +
 +/**
 + * TTypeHandlerFactory provides type handler classes to convert database field type
 + * to PHP types and vice versa.
 + *
 + * @author Wei Zhuo <weizho[at]gmail[dot]com>
 + * @version $Id$
 + * @package System.Data.SqlMap.DataMapper
 + * @since 3.1
 + */
 +class TSqlMapTypeHandlerRegistry
 +{
 +	private $_typeHandlers=array();
 +
 +	/**
 +	 * @param string database field type
 +	 * @return TSqlMapTypeHandler type handler for give database field type.
 +	 */
 +	public function getDbTypeHandler($dbType='NULL')
 +	{
 +		foreach($this->_typeHandlers as $handler)
 +			if($handler->getDbType()===$dbType)
 +				return $handler;
 +	}
 +
 +	/**
 +	 * @param string type handler class name
 +	 * @return TSqlMapTypeHandler type handler
 +	 */
 +	public function getTypeHandler($class)
 +	{
 +		if(isset($this->_typeHandlers[$class]))
 +			return $this->_typeHandlers[$class];
 +	}
 +
 +	/**
 +	 * @param TSqlMapTypeHandler registers a new type handler
 +	 */
 +	public function registerTypeHandler(TSqlMapTypeHandler $handler)
 +	{
 +		$this->_typeHandlers[$handler->getType()] = $handler;
 +	}
 +
 +	/**
 +	 * Creates a new instance of a particular class (for PHP primative types,
 +	 * their corresponding default value for given type is used).
 +	 * @param string PHP type name
 +	 * @return mixed default type value, if no type is specified null is returned.
 +	 * @throws TSqlMapException if class name is not found.
 +	 */
 +	public function createInstanceOf($type='')
 +	{
 +		if(strlen($type) > 0)
 +		{
 +			switch(strtolower($type))
 +			{
 +				case 'string': return '';
 +				case 'array': return array();
 +				case 'float': case 'double': case 'decimal': return 0.0;
 +				case 'integer': case 'int': return 0;
 +				case 'bool': case 'boolean': return false;
 +			}
 +
 +			if(class_exists('Prado', false))
 +				return Prado::createComponent($type);
 +			else if(class_exists($type, false)) //NO auto loading
 +				return new $type;
 +			else
 +				throw new TSqlMapException('sqlmap_unable_to_find_class', $type);
 +		}
 +	}
 +
 +	/**
 +	 * Converts the value to given type using PHP's settype() function.
 +	 * @param string PHP primative type.
 +	 * @param mixed value to be casted
 +	 * @return mixed type casted value.
 +	 */
 +	public function convertToType($type, $value)
 +	{
 +		switch(strtolower($type))
 +		{
 +			case 'integer': case 'int':
 +				$type = 'integer'; break;
 +			case 'float': case 'double': case 'decimal':
 +				$type = 'float'; break;
 +			case 'boolean': case 'bool':
 +				$type = 'boolean'; break;
 +			case 'string' :
 +				$type = 'string'; break;
 +			default:
 +				return $value;
 +		}
 +		settype($value, $type);
 +		return $value;
 +	}
 +}
 +
 +/**
 + * A simple interface for implementing custom type handlers.
 + *
 + * Using this interface, you can implement a type handler that
 + * will perform customized processing before parameters are set
 + * on and after values are retrieved from the database.
 + * Using a custom type handler you can extend
 + * the framework to handle types that are not supported, or
 + * handle supported types in a different way.  For example,
 + * you might use a custom type handler to implement proprietary
 + * BLOB support (e.g. Oracle), or you might use it to handle
 + * booleans using "Y" and "N" instead of the more typical 0/1.
 + *
 + * @author Wei Zhuo <weizho[at]gmail[dot]com>
 + * @version $Id$
 + * @package System.Data.SqlMap.DataMapper
 + * @since 3.1
 + */
 +abstract class TSqlMapTypeHandler extends TComponent
 +{
 +	private $_dbType='NULL';
 +	private $_type;
 +	/**
 +	 * @param string database field type.
 +	 */
 +	public function setDbType($value)
 +	{
 +		$this->_dbType=$value;
 +	}
 +
 +	/**
 +	 * @return string database field type.
 +	 */
 +	public function getDbType()
 +	{
 +		return $this->_dbType;
 +	}
 +
 +	public function getType()
 +	{
 +		if($this->_type===null)
 +			return get_class($this);
 +		else
 +			return $this->_type;
 +	}
 +
 +	public function setType($value)
 +	{
 +		$this->_type=$value;
 +	}
 +
 +	/**
 +	 * Performs processing on a value before it is used to set
 +	 * the parameter of a IDbCommand.
 +	 * @param object The interface for setting the value.
 +	 * @param object The value to be set.
 +	 */
 +	public abstract function getParameter($object);
 +
 +
 +	/**
 +	 * Performs processing on a value before after it has been retrieved
 +	 * from a database
 +	 * @param object The interface for getting the value.
 +	 * @return mixed The processed value.
 +	 */
 +	public abstract function getResult($string);
 +
 +
 +	/**
 +	 * Casts the string representation of a value into a type recognized by
 +	 * this type handler.  This method is used to translate nullValue values
 +	 * into types that can be appropriately compared.  If your custom type handler
 +	 * cannot support nullValues, or if there is no reasonable string representation
 +	 * for this type (e.g. File type), you can simply return the String representation
 +	 * as it was passed in.  It is not recommended to return null, unless null was passed
 +	 * in.
 +	 * @param array result row.
 +	 * @return mixed
 +	 */
 +	public abstract function createNewInstance($row=null);
 +}
 +
 +?>
\ No newline at end of file diff --git a/framework/Data/SqlMap/DataMapper/messages.txt b/framework/Data/SqlMap/DataMapper/messages.txt new file mode 100644 index 00000000..0923d606 --- /dev/null +++ b/framework/Data/SqlMap/DataMapper/messages.txt @@ -0,0 +1,66 @@ +
 +# TSqlMapManager.php
 +sqlmap_contains_no_statement			= Unable to find SQLMap statement '{0}'.
 +sqlmap_already_contains_statement		= Duplicate SQLMap statement found, '{0}' already exists.
 +sqlmap_contains_no_result_map			= Unable to find SQLMap result map '{0}'.
 +sqlmap_already_contains_result_map		= Duplicate SQLMap result map found, '{0}' already exists.
 +sqlmap_contains_no_parameter_map		= Unable to find SQLMap parameter map '{0}'.
 +sqlmap_already_contains_parameter_map	= Duplicate SQLMap parameter map found, '{0}' already exists.
 +sqlmap_cache_model_already_exists		= This SQLMap already contains cache model '{0}'.
 +sqlmap_unable_to_find_cache_model		= Unable to find cache model '{0}' in this SQLMap.
 +
 +# TTypeHandlerFactory.php
 +sqlmap_dbtype_handler_not_found			= Type handler for dbType='{0}' not found.
 +sqlmap_type_handler_class_not_found		= Type handler class '{0}' not found.
 +sqlmap_unable_to_find_class				= Unable to find class '{0}'.
 +
 +# TSqlMapXmlConfig.php
 +sqlmap_node_class_undef					= Missing attribute 'class' in tag '{0}' in configuration file '{1}'.
 +sqlmap_unable_to_find_parent_result_map	= Unable to find parent SQLMap result map named '{2}' in file {1} near '{0}'.
 +sqlmap_undefined_discriminator			= The <discriminator> tag not found in ResultMap '{0}' for sub-map '{2}' in file '{1}'.
 +sqlmap_unable_to_find_parent_sql		= Unable to find parent sql statement extension '{0}' near '{2}' in file {1}.
 +sqlmap_invalid_property					= Invalid property '{0}' for class '{1}' for tag '{2}' in configuration file '{3}'.
 +
 +
 +# TInlineParameterMapParser.php
 +sqlmap_undefined_property_inline_map	= Invalid attribute '{0}' in '{3}' for inline parameter in statement '{2}' in file {1}.
 +
 +# TSqlMapCacheModel.php
 +sqlmap_unable_to_find_implemenation		= Unable to find cache implementation class '{0}'.
 +
 +# TResultProperty.php
 +sqlmap_error_in_result_property_from_handler	= For result map '{0}', error in getting result from type handler '{2}', with value '{1}'.
 +
 +# TParameterMap.php
 +sqlmap_index_must_be_string_or_int		= Invalid index '{0}', must be an integes or string to get a SqlMap parameter map property.
 +sqlmap_unable_to_get_property_for_parameter = Unable to find property '{1}' in object '{2}' for parameter map '{0}'.
 +sqlmap_error_in_parameter_from_handler	= For parameter map '{0}', error in getting parameter from type handler '{2}' with value '{1}': '{3}'.
 +
 +# MISC
 +sqlmap_type_handler_class_undef			= Unable to find type handler class named '{1}' in sqlmap configuration file '{0}'.
 +sqlmap_type_handler_callback_undef		= Attributes 'type' and 'callback' must be defined in typeHandler tag in configuration file '{0}'.
 +
 +sqlmap_undefined_attribute				= {0} attribute '{1}' is not defined for {2} in file {3}.
 +sqlmap_unable_to_find_parent_parameter_map	= Unable to find parent parameter map extension '{0}' in file {1}.
 +sqlmap_unable_to_find_result_mapping	= Unable to resolve SQLMap result mapping '{0}' in Result Map '{2}' using configuration file {1}.
 +
 +sqlmap_undefined_input_property			= Undefined array index '{0}' in retrieving property in SQLMap parameter map '{1}'.
 +sqlmap_can_not_instantiate				= Type handler '{0}' can not create new objects.
 +sqlmap_cannot_execute_query_for_map		= SQLMap statement class {0} can not query for map in statement '{1}'.
 +sqlmap_cannot_execute_update			= SQLMap statement class {0} can not execute update query in statement '{1}'.
 +sqlmap_cannot_execute_insert			= SQLMap statement class {0} can not execute insert in statement '{1}'.
 +sqlmap_cannot_execute_query_for_list	= SQLMap statement class {0} can not query for list in statement '{1}'.
 +sqlmap_cannot_execute_query_for_object	= SQLMap statement class {0} can not query for object in statement '{1}'.
 +sqlmap_execution_error_no_record		= No record set found in executing statement '{0}': '{1}'.
 +sqlmap_unable_to_create_new_instance	= Unable to create a new instance of '{0}' using type hander '{1}' for SQLMap statement with ID '{2}'.
 +sqlmap_invalid_property_type			= Invalid object type, must be 'Object', unable to set property in path '{0}'.
 +
 +sqlmap_unable_to_find_config			= Unable to find SQLMap configuration file '{0}'.
 +sqlmap_unable_to_find_groupby			= Unable to find data in result set with column '{0}' in result map with ID '{1}'.
 +sqlmap_invalid_lazyload_list			= Invalid type to lazy load, must specify a valid ListClass in statement '{0}'.
 +sqlmap_unable_to_find_resource			= 'Unable to find SQLMap configuration file '{0}'.
 +sqlmap_query_execution_error			= Error in executing SQLMap statement '{0}' : '{1}'.
 +sqlmap_invalid_delegate					= Invalid callback row delegate '{1}' in mapped statement '{0}'.
 +sqlmap_invalid_prado_cache				= Unable to find Prado cache module for SQLMap cache '{0}'.
 +
 +sqlmap_non_groupby_array_list_type		= Expecting GroupBy property in result map '{0}' since {1}::{2} is an array or TList type.
\ No newline at end of file  | 
