From 903ae8a581fac1e6917fc3e31d2ad8fb91df80c3 Mon Sep 17 00:00:00 2001 From: ctrlaltca <> Date: Thu, 12 Jul 2012 11:21:01 +0000 Subject: standardize the use of unix eol; use svn properties to enforce native eol --- .../Data/SqlMap/Configuration/TDiscriminator.php | 462 +++--- .../Configuration/TInlineParameterMapParser.php | 156 +- .../Data/SqlMap/Configuration/TParameterMap.php | 420 ++--- .../SqlMap/Configuration/TParameterProperty.php | 298 ++-- framework/Data/SqlMap/Configuration/TResultMap.php | 400 ++--- .../Data/SqlMap/Configuration/TResultProperty.php | 688 ++++----- .../SqlMap/Configuration/TSimpleDynamicParser.php | 88 +- .../SqlMap/Configuration/TSqlMapCacheModel.php | 492 +++--- .../Data/SqlMap/Configuration/TSqlMapStatement.php | 902 +++++------ .../Configuration/TSqlMapXmlConfiguration.php | 1610 ++++++++++---------- 10 files changed, 2758 insertions(+), 2758 deletions(-) (limited to 'framework/Data/SqlMap/Configuration') diff --git a/framework/Data/SqlMap/Configuration/TDiscriminator.php b/framework/Data/SqlMap/Configuration/TDiscriminator.php index cbc05612..f0c9187b 100644 --- a/framework/Data/SqlMap/Configuration/TDiscriminator.php +++ b/framework/Data/SqlMap/Configuration/TDiscriminator.php @@ -1,232 +1,232 @@ - - * @link http://www.pradosoft.com/ + + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Data.SqlMap.Configuration - */ - -/** - * The TDiscriminator corresponds to the tag within a . - * - * TDiscriminator allows inheritance logic in SqlMap result mappings. - * SqlMap compares the data found in the discriminator column to the different - * values using the column value's string equivalence. When the string values - * matches a particular , SqlMap will use the defined by - * {@link resultMapping TSubMap::setResultMapping()} property for loading - * the object data. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - * @since 3.1 - */ -class TDiscriminator extends TComponent -{ - private $_column; - private $_type; - private $_typeHandler=null; - private $_columnIndex; - private $_nullValue; - private $_mapping; - private $_resultMaps=array(); - private $_subMaps=array(); - - /** - * @return string the name of the column in the result set from which the - * value will be used to populate the property. - */ - public function getColumn() - { - return $this->_column; - } - - /** - * @param string the name of the column in the result set from which the - * value will be used to populate the property. - */ - public function setColumn($value) - { - $this->_column = $value; - } - - /** - * @param string property type of the parameter to be set. - */ - public function getType() - { - return $this->_type; - } - - /** - * The type attribute is used to explicitly specify the property type of the - * parameter to be set. If the attribute type is not set and the framework - * cannot otherwise determine the type, the type is assumed from the default - * value of the property. - * @return string property type of the parameter to be set. - */ - public function setType($value) - { - $this->_type = $value; - } - - /** - * @return string custom type handler class name (may use namespace). - */ - public function getTypeHandler() - { - return $this->_typeHandler; - } - - /** - * @param string custom type handler class name (may use namespace). - */ - public function setTypeHandler($value) - { - $this->_typeHandler = $value; - } - - /** - * @return int index of the column in the ResultSet - */ - public function getColumnIndex() - { - return $this->_columnIndex; - } - - /** - * The columnIndex attribute value is the index of the column in the - * ResultSet from which the value will be used to populate the object property. - * @param int index of the column in the ResultSet - */ - public function setColumnIndex($value) - { - $this->_columnIndex = TPropertyValue::ensureInteger($value); - } - - /** - * @return mixed outgoing null value replacement. - */ - public function getNullValue() - { - return $this->_nullValue; - } - - /** - * @param mixed outgoing null value replacement. - */ - public function setNullValue($value) - { - $this->_nullValue = $value; - } - - /** - * @return TResultProperty result property for the discriminator column. - */ - public function getMapping() - { - return $this->_mapping; - } - - /** - * @param TSubMap add new sub mapping. - */ - public function addSubMap($subMap) - { - $this->_subMaps[] = $subMap; - } - - /** - * @param string database value - * @return TResultMap result mapping. - */ - public function getSubMap($value) - { - if(isset($this->_resultMaps[$value])) - return $this->_resultMaps[$value]; - } - - /** - * Copies the discriminator properties to a new TResultProperty. - * @param TResultMap result map holding the discriminator. - */ - public function initMapping($resultMap) - { - $this->_mapping = new TResultProperty($resultMap); - $this->_mapping->setColumn($this->getColumn()); - $this->_mapping->setColumnIndex($this->getColumnIndex()); - $this->_mapping->setType($this->getType()); - $this->_mapping->setTypeHandler($this->getTypeHandler()); - $this->_mapping->setNullValue($this->getNullValue()); - } - - /** - * Set the result maps for particular sub-mapping values. - * @param TSqlMapManager sql map manager instance. - */ - public function initialize($manager) - { - foreach($this->_subMaps as $subMap) - { - $this->_resultMaps[$subMap->getValue()] = - $manager->getResultMap($subMap->getResultMapping()); - } - } -} - -/** - * TSubMap class defines a submapping value and the corresponding - * - * The {@link Value setValue()} property is used for comparison with the - * discriminator column value. When the {@link Value setValue()} matches - * that of the discriminator column value, the corresponding {@link ResultMapping setResultMapping} - * is used inplace of the current result map. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - * @since 3.1 - */ -class TSubMap extends TComponent -{ - private $_value; - private $_resultMapping; - - /** - * @return string value for comparison with discriminator column value. - */ - public function getValue() - { - return $this->_value; - } - - /** - * @param string value for comparison with discriminator column value. - */ - public function setValue($value) - { - $this->_value = $value; - } - - /** - * The result map to use when the Value matches the discriminator column value. - * @return string ID of a result map - */ - public function getResultMapping() - { - return $this->_resultMapping; - } - - /** - * @param string ID of a result map - */ - public function setResultMapping($value) - { - $this->_resultMapping = $value; - } -} - + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +/** + * The TDiscriminator corresponds to the tag within a . + * + * TDiscriminator allows inheritance logic in SqlMap result mappings. + * SqlMap compares the data found in the discriminator column to the different + * values using the column value's string equivalence. When the string values + * matches a particular , SqlMap will use the defined by + * {@link resultMapping TSubMap::setResultMapping()} property for loading + * the object data. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TDiscriminator extends TComponent +{ + private $_column; + private $_type; + private $_typeHandler=null; + private $_columnIndex; + private $_nullValue; + private $_mapping; + private $_resultMaps=array(); + private $_subMaps=array(); + + /** + * @return string the name of the column in the result set from which the + * value will be used to populate the property. + */ + public function getColumn() + { + return $this->_column; + } + + /** + * @param string the name of the column in the result set from which the + * value will be used to populate the property. + */ + public function setColumn($value) + { + $this->_column = $value; + } + + /** + * @param string property type of the parameter to be set. + */ + public function getType() + { + return $this->_type; + } + + /** + * The type attribute is used to explicitly specify the property type of the + * parameter to be set. If the attribute type is not set and the framework + * cannot otherwise determine the type, the type is assumed from the default + * value of the property. + * @return string property type of the parameter to be set. + */ + public function setType($value) + { + $this->_type = $value; + } + + /** + * @return string custom type handler class name (may use namespace). + */ + public function getTypeHandler() + { + return $this->_typeHandler; + } + + /** + * @param string custom type handler class name (may use namespace). + */ + public function setTypeHandler($value) + { + $this->_typeHandler = $value; + } + + /** + * @return int index of the column in the ResultSet + */ + public function getColumnIndex() + { + return $this->_columnIndex; + } + + /** + * The columnIndex attribute value is the index of the column in the + * ResultSet from which the value will be used to populate the object property. + * @param int index of the column in the ResultSet + */ + public function setColumnIndex($value) + { + $this->_columnIndex = TPropertyValue::ensureInteger($value); + } + + /** + * @return mixed outgoing null value replacement. + */ + public function getNullValue() + { + return $this->_nullValue; + } + + /** + * @param mixed outgoing null value replacement. + */ + public function setNullValue($value) + { + $this->_nullValue = $value; + } + + /** + * @return TResultProperty result property for the discriminator column. + */ + public function getMapping() + { + return $this->_mapping; + } + + /** + * @param TSubMap add new sub mapping. + */ + public function addSubMap($subMap) + { + $this->_subMaps[] = $subMap; + } + + /** + * @param string database value + * @return TResultMap result mapping. + */ + public function getSubMap($value) + { + if(isset($this->_resultMaps[$value])) + return $this->_resultMaps[$value]; + } + + /** + * Copies the discriminator properties to a new TResultProperty. + * @param TResultMap result map holding the discriminator. + */ + public function initMapping($resultMap) + { + $this->_mapping = new TResultProperty($resultMap); + $this->_mapping->setColumn($this->getColumn()); + $this->_mapping->setColumnIndex($this->getColumnIndex()); + $this->_mapping->setType($this->getType()); + $this->_mapping->setTypeHandler($this->getTypeHandler()); + $this->_mapping->setNullValue($this->getNullValue()); + } + + /** + * Set the result maps for particular sub-mapping values. + * @param TSqlMapManager sql map manager instance. + */ + public function initialize($manager) + { + foreach($this->_subMaps as $subMap) + { + $this->_resultMaps[$subMap->getValue()] = + $manager->getResultMap($subMap->getResultMapping()); + } + } +} + +/** + * TSubMap class defines a submapping value and the corresponding + * + * The {@link Value setValue()} property is used for comparison with the + * discriminator column value. When the {@link Value setValue()} matches + * that of the discriminator column value, the corresponding {@link ResultMapping setResultMapping} + * is used inplace of the current result map. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSubMap extends TComponent +{ + private $_value; + private $_resultMapping; + + /** + * @return string value for comparison with discriminator column value. + */ + public function getValue() + { + return $this->_value; + } + + /** + * @param string value for comparison with discriminator column value. + */ + public function setValue($value) + { + $this->_value = $value; + } + + /** + * The result map to use when the Value matches the discriminator column value. + * @return string ID of a result map + */ + public function getResultMapping() + { + return $this->_resultMapping; + } + + /** + * @param string ID of a result map + */ + public function setResultMapping($value) + { + $this->_resultMapping = $value; + } +} + diff --git a/framework/Data/SqlMap/Configuration/TInlineParameterMapParser.php b/framework/Data/SqlMap/Configuration/TInlineParameterMapParser.php index b78a235c..914d7eb7 100644 --- a/framework/Data/SqlMap/Configuration/TInlineParameterMapParser.php +++ b/framework/Data/SqlMap/Configuration/TInlineParameterMapParser.php @@ -1,79 +1,79 @@ - - * @link http://www.pradosoft.com/ + + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Data.SqlMap.Configuration - */ - -/** - * TInlineParameterMapParser class. - * - * The inline parameter map syntax lets you embed the property name, - * the property type, the column type, and a null value replacement into a - * parametrized SQL statement. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - * @since 3.1 - */ -class TInlineParameterMapParser -{ - /** - * Regular expression for parsing inline parameter maps. - */ - const PARAMETER_TOKEN_REGEXP = '/#([^#]+)#/'; - - /** - * Parse the sql text for inline parameters. - * @param string sql text - * @param array file and node details for exception message. - * @return array 'sql' and 'parameters' name value pairs. - */ - public function parse($sqlText, $scope) - { - $matches = array(); - $mappings = array(); - preg_match_all(self::PARAMETER_TOKEN_REGEXP, $sqlText, $matches); - - for($i = 0, $k=count($matches[1]); $i<$k; $i++) - { - $mappings[] = $this->parseMapping($matches[1][$i], $scope); - $sqlText = str_replace($matches[0][$i], '?', $sqlText); - } - return array('sql'=>$sqlText, 'parameters'=>$mappings); - } - - /** - * Parse inline parameter with syntax as - * #propertyName,type=string,dbype=Varchar,nullValue=N/A,handler=string# - * @param string parameter token - * @param array file and node details for exception message. - */ - protected function parseMapping($token, $scope) - { - $mapping = new TParameterProperty; - $properties = explode(',', $token); - $mapping->setProperty(trim(array_shift($properties))); - foreach($properties as $property) - { - $prop = explode('=',$property); - $name = trim($prop[0]); $value=trim($prop[1]); - if($mapping->canSetProperty($name)) - $mapping->{'set'.$name}($value); - else - { - throw new TSqlMapUndefinedException( - 'sqlmap_undefined_property_inline_map', - $name, $scope['file'], $scope['node'], $token); - } - } - return $mapping; - } -} - + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +/** + * TInlineParameterMapParser class. + * + * The inline parameter map syntax lets you embed the property name, + * the property type, the column type, and a null value replacement into a + * parametrized SQL statement. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TInlineParameterMapParser +{ + /** + * Regular expression for parsing inline parameter maps. + */ + const PARAMETER_TOKEN_REGEXP = '/#([^#]+)#/'; + + /** + * Parse the sql text for inline parameters. + * @param string sql text + * @param array file and node details for exception message. + * @return array 'sql' and 'parameters' name value pairs. + */ + public function parse($sqlText, $scope) + { + $matches = array(); + $mappings = array(); + preg_match_all(self::PARAMETER_TOKEN_REGEXP, $sqlText, $matches); + + for($i = 0, $k=count($matches[1]); $i<$k; $i++) + { + $mappings[] = $this->parseMapping($matches[1][$i], $scope); + $sqlText = str_replace($matches[0][$i], '?', $sqlText); + } + return array('sql'=>$sqlText, 'parameters'=>$mappings); + } + + /** + * Parse inline parameter with syntax as + * #propertyName,type=string,dbype=Varchar,nullValue=N/A,handler=string# + * @param string parameter token + * @param array file and node details for exception message. + */ + protected function parseMapping($token, $scope) + { + $mapping = new TParameterProperty; + $properties = explode(',', $token); + $mapping->setProperty(trim(array_shift($properties))); + foreach($properties as $property) + { + $prop = explode('=',$property); + $name = trim($prop[0]); $value=trim($prop[1]); + if($mapping->canSetProperty($name)) + $mapping->{'set'.$name}($value); + else + { + throw new TSqlMapUndefinedException( + 'sqlmap_undefined_property_inline_map', + $name, $scope['file'], $scope['node'], $token); + } + } + return $mapping; + } +} + diff --git a/framework/Data/SqlMap/Configuration/TParameterMap.php b/framework/Data/SqlMap/Configuration/TParameterMap.php index d7cc5eb6..ee740fdb 100644 --- a/framework/Data/SqlMap/Configuration/TParameterMap.php +++ b/framework/Data/SqlMap/Configuration/TParameterMap.php @@ -1,210 +1,210 @@ - - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Data.SqlMap.Configuration - */ - -/** - * TParameterMap corresponds to the element. - * - * TParameterMap holds one or more parameter child elements that map object - * properties to placeholders in a SQL statement. - * - * A TParameterMap defines an ordered list of values that match up with the - * placeholders of a parameterized query statement. While the attributes - * specified by the map still need to be in the correct order, each parameter - * is named. You can populate the underlying class in any order, and the - * TParameterMap ensures each value is passed in the correct order. - * - * Parameter Maps can be provided as an external element and inline. - * The element accepts two attributes: id (required) and extends (optional). - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - * @since 3.1 - */ -class TParameterMap extends TComponent -{ - private $_extend; - private $_properties; - private $_propertyMap; - private $_extendMap; - private $_ID; - - /** - * Initialize the properties and property map collections. - */ - public function __construct() - { - $this->_properties = new TList; - $this->_propertyMap = new TMap; - } - - /** - * @return string a unique identifier for the . - */ - public function getID() - { - return $this->_ID; - } - - /** - * @param string a unique identifier for the . - */ - public function setID($value) - { - $this->_ID=$value; - } - - /** - * @return TParameterProperty[] list of properties for the parameter map. - */ - public function getProperties() - { - return $this->_properties; - } - - /** - * @return string name of another upon which to base this TParameterMap. - */ - public function getExtends() - { - return $this->_extend; - } - - /** - * @param string name of another upon which to base this TParameterMap. - */ - public function setExtends($value) - { - $this->_extend = $value; - } - - /** - * @param string name of a parameter property. - * @return TParameterProperty parameter property. - * @throws TSqlMapException if index is not string nor integer. - */ - public function getProperty($index) - { - if(is_string($index)) - return $this->_propertyMap->itemAt($index); - else if(is_int($index)) - return $this->_properties->itemAt($index); - else - throw new TSqlMapException('sqlmap_index_must_be_string_or_int', $index); - } - - /** - * @param TParameterProperty new parameter property - */ - public function addProperty(TParameterProperty $property) - { - $this->_propertyMap->add($property->getProperty(), $property); - $this->_properties->add($property); - } - - /** - * @param int parameter property index - * @param TParameterProperty new parameter property. - */ - public function insertProperty($index, TParameterProperty $property) - { - $this->_propertyMap->add($property->getProperty(), $property); - $this->_properties->insertAt($index, $property); - } - - /** - * @return array list of property names. - */ - public function getPropertyNames() - { - return $this->_propertyMap->getKeys(); - } - - /** - * Get the value of a property from the the parameter object. - * @param TSqlMapTypeHandlerRegistry type handler registry. - * @param TParameterProperty parameter proproperty. - * @param mixed parameter object to get the value from. - * @return unknown - */ - public function getPropertyValue($registry, $property, $parameterValue) - { - $value = $this->getObjectValue($parameterValue,$property); - - if(($handler=$this->createTypeHandler($property, $registry))!==null) - $value = $handler->getParameter($value); - - $value = $this->nullifyDefaultValue($property,$value); - - if(($type = $property->getType())!==null) - $value = $registry->convertToType($type, $value); - - return $value; - } - - - /** - * Create type handler from {@link Type setType()} or {@link TypeHandler setTypeHandler}. - * @param TParameterProperty parameter property - * @param TSqlMapTypeHandlerRegistry type handler registry - * @return TSqlMapTypeHandler type handler. - */ - protected function createTypeHandler($property, $registry) - { - $type=$property->getTypeHandler() ? $property->getTypeHandler() : $property->getType(); - $handler=$registry->getTypeHandler($type); - if($handler===null && $property->getTypeHandler()) - $handler = Prado::createComponent($type); - return $handler; - } - - - /** - * @param mixed object to obtain the property from. - * @param TParameterProperty parameter property. - * @return mixed property value. - * @throws TSqlMapException if property access is invalid. - */ - protected function getObjectValue($object,$property) - { - try - { - return TPropertyAccess::get($object, $property->getProperty()); - } - catch (TInvalidPropertyException $e) - { - throw new TSqlMapException( - 'sqlmap_unable_to_get_property_for_parameter', - $this->getID(), - $property->getProperty(), - (is_object($object) ? get_class($object) : gettype($object)) - ); - } - } - - /** - * When the actual value matches the {@link NullValue TParameterProperty::setNullValue()}, - * set the current value to null. - * @param TParameterProperty parameter property. - * @param mixed current property value - * @return mixed null if NullValue matches currrent value. - */ - protected function nullifyDefaultValue($property,$value) - { - if(($nullValue = $property->getNullValue())!==null) - { - if($nullValue === $value) - $value = null; - } - return $value; - } -} + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +/** + * TParameterMap corresponds to the element. + * + * TParameterMap holds one or more parameter child elements that map object + * properties to placeholders in a SQL statement. + * + * A TParameterMap defines an ordered list of values that match up with the + * placeholders of a parameterized query statement. While the attributes + * specified by the map still need to be in the correct order, each parameter + * is named. You can populate the underlying class in any order, and the + * TParameterMap ensures each value is passed in the correct order. + * + * Parameter Maps can be provided as an external element and inline. + * The element accepts two attributes: id (required) and extends (optional). + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TParameterMap extends TComponent +{ + private $_extend; + private $_properties; + private $_propertyMap; + private $_extendMap; + private $_ID; + + /** + * Initialize the properties and property map collections. + */ + public function __construct() + { + $this->_properties = new TList; + $this->_propertyMap = new TMap; + } + + /** + * @return string a unique identifier for the . + */ + public function getID() + { + return $this->_ID; + } + + /** + * @param string a unique identifier for the . + */ + public function setID($value) + { + $this->_ID=$value; + } + + /** + * @return TParameterProperty[] list of properties for the parameter map. + */ + public function getProperties() + { + return $this->_properties; + } + + /** + * @return string name of another upon which to base this TParameterMap. + */ + public function getExtends() + { + return $this->_extend; + } + + /** + * @param string name of another upon which to base this TParameterMap. + */ + public function setExtends($value) + { + $this->_extend = $value; + } + + /** + * @param string name of a parameter property. + * @return TParameterProperty parameter property. + * @throws TSqlMapException if index is not string nor integer. + */ + public function getProperty($index) + { + if(is_string($index)) + return $this->_propertyMap->itemAt($index); + else if(is_int($index)) + return $this->_properties->itemAt($index); + else + throw new TSqlMapException('sqlmap_index_must_be_string_or_int', $index); + } + + /** + * @param TParameterProperty new parameter property + */ + public function addProperty(TParameterProperty $property) + { + $this->_propertyMap->add($property->getProperty(), $property); + $this->_properties->add($property); + } + + /** + * @param int parameter property index + * @param TParameterProperty new parameter property. + */ + public function insertProperty($index, TParameterProperty $property) + { + $this->_propertyMap->add($property->getProperty(), $property); + $this->_properties->insertAt($index, $property); + } + + /** + * @return array list of property names. + */ + public function getPropertyNames() + { + return $this->_propertyMap->getKeys(); + } + + /** + * Get the value of a property from the the parameter object. + * @param TSqlMapTypeHandlerRegistry type handler registry. + * @param TParameterProperty parameter proproperty. + * @param mixed parameter object to get the value from. + * @return unknown + */ + public function getPropertyValue($registry, $property, $parameterValue) + { + $value = $this->getObjectValue($parameterValue,$property); + + if(($handler=$this->createTypeHandler($property, $registry))!==null) + $value = $handler->getParameter($value); + + $value = $this->nullifyDefaultValue($property,$value); + + if(($type = $property->getType())!==null) + $value = $registry->convertToType($type, $value); + + return $value; + } + + + /** + * Create type handler from {@link Type setType()} or {@link TypeHandler setTypeHandler}. + * @param TParameterProperty parameter property + * @param TSqlMapTypeHandlerRegistry type handler registry + * @return TSqlMapTypeHandler type handler. + */ + protected function createTypeHandler($property, $registry) + { + $type=$property->getTypeHandler() ? $property->getTypeHandler() : $property->getType(); + $handler=$registry->getTypeHandler($type); + if($handler===null && $property->getTypeHandler()) + $handler = Prado::createComponent($type); + return $handler; + } + + + /** + * @param mixed object to obtain the property from. + * @param TParameterProperty parameter property. + * @return mixed property value. + * @throws TSqlMapException if property access is invalid. + */ + protected function getObjectValue($object,$property) + { + try + { + return TPropertyAccess::get($object, $property->getProperty()); + } + catch (TInvalidPropertyException $e) + { + throw new TSqlMapException( + 'sqlmap_unable_to_get_property_for_parameter', + $this->getID(), + $property->getProperty(), + (is_object($object) ? get_class($object) : gettype($object)) + ); + } + } + + /** + * When the actual value matches the {@link NullValue TParameterProperty::setNullValue()}, + * set the current value to null. + * @param TParameterProperty parameter property. + * @param mixed current property value + * @return mixed null if NullValue matches currrent value. + */ + protected function nullifyDefaultValue($property,$value) + { + if(($nullValue = $property->getNullValue())!==null) + { + if($nullValue === $value) + $value = null; + } + return $value; + } +} diff --git a/framework/Data/SqlMap/Configuration/TParameterProperty.php b/framework/Data/SqlMap/Configuration/TParameterProperty.php index d941ca18..a79af7f2 100644 --- a/framework/Data/SqlMap/Configuration/TParameterProperty.php +++ b/framework/Data/SqlMap/Configuration/TParameterProperty.php @@ -1,150 +1,150 @@ - - * @link http://www.pradosoft.com/ + + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Data.SqlMap.Configuration - */ - -/** - * TParameterProperty corresponds to the tag and defines - * one object property for the - * - * The {@link NullValue setNullValue()} attribute can be set to any valid - * value (based on property type). The {@link NullValue setNullValue()} attribute - * is used to specify an inbound null value replacement. What this means is - * that when the value is detected in the object property, a NULL will be written - * to the database (the opposite behavior of an inbound null value replacement). - * This allows you to use a magic null number in your application for types that - * do not support null values (such as int, double, float). When these types of - * properties contain a matching null value (for example, say, -9999), a NULL - * will be written to the database instead of the value. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - * @since 3.1 - */ -class TParameterProperty extends TComponent -{ - private $_typeHandler; - private $_type; - private $_column; - private $_dbType; - private $_property; - private $_nullValue; - - /** - * @return string class name of a custom type handler. - */ - public function getTypeHandler() - { - return $this->_typeHandler; - } - - /** - * @param string class name of a custom type handler. - */ - public function setTypeHandler($value) - { - $this->_typeHandler = $value; - } - - /** - * @return string type of the parameter's property - */ - public function getType() - { - return $this->_type; - } - - /** - * @param string type of the parameter's property - */ - public function setType($value) - { - $this->_type = $value; - } - - /** - * @return string name of a parameter to be used in the SQL statement. - */ - public function getColumn() - { - return $this->_column; - } - - /** - * @param string name of a parameter to be used in the SQL statement. - */ - public function setColumn($value) - { - $this->_column = $value; - } - - /** - * @return string the database column type of the parameter to be set by this property. - */ - public function getDbType() - { - return $this->_dbType; - } - - /** - * @param string the database column type of the parameter to be set by this property. - */ - public function setDbType($value) - { - $this->_dbType = $value; - } - - /** - * @return string name of a property of the parameter object. - */ - public function getProperty() - { - return $this->_property; - } - - /** - * @param string name of a property of the parameter object. - */ - public function setProperty($value) - { - $this->_property = $value; - } - - /** - * @return mixed null value replacement - */ - public function getNullValue() - { - return $this->_nullValue; - } - - /** - * The nullValue attribute is used to specify an outgoing null value replacement. - * @param mixed null value replacement. - */ - public function setNullValue($value) - { - $this->_nullValue = $value; - } - - public function __sleep() - { - $exprops = array(); $cn = 'TParameterProperty'; - if ($this->_typeHandler===null) $exprops[] = "\0$cn\0_typeHandler"; - if ($this->_type===null) $exprops[] = "\0$cn\0_type"; - if ($this->_column===null) $exprops[] = "\0$cn\0_column"; - if ($this->_dbType===null) $exprops[] = "\0$cn\0_dbType"; - if ($this->_property===null) $exprops[] = "\0$cn\0_property"; - if ($this->_nullValue===null) $exprops[] = "\0$cn\0_nullValue"; - return array_diff(parent::__sleep(),$exprops); - } -} - + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +/** + * TParameterProperty corresponds to the tag and defines + * one object property for the + * + * The {@link NullValue setNullValue()} attribute can be set to any valid + * value (based on property type). The {@link NullValue setNullValue()} attribute + * is used to specify an inbound null value replacement. What this means is + * that when the value is detected in the object property, a NULL will be written + * to the database (the opposite behavior of an inbound null value replacement). + * This allows you to use a magic null number in your application for types that + * do not support null values (such as int, double, float). When these types of + * properties contain a matching null value (for example, say, -9999), a NULL + * will be written to the database instead of the value. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TParameterProperty extends TComponent +{ + private $_typeHandler; + private $_type; + private $_column; + private $_dbType; + private $_property; + private $_nullValue; + + /** + * @return string class name of a custom type handler. + */ + public function getTypeHandler() + { + return $this->_typeHandler; + } + + /** + * @param string class name of a custom type handler. + */ + public function setTypeHandler($value) + { + $this->_typeHandler = $value; + } + + /** + * @return string type of the parameter's property + */ + public function getType() + { + return $this->_type; + } + + /** + * @param string type of the parameter's property + */ + public function setType($value) + { + $this->_type = $value; + } + + /** + * @return string name of a parameter to be used in the SQL statement. + */ + public function getColumn() + { + return $this->_column; + } + + /** + * @param string name of a parameter to be used in the SQL statement. + */ + public function setColumn($value) + { + $this->_column = $value; + } + + /** + * @return string the database column type of the parameter to be set by this property. + */ + public function getDbType() + { + return $this->_dbType; + } + + /** + * @param string the database column type of the parameter to be set by this property. + */ + public function setDbType($value) + { + $this->_dbType = $value; + } + + /** + * @return string name of a property of the parameter object. + */ + public function getProperty() + { + return $this->_property; + } + + /** + * @param string name of a property of the parameter object. + */ + public function setProperty($value) + { + $this->_property = $value; + } + + /** + * @return mixed null value replacement + */ + public function getNullValue() + { + return $this->_nullValue; + } + + /** + * The nullValue attribute is used to specify an outgoing null value replacement. + * @param mixed null value replacement. + */ + public function setNullValue($value) + { + $this->_nullValue = $value; + } + + public function __sleep() + { + $exprops = array(); $cn = 'TParameterProperty'; + if ($this->_typeHandler===null) $exprops[] = "\0$cn\0_typeHandler"; + if ($this->_type===null) $exprops[] = "\0$cn\0_type"; + if ($this->_column===null) $exprops[] = "\0$cn\0_column"; + if ($this->_dbType===null) $exprops[] = "\0$cn\0_dbType"; + if ($this->_property===null) $exprops[] = "\0$cn\0_property"; + if ($this->_nullValue===null) $exprops[] = "\0$cn\0_nullValue"; + return array_diff(parent::__sleep(),$exprops); + } +} + diff --git a/framework/Data/SqlMap/Configuration/TResultMap.php b/framework/Data/SqlMap/Configuration/TResultMap.php index e05c4c47..77b5f0b2 100644 --- a/framework/Data/SqlMap/Configuration/TResultMap.php +++ b/framework/Data/SqlMap/Configuration/TResultMap.php @@ -1,200 +1,200 @@ - - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Data.SqlMap.Configuration - */ - -/** - * TResultMap corresponds to mapping tag. - * - * A TResultMap lets you control how data is extracted from the result of a - * query, and how the columns are mapped to object properties. A TResultMap - * can describe the column type, a null value replacement, and complex property - * mappings including Collections. - * - * The can contain any number of property mappings that map object - * properties to the columns of a result element. The property mappings are - * applied, and the columns are read, in the order that they are defined. - * Maintaining the element order ensures consistent results between different - * drivers and providers. - * - * The {@link Class setClass()} property must be a PHP class object or array instance. - * - * The optional {@link Extends setExtends()} attribute can be set to the ID of - * another upon which to base this . All properties of the - * "parent" will be included as part of this , and values - * from the "parent" are set before any values specified by this . - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - * @since 3.1 - */ -class TResultMap extends TComponent -{ - private $_columns; - private $_class; - private $_extends; - private $_groupBy; - private $_discriminator; - private $_typeHandlers; - private $_ID; - - /** - * Initialize the columns collection. - */ - public function __construct() - { - $this->_columns=new TMap; - } - - /** - * @return string a unique identifier for the . - */ - public function getID() - { - return $this->_ID; - } - - /** - * @param string a unique identifier for the . - */ - public function setID($value) - { - $this->_ID=$value; - } - - /** - * @return string result class name. - */ - public function getClass() - { - return $this->_class; - } - - /** - * @param string result class name. - */ - public function setClass($value) - { - $this->_class = $value; - } - - /** - * @return TMap result columns. - */ - public function getColumns() - { - return $this->_columns; - } - - /** - * @return string result map extends another result map. - */ - public function getExtends() - { - return $this->_extends; - } - - /** - * @param string result map extends another result map. - */ - public function setExtends($value) - { - $this->_extends = $value; - } - - /** - * @return string result map groups by. - */ - public function getGroupBy() - { - return $this->_groupBy; - } - - /** - * @param string result map group by - */ - public function setGroupBy($value) - { - $this->_groupBy = $value; - } - - /** - * @return TDiscriminator result class discriminator. - */ - public function getDiscriminator() - { - return $this->_discriminator; - } - - /** - * @param TDiscriminator result class discriminator. - */ - public function setDiscriminator(TDiscriminator $value) - { - $this->_discriminator = $value; - } - - /** - * Add a TResultProperty to result mapping. - * @param TResultProperty result property. - */ - public function addResultProperty(TResultProperty $property) - { - $this->_columns[$property->getProperty()] = $property; - } - - /** - * Create a new instance of the class of this result map. - * @param TSqlMapTypeHandlerRegistry type handler registry. - * @return mixed new result object. - * @throws TSqlMapException - */ - public function createInstanceOfResult($registry) - { - $handler = $registry->getTypeHandler($this->getClass()); - try - { - if($handler!==null) - return $handler->createNewInstance(); - else - return $registry->createInstanceOf($this->getClass()); - } - catch (TSqlMapException $e) - { - throw new TSqlMapException( - 'sqlmap_unable_to_create_new_instance', - $this->getClass(), get_class($handler), $this->getID()); - } - } - - /** - * Result sub-mappings using the discriminiator column. - * @param TSqlMapTypeHandlerRegistry type handler registry - * @param array row data. - * @return TResultMap result sub-map. - */ - public function resolveSubMap($registry,$row) - { - $subMap = $this; - if(($disc = $this->getDiscriminator())!==null) - { - $value = $disc->getMapping()->getPropertyValue($registry,$row); - $subMap = $disc->getSubMap((string)$value); - - if($subMap===null) - $subMap = $this; - else if($subMap !== $this) - $subMap = $subMap->resolveSubMap($registry,$row); - } - return $subMap; - } -} - + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +/** + * TResultMap corresponds to mapping tag. + * + * A TResultMap lets you control how data is extracted from the result of a + * query, and how the columns are mapped to object properties. A TResultMap + * can describe the column type, a null value replacement, and complex property + * mappings including Collections. + * + * The can contain any number of property mappings that map object + * properties to the columns of a result element. The property mappings are + * applied, and the columns are read, in the order that they are defined. + * Maintaining the element order ensures consistent results between different + * drivers and providers. + * + * The {@link Class setClass()} property must be a PHP class object or array instance. + * + * The optional {@link Extends setExtends()} attribute can be set to the ID of + * another upon which to base this . All properties of the + * "parent" will be included as part of this , and values + * from the "parent" are set before any values specified by this . + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TResultMap extends TComponent +{ + private $_columns; + private $_class; + private $_extends; + private $_groupBy; + private $_discriminator; + private $_typeHandlers; + private $_ID; + + /** + * Initialize the columns collection. + */ + public function __construct() + { + $this->_columns=new TMap; + } + + /** + * @return string a unique identifier for the . + */ + public function getID() + { + return $this->_ID; + } + + /** + * @param string a unique identifier for the . + */ + public function setID($value) + { + $this->_ID=$value; + } + + /** + * @return string result class name. + */ + public function getClass() + { + return $this->_class; + } + + /** + * @param string result class name. + */ + public function setClass($value) + { + $this->_class = $value; + } + + /** + * @return TMap result columns. + */ + public function getColumns() + { + return $this->_columns; + } + + /** + * @return string result map extends another result map. + */ + public function getExtends() + { + return $this->_extends; + } + + /** + * @param string result map extends another result map. + */ + public function setExtends($value) + { + $this->_extends = $value; + } + + /** + * @return string result map groups by. + */ + public function getGroupBy() + { + return $this->_groupBy; + } + + /** + * @param string result map group by + */ + public function setGroupBy($value) + { + $this->_groupBy = $value; + } + + /** + * @return TDiscriminator result class discriminator. + */ + public function getDiscriminator() + { + return $this->_discriminator; + } + + /** + * @param TDiscriminator result class discriminator. + */ + public function setDiscriminator(TDiscriminator $value) + { + $this->_discriminator = $value; + } + + /** + * Add a TResultProperty to result mapping. + * @param TResultProperty result property. + */ + public function addResultProperty(TResultProperty $property) + { + $this->_columns[$property->getProperty()] = $property; + } + + /** + * Create a new instance of the class of this result map. + * @param TSqlMapTypeHandlerRegistry type handler registry. + * @return mixed new result object. + * @throws TSqlMapException + */ + public function createInstanceOfResult($registry) + { + $handler = $registry->getTypeHandler($this->getClass()); + try + { + if($handler!==null) + return $handler->createNewInstance(); + else + return $registry->createInstanceOf($this->getClass()); + } + catch (TSqlMapException $e) + { + throw new TSqlMapException( + 'sqlmap_unable_to_create_new_instance', + $this->getClass(), get_class($handler), $this->getID()); + } + } + + /** + * Result sub-mappings using the discriminiator column. + * @param TSqlMapTypeHandlerRegistry type handler registry + * @param array row data. + * @return TResultMap result sub-map. + */ + public function resolveSubMap($registry,$row) + { + $subMap = $this; + if(($disc = $this->getDiscriminator())!==null) + { + $value = $disc->getMapping()->getPropertyValue($registry,$row); + $subMap = $disc->getSubMap((string)$value); + + if($subMap===null) + $subMap = $this; + else if($subMap !== $this) + $subMap = $subMap->resolveSubMap($registry,$row); + } + return $subMap; + } +} + diff --git a/framework/Data/SqlMap/Configuration/TResultProperty.php b/framework/Data/SqlMap/Configuration/TResultProperty.php index 0a016350..8447d400 100644 --- a/framework/Data/SqlMap/Configuration/TResultProperty.php +++ b/framework/Data/SqlMap/Configuration/TResultProperty.php @@ -1,344 +1,344 @@ - - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Data.SqlMap.Configuration - */ - -/** - * TResultProperty corresponds a tags inside a tag. - * - * The {@link NullValue setNullValue()} attribute can be set to any valid - * value (based on property type). The {@link NullValue setNullValue()} attribute - * is used to specify an outgoing null value replacement. What this means is - * that when a null value is detected in the result, the corresponding value of - * the {@link NullValue getNullValue()} will be used instead. - * - * The {@link Select setSelect()} property is used to describe a relationship - * between objects and to automatically load complex (i.e. user defined) - * property types. The value of the {@link Select setSelect()} property must be - * the name of another mapped statement. The value of the database - * {@link Column setColumn()} that is defined in the same property element as - * this statement attribute will be passed to the related mapped statement as - * the parameter. The {@link LazyLoad setLayLoad()} attribute can be specified - * with the {@link Select setSelect()} . - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - * @since 3.1 - */ -class TResultProperty extends TComponent -{ - private $_nullValue; - private $_propertyName; - private $_columnName; - private $_columnIndex=-1; - private $_nestedResultMapName; - private $_nestedResultMap; - private $_valueType; - private $_typeHandler; - private $_isLazyLoad=false; - private $_select; - - private $_hostResultMapID='inplicit internal mapping'; - - const LIST_TYPE = 0; - const ARRAY_TYPE = 1; - - /** - * Gets the containing result map ID. - * @param TResultMap containing result map. - */ - public function __construct($resultMap=null) - { - if($resultMap instanceof TResultMap) - $this->_hostResultMapID = $resultMap->getID(); - } - - /** - * @return mixed null value replacement. - */ - public function getNullValue() - { - return $this->_nullValue; - } - - /** - * @param mixed null value replacement. - */ - public function setNullValue($value) - { - $this->_nullValue = $value; - } - - /** - * @return string name of a property of the result object that will be set to. - */ - public function getProperty() - { - return $this->_propertyName; - } - - /** - * @param string name of a property of the result object that will be set to. - */ - public function setProperty($value) - { - $this->_propertyName = $value; - } - - /** - * @return string name of the column in the result set from which the value - * will be used to populate the property. - */ - public function getColumn() - { - return $this->_columnName; - } - - /** - * @param string name of the column in the result set from which the value - * will be used to populate the property. - */ - public function setColumn($value) - { - $this->_columnName = $value; - } - - /** - * @return int index of the column in the ResultSet from which the value will - * be used to populate the object property - */ - public function getColumnIndex() - { - return $this->_columnIndex; - } - - /** - * @param int index of the column in the ResultSet from which the value will - * be used to populate the object property - */ - public function setColumnIndex($value) - { - $this->_columnIndex = TPropertyValue::ensureInteger($value); - } - - /** - * @return string ID of another used to fill the property. - */ - public function getResultMapping() - { - return $this->_nestedResultMapName; - } - - /** - * @param string ID of another used to fill the property. - */ - public function setResultMapping($value) - { - $this->_nestedResultMapName = $value; - } - - /** - * @return TResultMap nested result map. - */ - public function getNestedResultMap() - { - return $this->_nestedResultMap; - } - - /** - * @param TResult nested result map. - */ - public function setNestedResultMap($value) - { - $this->_nestedResultMap = $value; - } - - /** - * @return string property type of the object property to be set. - */ - public function getType() - { - return $this->_valueType; - } - - /** - * @param string property type of the object property to be set. - */ - public function setType($value) - { - $this->_valueType = $value; - } - - /** - * @return string custom type handler class name (may use namespace). - */ - public function getTypeHandler() - { - return $this->_typeHandler; - } - - /** - * @param string custom type handler class name (may use namespace). - */ - public function setTypeHandler($value) - { - $this->_typeHandler = $value; - } - - /** - * @return string name of another mapped statement - */ - public function getSelect() - { - return $this->_select; - } - - /** - * The select property is used to describe a relationship between objects - * and to automatically load complex (i.e. user defined) property types. - * @param string name of another mapped statement. - */ - public function setSelect($value) - { - $this->_select = $value; - } - - /** - * @return boolean indicate whether or not the select statement's results should be lazy loaded - */ - public function getLazyLoad() - { - return $this->_isLazyLoad; - } - - /** - * @param boolean indicate whether or not the select statement's results should be lazy loaded - */ - public function setLazyLoad($value) - { - $this->_isLazyLoad = TPropertyValue::ensureBoolean($value,false); - } - - /** - * Gets the value for the current property, converts to applicable type if necessary. - * @param TSqlMapTypeHandlerRegistry type handler registry - * @param array result row - * @return mixed property value. - */ - public function getPropertyValue($registry,$row) - { - $value = null; - $index = $this->getColumnIndex(); - $name = $this->getColumn(); - if($index > 0 && isset($row[$index])) - $value = $this->getTypedValue($registry,$row[$index]); - else if(isset($row[$name])) - $value = $this->getTypedValue($registry,$row[$name]); - if(($value===null) && ($this->getNullValue()!==null)) - $value = $this->getTypedValue($registry,$this->getNullValue()); - return $value; - } - - /** - * @param TSqlMapTypeHandlerRegistry type handler registry - * @param mixed raw property value - * @return mixed property value casted to specific type. - */ - protected function getTypedValue($registry,$value) - { - if(($handler = $this->createTypeHandler($registry))!==null) - return $handler->getResult($value); - else - return $registry->convertToType($this->getType(), $value); - } - - /** - * Create type handler from {@link Type setType()} or {@link TypeHandler setTypeHandler}. - * @param TSqlMapTypeHandlerRegistry type handler registry - * @return TSqlMapTypeHandler type handler. - */ - protected function createTypeHandler($registry) - { - $type=$this->getTypeHandler() ? $this->getTypeHandler() : $this->getType(); - $handler=$registry->getTypeHandler($type); - if($handler===null && $this->getTypeHandler()) - $handler = Prado::createComponent($type); - return $handler; - } - - /** - * Determines if the type is an instance of ArrayAccess, TList or an array. - * @return int TResultProperty::LIST_TYPE or TResultProperty::ARRAY_TYPE - */ - protected function getPropertyValueType() - { - if(class_exists($type = $this->getType(), false)) //NO force autoloading - { - if($type==='TList') - return self::LIST_TYPE; - $class = new ReflectionClass($type); - if($class->isSubclassOf('TList')) - return self::LIST_TYPE; - if($class->implementsInterface('ArrayAccess')) - return self::ARRAY_TYPE; - } - if(strtolower($type) == 'array') - return self::ARRAY_TYPE; - } - - /** - * Returns true if the result property {@link Type getType()} is of TList type - * or that the actual result object is an instance of TList. - * @param object result object - * @return boolean true if the result object is an instance of TList - */ - public function instanceOfListType($target) - { - if($this->getType()===null) - return TPropertyAccess::get($target,$this->getProperty()) instanceof TList; - return $this->getPropertyValueType() == self::LIST_TYPE; - } - - /** - * Returns true if the result property {@link Type getType()} is of ArrayAccess - * or that the actual result object is an array or implements ArrayAccess - * @param object result object - * @return boolean true if the result object is an instance of ArrayAccess or is an array. - */ - public function instanceOfArrayType($target) - { - if($this->getType()===null) - { - $prop = TPropertyAccess::get($target,$this->getProperty()); - if(is_object($prop)) - return $prop instanceof ArrayAccess; - return is_array($prop); - } - return $this->getPropertyValueType() == self::ARRAY_TYPE; - } - - public function __sleep() - { - $exprops = array(); $cn = 'TResultProperty'; - if ($this->_nullValue===null) $exprops[] = "\0$cn\0_nullValue"; - if ($this->_propertyName===null) $exprops[] = "\0$cn\0_propertyNama"; - if ($this->_columnName===null) $exprops[] = "\0$cn\0_columnName"; - if ($this->_columnIndex==-1) $exprops[] = "\0$cn\0_columnIndex"; - if ($this->_nestedResultMapName===null) $exprops[] = "\0$cn\0_nestedResultMapName"; - if ($this->_nestedResultMap===null) $exprops[] = "\0$cn\0_nestedResultMap"; - if ($this->_valueType===null) $exprops[] = "\0$cn\0_valueType"; - if ($this->_typeHandler===null) $exprops[] = "\0$cn\0_typeHandler"; - if ($this->_isLazyLoad===false) $exprops[] = "\0$cn\0_isLazyLoad"; - if ($this->_select===null) $exprops[] = "\0$cn\0_select"; - return array_diff(parent::__sleep(),$exprops); - } -} - + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +/** + * TResultProperty corresponds a tags inside a tag. + * + * The {@link NullValue setNullValue()} attribute can be set to any valid + * value (based on property type). The {@link NullValue setNullValue()} attribute + * is used to specify an outgoing null value replacement. What this means is + * that when a null value is detected in the result, the corresponding value of + * the {@link NullValue getNullValue()} will be used instead. + * + * The {@link Select setSelect()} property is used to describe a relationship + * between objects and to automatically load complex (i.e. user defined) + * property types. The value of the {@link Select setSelect()} property must be + * the name of another mapped statement. The value of the database + * {@link Column setColumn()} that is defined in the same property element as + * this statement attribute will be passed to the related mapped statement as + * the parameter. The {@link LazyLoad setLayLoad()} attribute can be specified + * with the {@link Select setSelect()} . + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TResultProperty extends TComponent +{ + private $_nullValue; + private $_propertyName; + private $_columnName; + private $_columnIndex=-1; + private $_nestedResultMapName; + private $_nestedResultMap; + private $_valueType; + private $_typeHandler; + private $_isLazyLoad=false; + private $_select; + + private $_hostResultMapID='inplicit internal mapping'; + + const LIST_TYPE = 0; + const ARRAY_TYPE = 1; + + /** + * Gets the containing result map ID. + * @param TResultMap containing result map. + */ + public function __construct($resultMap=null) + { + if($resultMap instanceof TResultMap) + $this->_hostResultMapID = $resultMap->getID(); + } + + /** + * @return mixed null value replacement. + */ + public function getNullValue() + { + return $this->_nullValue; + } + + /** + * @param mixed null value replacement. + */ + public function setNullValue($value) + { + $this->_nullValue = $value; + } + + /** + * @return string name of a property of the result object that will be set to. + */ + public function getProperty() + { + return $this->_propertyName; + } + + /** + * @param string name of a property of the result object that will be set to. + */ + public function setProperty($value) + { + $this->_propertyName = $value; + } + + /** + * @return string name of the column in the result set from which the value + * will be used to populate the property. + */ + public function getColumn() + { + return $this->_columnName; + } + + /** + * @param string name of the column in the result set from which the value + * will be used to populate the property. + */ + public function setColumn($value) + { + $this->_columnName = $value; + } + + /** + * @return int index of the column in the ResultSet from which the value will + * be used to populate the object property + */ + public function getColumnIndex() + { + return $this->_columnIndex; + } + + /** + * @param int index of the column in the ResultSet from which the value will + * be used to populate the object property + */ + public function setColumnIndex($value) + { + $this->_columnIndex = TPropertyValue::ensureInteger($value); + } + + /** + * @return string ID of another used to fill the property. + */ + public function getResultMapping() + { + return $this->_nestedResultMapName; + } + + /** + * @param string ID of another used to fill the property. + */ + public function setResultMapping($value) + { + $this->_nestedResultMapName = $value; + } + + /** + * @return TResultMap nested result map. + */ + public function getNestedResultMap() + { + return $this->_nestedResultMap; + } + + /** + * @param TResult nested result map. + */ + public function setNestedResultMap($value) + { + $this->_nestedResultMap = $value; + } + + /** + * @return string property type of the object property to be set. + */ + public function getType() + { + return $this->_valueType; + } + + /** + * @param string property type of the object property to be set. + */ + public function setType($value) + { + $this->_valueType = $value; + } + + /** + * @return string custom type handler class name (may use namespace). + */ + public function getTypeHandler() + { + return $this->_typeHandler; + } + + /** + * @param string custom type handler class name (may use namespace). + */ + public function setTypeHandler($value) + { + $this->_typeHandler = $value; + } + + /** + * @return string name of another mapped statement + */ + public function getSelect() + { + return $this->_select; + } + + /** + * The select property is used to describe a relationship between objects + * and to automatically load complex (i.e. user defined) property types. + * @param string name of another mapped statement. + */ + public function setSelect($value) + { + $this->_select = $value; + } + + /** + * @return boolean indicate whether or not the select statement's results should be lazy loaded + */ + public function getLazyLoad() + { + return $this->_isLazyLoad; + } + + /** + * @param boolean indicate whether or not the select statement's results should be lazy loaded + */ + public function setLazyLoad($value) + { + $this->_isLazyLoad = TPropertyValue::ensureBoolean($value,false); + } + + /** + * Gets the value for the current property, converts to applicable type if necessary. + * @param TSqlMapTypeHandlerRegistry type handler registry + * @param array result row + * @return mixed property value. + */ + public function getPropertyValue($registry,$row) + { + $value = null; + $index = $this->getColumnIndex(); + $name = $this->getColumn(); + if($index > 0 && isset($row[$index])) + $value = $this->getTypedValue($registry,$row[$index]); + else if(isset($row[$name])) + $value = $this->getTypedValue($registry,$row[$name]); + if(($value===null) && ($this->getNullValue()!==null)) + $value = $this->getTypedValue($registry,$this->getNullValue()); + return $value; + } + + /** + * @param TSqlMapTypeHandlerRegistry type handler registry + * @param mixed raw property value + * @return mixed property value casted to specific type. + */ + protected function getTypedValue($registry,$value) + { + if(($handler = $this->createTypeHandler($registry))!==null) + return $handler->getResult($value); + else + return $registry->convertToType($this->getType(), $value); + } + + /** + * Create type handler from {@link Type setType()} or {@link TypeHandler setTypeHandler}. + * @param TSqlMapTypeHandlerRegistry type handler registry + * @return TSqlMapTypeHandler type handler. + */ + protected function createTypeHandler($registry) + { + $type=$this->getTypeHandler() ? $this->getTypeHandler() : $this->getType(); + $handler=$registry->getTypeHandler($type); + if($handler===null && $this->getTypeHandler()) + $handler = Prado::createComponent($type); + return $handler; + } + + /** + * Determines if the type is an instance of ArrayAccess, TList or an array. + * @return int TResultProperty::LIST_TYPE or TResultProperty::ARRAY_TYPE + */ + protected function getPropertyValueType() + { + if(class_exists($type = $this->getType(), false)) //NO force autoloading + { + if($type==='TList') + return self::LIST_TYPE; + $class = new ReflectionClass($type); + if($class->isSubclassOf('TList')) + return self::LIST_TYPE; + if($class->implementsInterface('ArrayAccess')) + return self::ARRAY_TYPE; + } + if(strtolower($type) == 'array') + return self::ARRAY_TYPE; + } + + /** + * Returns true if the result property {@link Type getType()} is of TList type + * or that the actual result object is an instance of TList. + * @param object result object + * @return boolean true if the result object is an instance of TList + */ + public function instanceOfListType($target) + { + if($this->getType()===null) + return TPropertyAccess::get($target,$this->getProperty()) instanceof TList; + return $this->getPropertyValueType() == self::LIST_TYPE; + } + + /** + * Returns true if the result property {@link Type getType()} is of ArrayAccess + * or that the actual result object is an array or implements ArrayAccess + * @param object result object + * @return boolean true if the result object is an instance of ArrayAccess or is an array. + */ + public function instanceOfArrayType($target) + { + if($this->getType()===null) + { + $prop = TPropertyAccess::get($target,$this->getProperty()); + if(is_object($prop)) + return $prop instanceof ArrayAccess; + return is_array($prop); + } + return $this->getPropertyValueType() == self::ARRAY_TYPE; + } + + public function __sleep() + { + $exprops = array(); $cn = 'TResultProperty'; + if ($this->_nullValue===null) $exprops[] = "\0$cn\0_nullValue"; + if ($this->_propertyName===null) $exprops[] = "\0$cn\0_propertyNama"; + if ($this->_columnName===null) $exprops[] = "\0$cn\0_columnName"; + if ($this->_columnIndex==-1) $exprops[] = "\0$cn\0_columnIndex"; + if ($this->_nestedResultMapName===null) $exprops[] = "\0$cn\0_nestedResultMapName"; + if ($this->_nestedResultMap===null) $exprops[] = "\0$cn\0_nestedResultMap"; + if ($this->_valueType===null) $exprops[] = "\0$cn\0_valueType"; + if ($this->_typeHandler===null) $exprops[] = "\0$cn\0_typeHandler"; + if ($this->_isLazyLoad===false) $exprops[] = "\0$cn\0_isLazyLoad"; + if ($this->_select===null) $exprops[] = "\0$cn\0_select"; + return array_diff(parent::__sleep(),$exprops); + } +} + diff --git a/framework/Data/SqlMap/Configuration/TSimpleDynamicParser.php b/framework/Data/SqlMap/Configuration/TSimpleDynamicParser.php index 1ceba9eb..a70e6b3f 100644 --- a/framework/Data/SqlMap/Configuration/TSimpleDynamicParser.php +++ b/framework/Data/SqlMap/Configuration/TSimpleDynamicParser.php @@ -1,45 +1,45 @@ - - * @link http://www.pradosoft.com/ + + * @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Data.SqlMap.Configuration - */ - -/** - * TSimpleDynamicParser finds place holders $name$ in the sql text and replaces - * it with a TSimpleDynamicParser::DYNAMIC_TOKEN. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - * @since 3.1 - */ -class TSimpleDynamicParser -{ - const PARAMETER_TOKEN_REGEXP = '/\$([^\$]+)\$/'; - const DYNAMIC_TOKEN = '`!`'; - - /** - * Parse the sql text for dynamic place holders of the form $name$. - * @param string Sql text. - * @return array name value pairs 'sql' and 'parameters'. - */ - public function parse($sqlText) - { - $matches = array(); - $mappings = array(); - preg_match_all(self::PARAMETER_TOKEN_REGEXP, $sqlText, $matches); - for($i = 0, $k=count($matches[1]); $i<$k; $i++) - { - $mappings[] = $matches[1][$i]; - $sqlText = str_replace($matches[0][$i], self::DYNAMIC_TOKEN, $sqlText); - } - return array('sql'=>$sqlText, 'parameters'=>$mappings); - } -} - + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +/** + * TSimpleDynamicParser finds place holders $name$ in the sql text and replaces + * it with a TSimpleDynamicParser::DYNAMIC_TOKEN. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSimpleDynamicParser +{ + const PARAMETER_TOKEN_REGEXP = '/\$([^\$]+)\$/'; + const DYNAMIC_TOKEN = '`!`'; + + /** + * Parse the sql text for dynamic place holders of the form $name$. + * @param string Sql text. + * @return array name value pairs 'sql' and 'parameters'. + */ + public function parse($sqlText) + { + $matches = array(); + $mappings = array(); + preg_match_all(self::PARAMETER_TOKEN_REGEXP, $sqlText, $matches); + for($i = 0, $k=count($matches[1]); $i<$k; $i++) + { + $mappings[] = $matches[1][$i]; + $sqlText = str_replace($matches[0][$i], self::DYNAMIC_TOKEN, $sqlText); + } + return array('sql'=>$sqlText, 'parameters'=>$mappings); + } +} + diff --git a/framework/Data/SqlMap/Configuration/TSqlMapCacheModel.php b/framework/Data/SqlMap/Configuration/TSqlMapCacheModel.php index 4b985e51..0dc5d821 100644 --- a/framework/Data/SqlMap/Configuration/TSqlMapCacheModel.php +++ b/framework/Data/SqlMap/Configuration/TSqlMapCacheModel.php @@ -1,246 +1,246 @@ - - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Data.SqlMap.Configuration - */ - -/** - * TSqlMapCacheModel corresponds to the sql mapping configuration tag. - * - * The results from a query Mapped Statement can be cached simply by specifying - * the {@link CacheModel TSqlMapStatement::setCacheModel()} property in tag. - * A cache model is a configured cache that is defined within the sql map - * configuration file. Cache models are configured using the element. - * - * The cache model uses a pluggable framework for supporting different types of - * caches. The choice of cache is specified by the {@link Implementation setImplementation()} - * property. The class name specified must be one of {@link TSqlMapCacheTypes}. - * - * The cache implementations, LRU and FIFO cache below do not persist across - * requests. That is, once the request is complete, all cache data is lost. - * These caches are useful queries that results in the same repeated data during - * the current request. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - * @since 3.1 - */ -class TSqlMapCacheModel extends TComponent -{ - private $_cache; - private $_hits = 0; - private $_requests = 0; - private $_id; - private $_implementation=TSqlMapCacheTypes::Basic; - private $_properties = array(); - private $_flushInterval = 0; - - private static $_cacheTypes = array(); - - public static function registerCacheType($type, $className) - { - self::$_cacheTypes[$type] = $className; - } - - /** - * @return string unique cache model identifier. - */ - public function getID() - { - return $this->_id; - } - - /** - * @param string unique cache model identifier. - */ - public function setID($value) - { - $this->_id = $value; - } - - /** - * @return string cache implements of TSqlMapCacheTypes, either 'Basic', 'LRU' or 'FIFO'. - */ - public function getImplementation() - { - return $this->_implementation; - } - - /** - * @param string cache implements of TSqlMapCacheTypes, either 'Basic', 'LRU' or 'FIFO'. - */ - public function setImplementation($value) - { - if (isset(self::$_cacheTypes[$value])) - $this->_implementation = $value; - else - $this->_implementation = TPropertyValue::ensureEnum($value,'TSqlMapCacheTypes'); - } - - /** - * @param integer the number of seconds in which the cached value will expire. 0 means never expire. - */ - public function setFlushInterval($value) - { - $this->_flushInterval=TPropertyValue::ensureInteger($value); - } - - /** - * @return integer cache duration. - */ - public function getFlushInterval() - { - return $this->_flushInterval; - } - - /** - * Initialize the cache implementation, sets the actual cache contain if supplied. - * @param ISqLMapCache cache implementation instance. - */ - public function initialize($cache=null) - { - if($cache===null) - $this->_cache= Prado::createComponent($this->getImplementationClass(), $this); - else - $this->_cache=$cache; - } - - /** - * @return string cache implementation class name. - */ - public function getImplementationClass() - { - $implementation = $this->_implementation; - if (isset(self::$_cacheTypes[$implementation])) return self::$_cacheTypes[$implementation]; - - switch(TPropertyValue::ensureEnum($implementation,'TSqlMapCacheTypes')) - { - case TSqlMapCacheTypes::FIFO: return 'TSqlMapFifoCache'; - case TSqlMapCacheTypes::LRU : return 'TSqlMapLruCache'; - case TSqlMapCacheTypes::Basic : return 'TSqlMapApplicationCache'; - } - } - - /** - * Register a mapped statement that will trigger a cache flush. - * @param TMappedStatement mapped statement that may flush the cache. - */ - public function registerTriggerStatement($mappedStatement) - { - $mappedStatement->attachEventHandler('OnExecuteQuery',array($this, 'flush')); - } - - /** - * Clears the cache. - */ - public function flush() - { - $this->_cache->flush(); - } - - /** - * @param TSqlMapCacheKey|string cache key - * @return mixed cached value. - */ - public function get($key) - { - if($key instanceof TSqlMapCacheKey) - $key = $key->getHash(); - - //if flush ? - $value = $this->_cache->get($key); - $this->_requests++; - if($value!==null) - $this->_hits++; - return $value; - } - - /** - * @param TSqlMapCacheKey|string cache key - * @param mixed value to be cached. - */ - public function set($key, $value) - { - if($key instanceof TSqlMapCacheKey) - $key = $key->getHash(); - - if($value!==null) - $this->_cache->set($key, $value, $this->_flushInterval); - } - - /** - * @return float cache hit ratio. - */ - public function getHitRatio() - { - if($this->_requests != 0) - return $this->_hits / $this->_requests; - else - return 0; - } -} - -/** - * TSqlMapCacheTypes enumerable class. - * - * Implemented cache are 'Basic', 'FIFO' and 'LRU'. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - * @since 3.1 - */ -class TSqlMapCacheTypes extends TEnumerable -{ - const Basic='Basic'; - const FIFO='FIFO'; - const LRU='LRU'; -} - -/** - * TSqlMapCacheKey class. - * - * Provides a hash of the object to be cached. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - * @since 3.1 - */ -class TSqlMapCacheKey -{ - private $_key; - - /** - * @param mixed object to be cached. - */ - public function __construct($object) - { - $this->_key = $this->generateKey(serialize($object)); - } - - /** - * @param string serialized object - * @return string crc32 hash of the serialized object. - */ - protected function generateKey($string) - { - return sprintf('%x',crc32($string)); - } - - /** - * @return string object hash. - */ - public function getHash() - { - return $this->_key; - } -} - + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +/** + * TSqlMapCacheModel corresponds to the sql mapping configuration tag. + * + * The results from a query Mapped Statement can be cached simply by specifying + * the {@link CacheModel TSqlMapStatement::setCacheModel()} property in tag. + * A cache model is a configured cache that is defined within the sql map + * configuration file. Cache models are configured using the element. + * + * The cache model uses a pluggable framework for supporting different types of + * caches. The choice of cache is specified by the {@link Implementation setImplementation()} + * property. The class name specified must be one of {@link TSqlMapCacheTypes}. + * + * The cache implementations, LRU and FIFO cache below do not persist across + * requests. That is, once the request is complete, all cache data is lost. + * These caches are useful queries that results in the same repeated data during + * the current request. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapCacheModel extends TComponent +{ + private $_cache; + private $_hits = 0; + private $_requests = 0; + private $_id; + private $_implementation=TSqlMapCacheTypes::Basic; + private $_properties = array(); + private $_flushInterval = 0; + + private static $_cacheTypes = array(); + + public static function registerCacheType($type, $className) + { + self::$_cacheTypes[$type] = $className; + } + + /** + * @return string unique cache model identifier. + */ + public function getID() + { + return $this->_id; + } + + /** + * @param string unique cache model identifier. + */ + public function setID($value) + { + $this->_id = $value; + } + + /** + * @return string cache implements of TSqlMapCacheTypes, either 'Basic', 'LRU' or 'FIFO'. + */ + public function getImplementation() + { + return $this->_implementation; + } + + /** + * @param string cache implements of TSqlMapCacheTypes, either 'Basic', 'LRU' or 'FIFO'. + */ + public function setImplementation($value) + { + if (isset(self::$_cacheTypes[$value])) + $this->_implementation = $value; + else + $this->_implementation = TPropertyValue::ensureEnum($value,'TSqlMapCacheTypes'); + } + + /** + * @param integer the number of seconds in which the cached value will expire. 0 means never expire. + */ + public function setFlushInterval($value) + { + $this->_flushInterval=TPropertyValue::ensureInteger($value); + } + + /** + * @return integer cache duration. + */ + public function getFlushInterval() + { + return $this->_flushInterval; + } + + /** + * Initialize the cache implementation, sets the actual cache contain if supplied. + * @param ISqLMapCache cache implementation instance. + */ + public function initialize($cache=null) + { + if($cache===null) + $this->_cache= Prado::createComponent($this->getImplementationClass(), $this); + else + $this->_cache=$cache; + } + + /** + * @return string cache implementation class name. + */ + public function getImplementationClass() + { + $implementation = $this->_implementation; + if (isset(self::$_cacheTypes[$implementation])) return self::$_cacheTypes[$implementation]; + + switch(TPropertyValue::ensureEnum($implementation,'TSqlMapCacheTypes')) + { + case TSqlMapCacheTypes::FIFO: return 'TSqlMapFifoCache'; + case TSqlMapCacheTypes::LRU : return 'TSqlMapLruCache'; + case TSqlMapCacheTypes::Basic : return 'TSqlMapApplicationCache'; + } + } + + /** + * Register a mapped statement that will trigger a cache flush. + * @param TMappedStatement mapped statement that may flush the cache. + */ + public function registerTriggerStatement($mappedStatement) + { + $mappedStatement->attachEventHandler('OnExecuteQuery',array($this, 'flush')); + } + + /** + * Clears the cache. + */ + public function flush() + { + $this->_cache->flush(); + } + + /** + * @param TSqlMapCacheKey|string cache key + * @return mixed cached value. + */ + public function get($key) + { + if($key instanceof TSqlMapCacheKey) + $key = $key->getHash(); + + //if flush ? + $value = $this->_cache->get($key); + $this->_requests++; + if($value!==null) + $this->_hits++; + return $value; + } + + /** + * @param TSqlMapCacheKey|string cache key + * @param mixed value to be cached. + */ + public function set($key, $value) + { + if($key instanceof TSqlMapCacheKey) + $key = $key->getHash(); + + if($value!==null) + $this->_cache->set($key, $value, $this->_flushInterval); + } + + /** + * @return float cache hit ratio. + */ + public function getHitRatio() + { + if($this->_requests != 0) + return $this->_hits / $this->_requests; + else + return 0; + } +} + +/** + * TSqlMapCacheTypes enumerable class. + * + * Implemented cache are 'Basic', 'FIFO' and 'LRU'. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapCacheTypes extends TEnumerable +{ + const Basic='Basic'; + const FIFO='FIFO'; + const LRU='LRU'; +} + +/** + * TSqlMapCacheKey class. + * + * Provides a hash of the object to be cached. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapCacheKey +{ + private $_key; + + /** + * @param mixed object to be cached. + */ + public function __construct($object) + { + $this->_key = $this->generateKey(serialize($object)); + } + + /** + * @param string serialized object + * @return string crc32 hash of the serialized object. + */ + protected function generateKey($string) + { + return sprintf('%x',crc32($string)); + } + + /** + * @return string object hash. + */ + public function getHash() + { + return $this->_key; + } +} + diff --git a/framework/Data/SqlMap/Configuration/TSqlMapStatement.php b/framework/Data/SqlMap/Configuration/TSqlMapStatement.php index 1d90d4b1..8f2ca5cc 100644 --- a/framework/Data/SqlMap/Configuration/TSqlMapStatement.php +++ b/framework/Data/SqlMap/Configuration/TSqlMapStatement.php @@ -1,451 +1,451 @@ - - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Data.SqlMap.Configuration - */ - -/** - * TSqlMapStatement class corresponds to element. - * - * Mapped Statements can hold any SQL statement and can use Parameter Maps - * and Result Maps for input and output. - * - * The element is a general "catch all" element that can be used - * for any type of SQL statement. Generally it is a good idea to use one of the - * more specific statement-type elements. The more specific elements provided - * better error-checking and even more functionality. (For example, the insert - * statement can return a database-generated key.) - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - * @since 3.1 - */ -class TSqlMapStatement extends TComponent -{ - private $_parameterMapName; - private $_parameterMap; - private $_parameterClassName; - private $_resultMapName; - private $_resultMap; - private $_resultClassName; - private $_cacheModelName; - private $_SQL; - private $_listClass; - private $_typeHandler; - private $_extendStatement; - private $_cache; - private $_ID; - - /** - * @return string name for this statement, unique to each sql map manager. - */ - public function getID() - { - return $this->_ID; - } - - /** - * @param string name for this statement, which must be unique for each sql map manager. - */ - public function setID($value) - { - $this->_ID=$value; - } - - /** - * @return string name of a parameter map. - */ - public function getParameterMap() - { - return $this->_parameterMapName; - } - - /** - * A Parameter Map defines an ordered list of values that match up with - * the "?" placeholders of a standard, parameterized query statement. - * @param string parameter map name. - */ - public function setParameterMap($value) - { - $this->_parameterMapName = $value; - } - - /** - * @return string parameter class name. - */ - public function getParameterClass() - { - return $this->_parameterClassName; - } - - /** - * If a {@link ParameterMap setParameterMap()} property is not specified, - * you may specify a ParameterClass instead and use inline parameters. - * The value of the parameterClass attribute can be any existing PHP class name. - * @param string parameter class name. - */ - public function setParameterClass($value) - { - $this->_parameterClassName = $value; - } - - /** - * @return string result map name. - */ - public function getResultMap() - { - return $this->_resultMapName; - } - - /** - * A Result Map lets you control how data is extracted from the result of a - * query, and how the columns are mapped to object properties. - * @param string result map name. - */ - public function setResultMap($value) - { - $this->_resultMapName = $value; - } - - /** - * @return string result class name. - */ - public function getResultClass() - { - return $this->_resultClassName; - } - - /** - * If a {@link ResultMap setResultMap()} is not specified, you may specify a - * ResultClass instead. The value of the ResultClass property can be the - * name of a PHP class or primitives like integer, string, or array. The - * class specified will be automatically mapped to the columns in the - * result, based on the result metadata. - * @param string result class name. - */ - public function setResultClass($value) - { - $this->_resultClassName = $value; - } - - /** - * @return string cache mode name. - */ - public function getCacheModel() - { - return $this->_cacheModelName; - } - - /** - * @param string cache mode name. - */ - public function setCacheModel($value) - { - $this->_cacheModelName = $value; - } - - /** - * @return TSqlMapCacheModel cache implementation instance for this statement. - */ - public function getCache() - { - return $this->_cache; - } - - /** - * @param TSqlMapCacheModel cache implementation instance for this statement. - */ - public function setCache($value) - { - $this->_cache = $value; - } - - /** - * @return TStaticSql sql text container. - */ - public function getSqlText() - { - return $this->_SQL; - } - - /** - * @param TStaticSql sql text container. - */ - public function setSqlText($value) - { - $this->_SQL = $value; - } - - /** - * @return string name of a PHP class that implements ArrayAccess. - */ - public function getListClass() - { - return $this->_listClass; - } - - /** - * An ArrayAccess class can be specified to handle the type of objects in the collection. - * @param string name of a PHP class that implements ArrayAccess. - */ - public function setListClass($value) - { - $this->_listClass = $value; - } - - /** - * @return string another statement element name. - */ - public function getExtends() - { - return $this->_extendStatement; - } - - /** - * @param string name of another statement element to extend. - */ - public function setExtends($value) - { - $this->_extendStatement = $value; - } - - /** - * @return TResultMap the result map corresponding to the - * {@link ResultMap getResultMap()} property. - */ - public function resultMap() - { - return $this->_resultMap; - } - - /** - * @return TParameterMap the parameter map corresponding to the - * {@link ParameterMap getParameterMap()} property. - */ - public function parameterMap() - { - return $this->_parameterMap; - } - - /** - * @param TInlineParameterMap parameter extracted from the sql text. - */ - public function setInlineParameterMap($map) - { - $this->_parameterMap = $map; - } - - /** - * @param TSqlMapManager initialize the statement, sets the result and parameter maps. - */ - public function initialize($manager) - { - if(strlen($this->_resultMapName) > 0) - $this->_resultMap = $manager->getResultMap($this->_resultMapName); - if(strlen($this->_parameterMapName) > 0) - $this->_parameterMap = $manager->getParameterMap($this->_parameterMapName); - } - - /** - * @param TSqlMapTypeHandlerRegistry type handler registry - * @return ArrayAccess new instance of list class. - */ - public function createInstanceOfListClass($registry) - { - if(strlen($type = $this->getListClass()) > 0) - return $this->createInstanceOf($registry,$type); - return array(); - } - - /** - * Create a new instance of a given type. - * @param TSqlMapTypeHandlerRegistry type handler registry - * @param string result class name. - * @param array result data. - * @return mixed result object. - */ - protected function createInstanceOf($registry,$type,$row=null) - { - $handler = $registry->getTypeHandler($type); - if($handler!==null) - return $handler->createNewInstance($row); - else - return $registry->createInstanceOf($type); - } - - /** - * Create a new instance of result class. - * @param TSqlMapTypeHandlerRegistry type handler registry - * @param array result data. - * @return mixed result object. - */ - public function createInstanceOfResultClass($registry,$row) - { - if(strlen($type= $this->getResultClass()) > 0) - return $this->createInstanceOf($registry,$type,$row); - } - - public function __sleep() - { - $cn = __CLASS__; - $exprops = array("\0$cn\0_resultMap"); - if (!$this->_parameterMapName) $exprops[] = "\0$cn\0_parameterMapName"; - if (!$this->_parameterMap) $exprops[] = "\0$cn\0_parameterMap"; - if (!$this->_parameterClassName) $exprops[] = "\0$cn\0_parameterClassName"; - if (!$this->_resultMapName) $exprops[] = "\0$cn\0_resultMapName"; - if (!$this->_resultMap) $exprops[] = "\0$cn\0_resultMap"; - if (!$this->_resultClassName) $exprops[] = "\0$cn\0_resultClassName"; - if (!$this->_cacheModelName) $exprops[] = "\0$cn\0_cacheModelName"; - if (!$this->_SQL) $exprops[] = "\0$cn\0_SQL"; - if (!$this->_listClass) $exprops[] = "\0$cn\0_listClass"; - if (!$this->_typeHandler) $exprops[] = "\0$cn\0_typeHandler"; - if (!$this->_extendStatement) $exprops[] = "\0$cn\0_extendStatement"; - if (!$this->_cache) $exprops[] = "\0$cn\0_cache"; - - return array_diff(parent::__sleep(),$exprops); - } - -} - -/** - * TSqlMapSelect class file. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Statements - * @since 3.1 - */ -class TSqlMapSelect extends TSqlMapStatement -{ - private $_generate; - - public function getGenerate(){ return $this->_generate; } - public function setGenerate($value){ $this->_generate = $value; } -} - -/** - * TSqlMapInsert class corresponds to the element. - * - * The element allows child elements that can be used - * to generate a key to be used for the insert command. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - * @since 3.1 - */ -class TSqlMapInsert extends TSqlMapStatement -{ - private $_selectKey=null; - - /** - * @return TSqlMapSelectKey select key element. - */ - public function getSelectKey() - { - return $this->_selectKey; - } - - /** - * @param TSqlMapSelectKey select key. - */ - public function setSelectKey($value) - { - $this->_selectKey = $value; - } -} - -/** - * TSqlMapUpdate class corresponds to element. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - * @since 3.1 - */ -class TSqlMapUpdate extends TSqlMapStatement -{ -} - -/** - * TSqlMapDelete class corresponds to the element. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - * @since 3.1 - */ -class TSqlMapDelete extends TSqlMapUpdate -{ -} - -/** - * TSqlMapSelect corresponds to the element. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - * @since 3.1 - */ -class TSqlMapSelectKey extends TSqlMapStatement -{ - private $_type = 'post'; - private $_property; - - /** - * @return string select generated key type, 'post' or 'pre'. - */ - public function getType() - { - return $this->_type; - } - - /** - * @param string select generated key type, 'post' or 'pre'. - */ - public function setType($value) - { - $this->_type = strtolower($value) == 'post' ? 'post' : 'pre'; - } - - /** - * @return string property name for the generated key. - */ - public function getProperty() - { - return $this->_property; - } - - /** - * @param string property name for the generated key. - */ - public function setProperty($value) - { - $this->_property = $value; - } - - /** - * @throws TSqlMapConfigurationException extends is unsupported. - */ - public function setExtends($value) - { - throw new TSqlMapConfigurationException('sqlmap_can_not_extend_select_key'); - } - - /** - * @return boolean true if key is generated after insert command, false otherwise. - */ - public function getIsAfter() - { - return $this->_type == 'post'; - } -} - + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +/** + * TSqlMapStatement class corresponds to element. + * + * Mapped Statements can hold any SQL statement and can use Parameter Maps + * and Result Maps for input and output. + * + * The element is a general "catch all" element that can be used + * for any type of SQL statement. Generally it is a good idea to use one of the + * more specific statement-type elements. The more specific elements provided + * better error-checking and even more functionality. (For example, the insert + * statement can return a database-generated key.) + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapStatement extends TComponent +{ + private $_parameterMapName; + private $_parameterMap; + private $_parameterClassName; + private $_resultMapName; + private $_resultMap; + private $_resultClassName; + private $_cacheModelName; + private $_SQL; + private $_listClass; + private $_typeHandler; + private $_extendStatement; + private $_cache; + private $_ID; + + /** + * @return string name for this statement, unique to each sql map manager. + */ + public function getID() + { + return $this->_ID; + } + + /** + * @param string name for this statement, which must be unique for each sql map manager. + */ + public function setID($value) + { + $this->_ID=$value; + } + + /** + * @return string name of a parameter map. + */ + public function getParameterMap() + { + return $this->_parameterMapName; + } + + /** + * A Parameter Map defines an ordered list of values that match up with + * the "?" placeholders of a standard, parameterized query statement. + * @param string parameter map name. + */ + public function setParameterMap($value) + { + $this->_parameterMapName = $value; + } + + /** + * @return string parameter class name. + */ + public function getParameterClass() + { + return $this->_parameterClassName; + } + + /** + * If a {@link ParameterMap setParameterMap()} property is not specified, + * you may specify a ParameterClass instead and use inline parameters. + * The value of the parameterClass attribute can be any existing PHP class name. + * @param string parameter class name. + */ + public function setParameterClass($value) + { + $this->_parameterClassName = $value; + } + + /** + * @return string result map name. + */ + public function getResultMap() + { + return $this->_resultMapName; + } + + /** + * A Result Map lets you control how data is extracted from the result of a + * query, and how the columns are mapped to object properties. + * @param string result map name. + */ + public function setResultMap($value) + { + $this->_resultMapName = $value; + } + + /** + * @return string result class name. + */ + public function getResultClass() + { + return $this->_resultClassName; + } + + /** + * If a {@link ResultMap setResultMap()} is not specified, you may specify a + * ResultClass instead. The value of the ResultClass property can be the + * name of a PHP class or primitives like integer, string, or array. The + * class specified will be automatically mapped to the columns in the + * result, based on the result metadata. + * @param string result class name. + */ + public function setResultClass($value) + { + $this->_resultClassName = $value; + } + + /** + * @return string cache mode name. + */ + public function getCacheModel() + { + return $this->_cacheModelName; + } + + /** + * @param string cache mode name. + */ + public function setCacheModel($value) + { + $this->_cacheModelName = $value; + } + + /** + * @return TSqlMapCacheModel cache implementation instance for this statement. + */ + public function getCache() + { + return $this->_cache; + } + + /** + * @param TSqlMapCacheModel cache implementation instance for this statement. + */ + public function setCache($value) + { + $this->_cache = $value; + } + + /** + * @return TStaticSql sql text container. + */ + public function getSqlText() + { + return $this->_SQL; + } + + /** + * @param TStaticSql sql text container. + */ + public function setSqlText($value) + { + $this->_SQL = $value; + } + + /** + * @return string name of a PHP class that implements ArrayAccess. + */ + public function getListClass() + { + return $this->_listClass; + } + + /** + * An ArrayAccess class can be specified to handle the type of objects in the collection. + * @param string name of a PHP class that implements ArrayAccess. + */ + public function setListClass($value) + { + $this->_listClass = $value; + } + + /** + * @return string another statement element name. + */ + public function getExtends() + { + return $this->_extendStatement; + } + + /** + * @param string name of another statement element to extend. + */ + public function setExtends($value) + { + $this->_extendStatement = $value; + } + + /** + * @return TResultMap the result map corresponding to the + * {@link ResultMap getResultMap()} property. + */ + public function resultMap() + { + return $this->_resultMap; + } + + /** + * @return TParameterMap the parameter map corresponding to the + * {@link ParameterMap getParameterMap()} property. + */ + public function parameterMap() + { + return $this->_parameterMap; + } + + /** + * @param TInlineParameterMap parameter extracted from the sql text. + */ + public function setInlineParameterMap($map) + { + $this->_parameterMap = $map; + } + + /** + * @param TSqlMapManager initialize the statement, sets the result and parameter maps. + */ + public function initialize($manager) + { + if(strlen($this->_resultMapName) > 0) + $this->_resultMap = $manager->getResultMap($this->_resultMapName); + if(strlen($this->_parameterMapName) > 0) + $this->_parameterMap = $manager->getParameterMap($this->_parameterMapName); + } + + /** + * @param TSqlMapTypeHandlerRegistry type handler registry + * @return ArrayAccess new instance of list class. + */ + public function createInstanceOfListClass($registry) + { + if(strlen($type = $this->getListClass()) > 0) + return $this->createInstanceOf($registry,$type); + return array(); + } + + /** + * Create a new instance of a given type. + * @param TSqlMapTypeHandlerRegistry type handler registry + * @param string result class name. + * @param array result data. + * @return mixed result object. + */ + protected function createInstanceOf($registry,$type,$row=null) + { + $handler = $registry->getTypeHandler($type); + if($handler!==null) + return $handler->createNewInstance($row); + else + return $registry->createInstanceOf($type); + } + + /** + * Create a new instance of result class. + * @param TSqlMapTypeHandlerRegistry type handler registry + * @param array result data. + * @return mixed result object. + */ + public function createInstanceOfResultClass($registry,$row) + { + if(strlen($type= $this->getResultClass()) > 0) + return $this->createInstanceOf($registry,$type,$row); + } + + public function __sleep() + { + $cn = __CLASS__; + $exprops = array("\0$cn\0_resultMap"); + if (!$this->_parameterMapName) $exprops[] = "\0$cn\0_parameterMapName"; + if (!$this->_parameterMap) $exprops[] = "\0$cn\0_parameterMap"; + if (!$this->_parameterClassName) $exprops[] = "\0$cn\0_parameterClassName"; + if (!$this->_resultMapName) $exprops[] = "\0$cn\0_resultMapName"; + if (!$this->_resultMap) $exprops[] = "\0$cn\0_resultMap"; + if (!$this->_resultClassName) $exprops[] = "\0$cn\0_resultClassName"; + if (!$this->_cacheModelName) $exprops[] = "\0$cn\0_cacheModelName"; + if (!$this->_SQL) $exprops[] = "\0$cn\0_SQL"; + if (!$this->_listClass) $exprops[] = "\0$cn\0_listClass"; + if (!$this->_typeHandler) $exprops[] = "\0$cn\0_typeHandler"; + if (!$this->_extendStatement) $exprops[] = "\0$cn\0_extendStatement"; + if (!$this->_cache) $exprops[] = "\0$cn\0_cache"; + + return array_diff(parent::__sleep(),$exprops); + } + +} + +/** + * TSqlMapSelect class file. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Statements + * @since 3.1 + */ +class TSqlMapSelect extends TSqlMapStatement +{ + private $_generate; + + public function getGenerate(){ return $this->_generate; } + public function setGenerate($value){ $this->_generate = $value; } +} + +/** + * TSqlMapInsert class corresponds to the element. + * + * The element allows child elements that can be used + * to generate a key to be used for the insert command. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapInsert extends TSqlMapStatement +{ + private $_selectKey=null; + + /** + * @return TSqlMapSelectKey select key element. + */ + public function getSelectKey() + { + return $this->_selectKey; + } + + /** + * @param TSqlMapSelectKey select key. + */ + public function setSelectKey($value) + { + $this->_selectKey = $value; + } +} + +/** + * TSqlMapUpdate class corresponds to element. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapUpdate extends TSqlMapStatement +{ +} + +/** + * TSqlMapDelete class corresponds to the element. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapDelete extends TSqlMapUpdate +{ +} + +/** + * TSqlMapSelect corresponds to the element. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapSelectKey extends TSqlMapStatement +{ + private $_type = 'post'; + private $_property; + + /** + * @return string select generated key type, 'post' or 'pre'. + */ + public function getType() + { + return $this->_type; + } + + /** + * @param string select generated key type, 'post' or 'pre'. + */ + public function setType($value) + { + $this->_type = strtolower($value) == 'post' ? 'post' : 'pre'; + } + + /** + * @return string property name for the generated key. + */ + public function getProperty() + { + return $this->_property; + } + + /** + * @param string property name for the generated key. + */ + public function setProperty($value) + { + $this->_property = $value; + } + + /** + * @throws TSqlMapConfigurationException extends is unsupported. + */ + public function setExtends($value) + { + throw new TSqlMapConfigurationException('sqlmap_can_not_extend_select_key'); + } + + /** + * @return boolean true if key is generated after insert command, false otherwise. + */ + public function getIsAfter() + { + return $this->_type == 'post'; + } +} + diff --git a/framework/Data/SqlMap/Configuration/TSqlMapXmlConfiguration.php b/framework/Data/SqlMap/Configuration/TSqlMapXmlConfiguration.php index a60827fe..988d00db 100644 --- a/framework/Data/SqlMap/Configuration/TSqlMapXmlConfiguration.php +++ b/framework/Data/SqlMap/Configuration/TSqlMapXmlConfiguration.php @@ -1,805 +1,805 @@ - - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2012 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Data.SqlMap.Configuration - */ - -Prado::using('System.Data.SqlMap.Configuration.TSqlMapStatement'); - -/** - * TSqlMapXmlConfig class file. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - */ -abstract class TSqlMapXmlConfigBuilder -{ - /** - * Create an instance of an object give by the attribute named 'class' in the - * node and set the properties on the object given by attribute names and values. - * @param SimpleXmlNode property node - * @return Object new instance of class with class name given by 'class' attribute value. - */ - protected function createObjectFromNode($node) - { - if(isset($node['class'])) - { - $obj = Prado::createComponent((string)$node['class']); - $this->setObjectPropFromNode($obj,$node,array('class')); - return $obj; - } - throw new TSqlMapConfigurationException( - 'sqlmap_node_class_undef', $node, $this->getConfigFile()); - } - - /** - * For each attributes (excluding attribute named in $except) set the - * property of the $obj given by the name of the attribute with the value - * of the attribute. - * @param Object object instance - * @param SimpleXmlNode property node - * @param array exception property name - */ - protected function setObjectPropFromNode($obj,$node,$except=array()) - { - foreach($node->attributes() as $name=>$value) - { - if(!in_array($name,$except)) - { - if($obj->canSetProperty($name)) - $obj->{$name} = (string)$value; - else - throw new TSqlMapConfigurationException( - 'sqlmap_invalid_property', $name, get_class($obj), - $node, $this->getConfigFile()); - } - } - } - - /** - * Gets the filename relative to the basefile. - * @param string base filename - * @param string relative filename - * @return string absolute filename. - */ - protected function getAbsoluteFilePath($basefile,$resource) - { - $basedir = dirname($basefile); - $file = realpath($basedir.DIRECTORY_SEPARATOR.$resource); - if(!is_string($file) || !is_file($file)) - $file = realpath($resource); - if(is_string($file) && is_file($file)) - return $file; - else - throw new TSqlMapConfigurationException( - 'sqlmap_unable_to_find_resource', $resource); - } - - /** - * Load document using simple xml. - * @param string filename. - * @return SimpleXmlElement xml document. - */ - protected function loadXmlDocument($filename,TSqlMapXmlConfiguration $config) - { - if( strpos($filename, '${') !== false) - $filename = $config->replaceProperties($filename); - - if(!is_file($filename)) - throw new TSqlMapConfigurationException( - 'sqlmap_unable_to_find_config', $filename); - return simplexml_load_string($config->replaceProperties(file_get_contents($filename))); - } - - /** - * Get element node by ID value (try for attribute name ID as case insensitive). - * @param SimpleXmlDocument $document - * @param string tag name. - * @param string id value. - * @return SimpleXmlElement node if found, null otherwise. - */ - protected function getElementByIdValue($document, $tag, $value) - { - //hack to allow upper case and lower case attribute names. - foreach(array('id','ID','Id', 'iD') as $id) - { - $xpath = "//{$tag}[@{$id}='{$value}']"; - foreach($document->xpath($xpath) as $node) - return $node; - } - } - - /** - * @return string configuration file. - */ - protected abstract function getConfigFile(); -} - -/** - * TSqlMapXmlConfig class. - * - * Configures the TSqlMapManager using xml configuration file. - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - * @since 3.1 - */ -class TSqlMapXmlConfiguration extends TSqlMapXmlConfigBuilder -{ - /** - * @var TSqlMapManager manager - */ - private $_manager; - /** - * @var string configuration file. - */ - private $_configFile; - /** - * @var array global properties. - */ - private $_properties=array(); - - /** - * @param TSqlMapManager manager instance. - */ - public function __construct($manager) - { - $this->_manager=$manager; - } - - public function getManager() - { - return $this->_manager; - } - - protected function getConfigFile() - { - return $this->_configFile; - } - - /** - * Configure the TSqlMapManager using the given xml file. - * @param string SqlMap configuration xml file. - */ - public function configure($filename=null) - { - $this->_configFile=$filename; - $document = $this->loadXmlDocument($filename,$this); - - foreach($document->xpath('//property') as $property) - $this->loadGlobalProperty($property); - - foreach($document->xpath('//typeHandler') as $handler) - $this->loadTypeHandler($handler); - - foreach($document->xpath('//connection[last()]') as $conn) - $this->loadDatabaseConnection($conn); - - //try to load configuration in the current config file. - $mapping = new TSqlMapXmlMappingConfiguration($this); - $mapping->configure($filename); - - foreach($document->xpath('//sqlMap') as $sqlmap) - $this->loadSqlMappingFiles($sqlmap); - - $this->resolveResultMapping(); - $this->attachCacheModels(); - } - - /** - * Load global replacement property. - * @param SimpleXmlElement property node. - */ - protected function loadGlobalProperty($node) - { - $this->_properties[(string)$node['name']] = (string)$node['value']; - } - - /** - * Load the type handler configurations. - * @param SimpleXmlElement type handler node - */ - protected function loadTypeHandler($node) - { - $handler = $this->createObjectFromNode($node); - $this->_manager->getTypeHandlers()->registerTypeHandler($handler); - } - - /** - * Load the database connection tag. - * @param SimpleXmlElement connection node. - */ - protected function loadDatabaseConnection($node) - { - $conn = $this->createObjectFromNode($node); - $this->_manager->setDbConnection($conn); - } - - /** - * Load SqlMap mapping configuration. - * @param unknown_type $node - */ - protected function loadSqlMappingFiles($node) - { - if(strlen($resource = (string)$node['resource']) > 0) - { - if( strpos($resource, '${') !== false) - $resource = $this->replaceProperties($resource); - - $mapping = new TSqlMapXmlMappingConfiguration($this); - $filename = $this->getAbsoluteFilePath($this->_configFile, $resource); - $mapping->configure($filename); - } - } - - /** - * Resolve nest result mappings. - */ - protected function resolveResultMapping() - { - $maps = $this->_manager->getResultMaps(); - foreach($maps as $entry) - { - foreach($entry->getColumns() as $item) - { - $resultMap = $item->getResultMapping(); - if(strlen($resultMap) > 0) - { - if($maps->contains($resultMap)) - $item->setNestedResultMap($maps[$resultMap]); - else - throw new TSqlMapConfigurationException( - 'sqlmap_unable_to_find_result_mapping', - $resultMap, $this->_configFile, $entry->getID()); - } - } - if($entry->getDiscriminator()!==null) - $entry->getDiscriminator()->initialize($this->_manager); - } - } - - /** - * Set the cache for each statement having a cache model property. - */ - protected function attachCacheModels() - { - foreach($this->_manager->getMappedStatements() as $mappedStatement) - { - if(strlen($model = $mappedStatement->getStatement()->getCacheModel()) > 0) - { - $cache = $this->_manager->getCacheModel($model); - $mappedStatement->getStatement()->setCache($cache); - } - } - } - - /** - * Replace the place holders ${name} in text with properties the - * corresponding global property value. - * @param string original string. - * @return string string with global property replacement. - */ - public function replaceProperties($string) - { - foreach($this->_properties as $find => $replace) - $string = str_replace('${'.$find.'}', $replace, $string); - return $string; - } -} - -/** - * Loads the statements, result maps, parameters maps from xml configuration. - * - * description - * - * @author Wei Zhuo - * @version $Id$ - * @package System.Data.SqlMap.Configuration - * @since 3.1 - */ -class TSqlMapXmlMappingConfiguration extends TSqlMapXmlConfigBuilder -{ - private $_xmlConfig; - private $_configFile; - private $_manager; - - private $_document; - - private $_FlushOnExecuteStatements=array(); - - /** - * Regular expressions for escaping simple/inline parameter symbols - */ - const SIMPLE_MARK='$'; - const INLINE_SYMBOL='#'; - const ESCAPED_SIMPLE_MARK_REGEXP='/\$\$/'; - const ESCAPED_INLINE_SYMBOL_REGEXP='/\#\#/'; - const SIMPLE_PLACEHOLDER='`!!`'; - const INLINE_PLACEHOLDER='`!!!`'; - - /** - * @param TSqlMapXmlConfiguration parent xml configuration. - */ - public function __construct(TSqlMapXmlConfiguration $xmlConfig) - { - $this->_xmlConfig=$xmlConfig; - $this->_manager=$xmlConfig->getManager(); - } - - protected function getConfigFile() - { - return $this->_configFile; - } - - /** - * Configure an XML mapping. - * @param string xml mapping filename. - */ - public function configure($filename) - { - $this->_configFile=$filename; - $document = $this->loadXmlDocument($filename,$this->_xmlConfig); - $this->_document=$document; - - static $bCacheDependencies; - if($bCacheDependencies === null) - $bCacheDependencies = Prado::getApplication()->getMode() !== TApplicationMode::Performance; - - if($bCacheDependencies) - $this->_manager->getCacheDependencies() - ->getDependencies() - ->add(new TFileCacheDependency($filename)); - - foreach($document->xpath('//resultMap') as $node) - $this->loadResultMap($node); - - foreach($document->xpath('//parameterMap') as $node) - $this->loadParameterMap($node); - - foreach($document->xpath('//statement') as $node) - $this->loadStatementTag($node); - - foreach($document->xpath('//select') as $node) - $this->loadSelectTag($node); - - foreach($document->xpath('//insert') as $node) - $this->loadInsertTag($node); - - foreach($document->xpath('//update') as $node) - $this->loadUpdateTag($node); - - foreach($document->xpath('//delete') as $node) - $this->loadDeleteTag($node); - - foreach($document->xpath('//procedure') as $node) - $this->loadProcedureTag($node); - - foreach($document->xpath('//cacheModel') as $node) - $this->loadCacheModel($node); - - $this->registerCacheTriggers(); - } - - /** - * Load the result maps. - * @param SimpleXmlElement result map node. - */ - protected function loadResultMap($node) - { - $resultMap = $this->createResultMap($node); - - //find extended result map. - if(strlen($extendMap = $resultMap->getExtends()) > 0) - { - if(!$this->_manager->getResultMaps()->contains($extendMap)) - { - $extendNode=$this->getElementByIdValue($this->_document,'resultMap',$extendMap); - if($extendNode!==null) - $this->loadResultMap($extendNode); - } - - if(!$this->_manager->getResultMaps()->contains($extendMap)) - throw new TSqlMapConfigurationException( - 'sqlmap_unable_to_find_parent_result_map', $node, $this->_configFile, $extendMap); - - $superMap = $this->_manager->getResultMap($extendMap); - $resultMap->getColumns()->mergeWith($superMap->getColumns()); - } - - //add the result map - if(!$this->_manager->getResultMaps()->contains($resultMap->getID())) - $this->_manager->addResultMap($resultMap); - } - - /** - * Create a new result map and its associated result properties, - * disciminiator and sub maps. - * @param SimpleXmlElement result map node - * @return TResultMap SqlMap result mapping. - */ - protected function createResultMap($node) - { - $resultMap = new TResultMap(); - $this->setObjectPropFromNode($resultMap,$node); - - //result nodes - foreach($node->result as $result) - { - $property = new TResultProperty($resultMap); - $this->setObjectPropFromNode($property,$result); - $resultMap->addResultProperty($property); - } - - //create the discriminator - $discriminator = null; - if(isset($node->discriminator)) - { - $discriminator = new TDiscriminator(); - $this->setObjectPropFromNode($discriminator, $node->discriminator); - $discriminator->initMapping($resultMap); - } - - foreach($node->xpath('subMap') as $subMapNode) - { - if($discriminator===null) - throw new TSqlMapConfigurationException( - 'sqlmap_undefined_discriminator', $node, $this->_configFile,$subMapNode); - $subMap = new TSubMap; - $this->setObjectPropFromNode($subMap,$subMapNode); - $discriminator->addSubMap($subMap); - } - - if($discriminator!==null) - $resultMap->setDiscriminator($discriminator); - - return $resultMap; - } - - /** - * Load parameter map from xml. - * - * @param SimpleXmlElement parameter map node. - */ - protected function loadParameterMap($node) - { - $parameterMap = $this->createParameterMap($node); - - if(strlen($extendMap = $parameterMap->getExtends()) > 0) - { - if(!$this->_manager->getParameterMaps()->contains($extendMap)) - { - $extendNode=$this->getElementByIdValue($this->_document,'parameterMap',$extendMap); - if($extendNode!==null) - $this->loadParameterMap($extendNode); - } - - if(!$this->_manager->getParameterMaps()->contains($extendMap)) - throw new TSqlMapConfigurationException( - 'sqlmap_unable_to_find_parent_parameter_map', $node, $this->_configFile,$extendMap); - $superMap = $this->_manager->getParameterMap($extendMap); - $index = 0; - foreach($superMap->getPropertyNames() as $propertyName) - $parameterMap->insertProperty($index++,$superMap->getProperty($propertyName)); - } - $this->_manager->addParameterMap($parameterMap); - } - - /** - * Create a new parameter map from xml node. - * @param SimpleXmlElement parameter map node. - * @return TParameterMap new parameter mapping. - */ - protected function createParameterMap($node) - { - $parameterMap = new TParameterMap(); - $this->setObjectPropFromNode($parameterMap,$node); - foreach($node->parameter as $parameter) - { - $property = new TParameterProperty(); - $this->setObjectPropFromNode($property,$parameter); - $parameterMap->addProperty($property); - } - return $parameterMap; - } - - /** - * Load statement mapping from xml configuration file. - * @param SimpleXmlElement statement node. - */ - protected function loadStatementTag($node) - { - $statement = new TSqlMapStatement(); - $this->setObjectPropFromNode($statement,$node); - $this->processSqlStatement($statement, $node); - $mappedStatement = new TMappedStatement($this->_manager, $statement); - $this->_manager->addMappedStatement($mappedStatement); - } - - /** - * Load extended SQL statements if application. Replaces global properties - * in the sql text. Extracts inline parameter maps. - * @param TSqlMapStatement mapped statement. - * @param SimpleXmlElement statement node. - */ - protected function processSqlStatement($statement, $node) - { - $commandText = (string)$node; - if(strlen($extend = $statement->getExtends()) > 0) - { - $superNode = $this->getElementByIdValue($this->_document,'*',$extend); - if($superNode!==null) - $commandText = (string)$superNode . $commandText; - else - throw new TSqlMapConfigurationException( - 'sqlmap_unable_to_find_parent_sql', $extend, $this->_configFile,$node); - } - //$commandText = $this->_xmlConfig->replaceProperties($commandText); - $statement->initialize($this->_manager); - $this->applyInlineParameterMap($statement, $commandText, $node); - } - - /** - * Extract inline parameter maps. - * @param TSqlMapStatement statement object. - * @param string sql text - * @param SimpleXmlElement statement node. - */ - protected function applyInlineParameterMap($statement, $sqlStatement, $node) - { - $scope['file'] = $this->_configFile; - $scope['node'] = $node; - - $sqlStatement=preg_replace(self::ESCAPED_INLINE_SYMBOL_REGEXP,self::INLINE_PLACEHOLDER,$sqlStatement); - if($statement->parameterMap() === null) - { - // Build a Parametermap with the inline parameters. - // if they exist. Then delete inline infos from sqltext. - $parameterParser = new TInlineParameterMapParser; - $sqlText = $parameterParser->parse($sqlStatement, $scope); - if(count($sqlText['parameters']) > 0) - { - $map = new TParameterMap(); - $map->setID($statement->getID().'-InLineParameterMap'); - $statement->setInlineParameterMap($map); - foreach($sqlText['parameters'] as $property) - $map->addProperty($property); - } - $sqlStatement = $sqlText['sql']; - } - $sqlStatement=preg_replace('/'.self::INLINE_PLACEHOLDER.'/',self::INLINE_SYMBOL,$sqlStatement); - - $this->prepareSql($statement, $sqlStatement, $node); - } - - /** - * Prepare the sql text (may extend to dynamic sql). - * @param TSqlMapStatement mapped statement. - * @param string sql text. - * @param SimpleXmlElement statement node. - * @todo Extend to dynamic sql. - */ - protected function prepareSql($statement,$sqlStatement, $node) - { - $simpleDynamic = new TSimpleDynamicParser; - $sqlStatement=preg_replace(self::ESCAPED_SIMPLE_MARK_REGEXP,self::SIMPLE_PLACEHOLDER,$sqlStatement); - $dynamics = $simpleDynamic->parse($sqlStatement); - if(count($dynamics['parameters']) > 0) - { - $sql = new TSimpleDynamicSql($dynamics['parameters']); - $sqlStatement = $dynamics['sql']; - } - else - $sql = new TStaticSql(); - $sqlStatement=preg_replace('/'.self::SIMPLE_PLACEHOLDER.'/',self::SIMPLE_MARK,$sqlStatement); - $sql->buildPreparedStatement($statement, $sqlStatement); - $statement->setSqlText($sql); - } - - /** - * Load select statement from xml mapping. - * @param SimpleXmlElement select node. - */ - protected function loadSelectTag($node) - { - $select = new TSqlMapSelect; - $this->setObjectPropFromNode($select,$node); - $this->processSqlStatement($select,$node); - $mappedStatement = new TMappedStatement($this->_manager, $select); - if(strlen($select->getCacheModel()) > 0) - $mappedStatement = new TCachingStatement($mappedStatement); - - $this->_manager->addMappedStatement($mappedStatement); - } - - /** - * Load insert statement from xml mapping. - * @param SimpleXmlElement insert node. - */ - protected function loadInsertTag($node) - { - $insert = $this->createInsertStatement($node); - $this->processSqlStatement($insert, $node); - $mappedStatement = new TInsertMappedStatement($this->_manager, $insert); - $this->_manager->addMappedStatement($mappedStatement); - } - - /** - * Create new insert statement from xml node. - * @param SimpleXmlElement insert node. - * @return TSqlMapInsert insert statement. - */ - protected function createInsertStatement($node) - { - $insert = new TSqlMapInsert; - $this->setObjectPropFromNode($insert,$node); - if(isset($node->selectKey)) - $this->loadSelectKeyTag($insert,$node->selectKey); - return $insert; - } - - /** - * Load the selectKey statement from xml mapping. - * @param SimpleXmlElement selectkey node - */ - protected function loadSelectKeyTag($insert, $node) - { - $selectKey = new TSqlMapSelectKey; - $this->setObjectPropFromNode($selectKey,$node); - $selectKey->setID($insert->getID()); - $selectKey->setID($insert->getID().'.SelectKey'); - $this->processSqlStatement($selectKey,$node); - $insert->setSelectKey($selectKey); - $mappedStatement = new TMappedStatement($this->_manager, $selectKey); - $this->_manager->addMappedStatement($mappedStatement); - } - - /** - * Load update statement from xml mapping. - * @param SimpleXmlElement update node. - */ - protected function loadUpdateTag($node) - { - $update = new TSqlMapUpdate; - $this->setObjectPropFromNode($update,$node); - $this->processSqlStatement($update, $node); - $mappedStatement = new TUpdateMappedStatement($this->_manager, $update); - $this->_manager->addMappedStatement($mappedStatement); - } - - /** - * Load delete statement from xml mapping. - * @param SimpleXmlElement delete node. - */ - protected function loadDeleteTag($node) - { - $delete = new TSqlMapDelete; - $this->setObjectPropFromNode($delete,$node); - $this->processSqlStatement($delete, $node); - $mappedStatement = new TDeleteMappedStatement($this->_manager, $delete); - $this->_manager->addMappedStatement($mappedStatement); - } - - /** - * Load procedure statement from xml mapping. - * @todo Implement loading procedure - * @param SimpleXmlElement procedure node - */ - protected function loadProcedureTag($node) - { - //var_dump('todo: add load procedure'); - } - - /** - * Load cache models from xml mapping. - * @param SimpleXmlElement cache node. - */ - protected function loadCacheModel($node) - { - $cacheModel = new TSqlMapCacheModel; - $properties = array('id','implementation'); - foreach($node->attributes() as $name=>$value) - { - if(in_array(strtolower($name), $properties)) - $cacheModel->{'set'.$name}((string)$value); - } - $cache = Prado::createComponent($cacheModel->getImplementationClass(), $cacheModel); - $this->setObjectPropFromNode($cache,$node,$properties); - - foreach($node->xpath('property') as $propertyNode) - { - $name = $propertyNode->attributes()->name; - if($name===null || $name==='') continue; - - $value = $propertyNode->attributes()->value; - if($value===null || $value==='') continue; - - if( !TPropertyAccess::has($cache, $name) ) continue; - - TPropertyAccess::set($cache, $name, $value); - } - - $this->loadFlushInterval($cacheModel,$node); - - $cacheModel->initialize($cache); - $this->_manager->addCacheModel($cacheModel); - foreach($node->xpath('flushOnExecute') as $flush) - $this->loadFlushOnCache($cacheModel,$node,$flush); - } - - /** - * Load the flush interval - * @param TSqlMapCacheModel cache model - * @param SimpleXmlElement cache node - */ - protected function loadFlushInterval($cacheModel, $node) - { - $flushInterval = $node->xpath('flushInterval'); - if($flushInterval === null || count($flushInterval) === 0) return; - $duration = 0; - foreach($flushInterval[0]->attributes() as $name=>$value) - { - switch(strToLower($name)) - { - case 'seconds': - $duration += (integer)$value; - break; - case 'minutes': - $duration += 60 * (integer)$value; - break; - case 'hours': - $duration += 3600 * (integer)$value; - break; - case 'days': - $duration += 86400 * (integer)$value; - break; - case 'duration': - $duration = (integer)$value; - break 2; // switch, foreach - } - } - $cacheModel->setFlushInterval($duration); - } - - /** - * Load the flush on cache properties. - * @param TSqlMapCacheModel cache model - * @param SimpleXmlElement parent node. - * @param SimpleXmlElement flush node. - */ - protected function loadFlushOnCache($cacheModel,$parent,$node) - { - $id = $cacheModel->getID(); - if(!isset($this->_FlushOnExecuteStatements[$id])) - $this->_FlushOnExecuteStatements[$id] = array(); - foreach($node->attributes() as $name=>$value) - { - if(strtolower($name)==='statement') - $this->_FlushOnExecuteStatements[$id][] = (string)$value; - } - } - - /** - * Attach CacheModel to statement and register trigger statements for cache models - */ - protected function registerCacheTriggers() - { - foreach($this->_FlushOnExecuteStatements as $cacheID => $statementIDs) - { - $cacheModel = $this->_manager->getCacheModel($cacheID); - foreach($statementIDs as $statementID) - { - $statement = $this->_manager->getMappedStatement($statementID); - $cacheModel->registerTriggerStatement($statement); - } - } - } -} - + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2012 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ + +Prado::using('System.Data.SqlMap.Configuration.TSqlMapStatement'); + +/** + * TSqlMapXmlConfig class file. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + */ +abstract class TSqlMapXmlConfigBuilder +{ + /** + * Create an instance of an object give by the attribute named 'class' in the + * node and set the properties on the object given by attribute names and values. + * @param SimpleXmlNode property node + * @return Object new instance of class with class name given by 'class' attribute value. + */ + protected function createObjectFromNode($node) + { + if(isset($node['class'])) + { + $obj = Prado::createComponent((string)$node['class']); + $this->setObjectPropFromNode($obj,$node,array('class')); + return $obj; + } + throw new TSqlMapConfigurationException( + 'sqlmap_node_class_undef', $node, $this->getConfigFile()); + } + + /** + * For each attributes (excluding attribute named in $except) set the + * property of the $obj given by the name of the attribute with the value + * of the attribute. + * @param Object object instance + * @param SimpleXmlNode property node + * @param array exception property name + */ + protected function setObjectPropFromNode($obj,$node,$except=array()) + { + foreach($node->attributes() as $name=>$value) + { + if(!in_array($name,$except)) + { + if($obj->canSetProperty($name)) + $obj->{$name} = (string)$value; + else + throw new TSqlMapConfigurationException( + 'sqlmap_invalid_property', $name, get_class($obj), + $node, $this->getConfigFile()); + } + } + } + + /** + * Gets the filename relative to the basefile. + * @param string base filename + * @param string relative filename + * @return string absolute filename. + */ + protected function getAbsoluteFilePath($basefile,$resource) + { + $basedir = dirname($basefile); + $file = realpath($basedir.DIRECTORY_SEPARATOR.$resource); + if(!is_string($file) || !is_file($file)) + $file = realpath($resource); + if(is_string($file) && is_file($file)) + return $file; + else + throw new TSqlMapConfigurationException( + 'sqlmap_unable_to_find_resource', $resource); + } + + /** + * Load document using simple xml. + * @param string filename. + * @return SimpleXmlElement xml document. + */ + protected function loadXmlDocument($filename,TSqlMapXmlConfiguration $config) + { + if( strpos($filename, '${') !== false) + $filename = $config->replaceProperties($filename); + + if(!is_file($filename)) + throw new TSqlMapConfigurationException( + 'sqlmap_unable_to_find_config', $filename); + return simplexml_load_string($config->replaceProperties(file_get_contents($filename))); + } + + /** + * Get element node by ID value (try for attribute name ID as case insensitive). + * @param SimpleXmlDocument $document + * @param string tag name. + * @param string id value. + * @return SimpleXmlElement node if found, null otherwise. + */ + protected function getElementByIdValue($document, $tag, $value) + { + //hack to allow upper case and lower case attribute names. + foreach(array('id','ID','Id', 'iD') as $id) + { + $xpath = "//{$tag}[@{$id}='{$value}']"; + foreach($document->xpath($xpath) as $node) + return $node; + } + } + + /** + * @return string configuration file. + */ + protected abstract function getConfigFile(); +} + +/** + * TSqlMapXmlConfig class. + * + * Configures the TSqlMapManager using xml configuration file. + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapXmlConfiguration extends TSqlMapXmlConfigBuilder +{ + /** + * @var TSqlMapManager manager + */ + private $_manager; + /** + * @var string configuration file. + */ + private $_configFile; + /** + * @var array global properties. + */ + private $_properties=array(); + + /** + * @param TSqlMapManager manager instance. + */ + public function __construct($manager) + { + $this->_manager=$manager; + } + + public function getManager() + { + return $this->_manager; + } + + protected function getConfigFile() + { + return $this->_configFile; + } + + /** + * Configure the TSqlMapManager using the given xml file. + * @param string SqlMap configuration xml file. + */ + public function configure($filename=null) + { + $this->_configFile=$filename; + $document = $this->loadXmlDocument($filename,$this); + + foreach($document->xpath('//property') as $property) + $this->loadGlobalProperty($property); + + foreach($document->xpath('//typeHandler') as $handler) + $this->loadTypeHandler($handler); + + foreach($document->xpath('//connection[last()]') as $conn) + $this->loadDatabaseConnection($conn); + + //try to load configuration in the current config file. + $mapping = new TSqlMapXmlMappingConfiguration($this); + $mapping->configure($filename); + + foreach($document->xpath('//sqlMap') as $sqlmap) + $this->loadSqlMappingFiles($sqlmap); + + $this->resolveResultMapping(); + $this->attachCacheModels(); + } + + /** + * Load global replacement property. + * @param SimpleXmlElement property node. + */ + protected function loadGlobalProperty($node) + { + $this->_properties[(string)$node['name']] = (string)$node['value']; + } + + /** + * Load the type handler configurations. + * @param SimpleXmlElement type handler node + */ + protected function loadTypeHandler($node) + { + $handler = $this->createObjectFromNode($node); + $this->_manager->getTypeHandlers()->registerTypeHandler($handler); + } + + /** + * Load the database connection tag. + * @param SimpleXmlElement connection node. + */ + protected function loadDatabaseConnection($node) + { + $conn = $this->createObjectFromNode($node); + $this->_manager->setDbConnection($conn); + } + + /** + * Load SqlMap mapping configuration. + * @param unknown_type $node + */ + protected function loadSqlMappingFiles($node) + { + if(strlen($resource = (string)$node['resource']) > 0) + { + if( strpos($resource, '${') !== false) + $resource = $this->replaceProperties($resource); + + $mapping = new TSqlMapXmlMappingConfiguration($this); + $filename = $this->getAbsoluteFilePath($this->_configFile, $resource); + $mapping->configure($filename); + } + } + + /** + * Resolve nest result mappings. + */ + protected function resolveResultMapping() + { + $maps = $this->_manager->getResultMaps(); + foreach($maps as $entry) + { + foreach($entry->getColumns() as $item) + { + $resultMap = $item->getResultMapping(); + if(strlen($resultMap) > 0) + { + if($maps->contains($resultMap)) + $item->setNestedResultMap($maps[$resultMap]); + else + throw new TSqlMapConfigurationException( + 'sqlmap_unable_to_find_result_mapping', + $resultMap, $this->_configFile, $entry->getID()); + } + } + if($entry->getDiscriminator()!==null) + $entry->getDiscriminator()->initialize($this->_manager); + } + } + + /** + * Set the cache for each statement having a cache model property. + */ + protected function attachCacheModels() + { + foreach($this->_manager->getMappedStatements() as $mappedStatement) + { + if(strlen($model = $mappedStatement->getStatement()->getCacheModel()) > 0) + { + $cache = $this->_manager->getCacheModel($model); + $mappedStatement->getStatement()->setCache($cache); + } + } + } + + /** + * Replace the place holders ${name} in text with properties the + * corresponding global property value. + * @param string original string. + * @return string string with global property replacement. + */ + public function replaceProperties($string) + { + foreach($this->_properties as $find => $replace) + $string = str_replace('${'.$find.'}', $replace, $string); + return $string; + } +} + +/** + * Loads the statements, result maps, parameters maps from xml configuration. + * + * description + * + * @author Wei Zhuo + * @version $Id$ + * @package System.Data.SqlMap.Configuration + * @since 3.1 + */ +class TSqlMapXmlMappingConfiguration extends TSqlMapXmlConfigBuilder +{ + private $_xmlConfig; + private $_configFile; + private $_manager; + + private $_document; + + private $_FlushOnExecuteStatements=array(); + + /** + * Regular expressions for escaping simple/inline parameter symbols + */ + const SIMPLE_MARK='$'; + const INLINE_SYMBOL='#'; + const ESCAPED_SIMPLE_MARK_REGEXP='/\$\$/'; + const ESCAPED_INLINE_SYMBOL_REGEXP='/\#\#/'; + const SIMPLE_PLACEHOLDER='`!!`'; + const INLINE_PLACEHOLDER='`!!!`'; + + /** + * @param TSqlMapXmlConfiguration parent xml configuration. + */ + public function __construct(TSqlMapXmlConfiguration $xmlConfig) + { + $this->_xmlConfig=$xmlConfig; + $this->_manager=$xmlConfig->getManager(); + } + + protected function getConfigFile() + { + return $this->_configFile; + } + + /** + * Configure an XML mapping. + * @param string xml mapping filename. + */ + public function configure($filename) + { + $this->_configFile=$filename; + $document = $this->loadXmlDocument($filename,$this->_xmlConfig); + $this->_document=$document; + + static $bCacheDependencies; + if($bCacheDependencies === null) + $bCacheDependencies = Prado::getApplication()->getMode() !== TApplicationMode::Performance; + + if($bCacheDependencies) + $this->_manager->getCacheDependencies() + ->getDependencies() + ->add(new TFileCacheDependency($filename)); + + foreach($document->xpath('//resultMap') as $node) + $this->loadResultMap($node); + + foreach($document->xpath('//parameterMap') as $node) + $this->loadParameterMap($node); + + foreach($document->xpath('//statement') as $node) + $this->loadStatementTag($node); + + foreach($document->xpath('//select') as $node) + $this->loadSelectTag($node); + + foreach($document->xpath('//insert') as $node) + $this->loadInsertTag($node); + + foreach($document->xpath('//update') as $node) + $this->loadUpdateTag($node); + + foreach($document->xpath('//delete') as $node) + $this->loadDeleteTag($node); + + foreach($document->xpath('//procedure') as $node) + $this->loadProcedureTag($node); + + foreach($document->xpath('//cacheModel') as $node) + $this->loadCacheModel($node); + + $this->registerCacheTriggers(); + } + + /** + * Load the result maps. + * @param SimpleXmlElement result map node. + */ + protected function loadResultMap($node) + { + $resultMap = $this->createResultMap($node); + + //find extended result map. + if(strlen($extendMap = $resultMap->getExtends()) > 0) + { + if(!$this->_manager->getResultMaps()->contains($extendMap)) + { + $extendNode=$this->getElementByIdValue($this->_document,'resultMap',$extendMap); + if($extendNode!==null) + $this->loadResultMap($extendNode); + } + + if(!$this->_manager->getResultMaps()->contains($extendMap)) + throw new TSqlMapConfigurationException( + 'sqlmap_unable_to_find_parent_result_map', $node, $this->_configFile, $extendMap); + + $superMap = $this->_manager->getResultMap($extendMap); + $resultMap->getColumns()->mergeWith($superMap->getColumns()); + } + + //add the result map + if(!$this->_manager->getResultMaps()->contains($resultMap->getID())) + $this->_manager->addResultMap($resultMap); + } + + /** + * Create a new result map and its associated result properties, + * disciminiator and sub maps. + * @param SimpleXmlElement result map node + * @return TResultMap SqlMap result mapping. + */ + protected function createResultMap($node) + { + $resultMap = new TResultMap(); + $this->setObjectPropFromNode($resultMap,$node); + + //result nodes + foreach($node->result as $result) + { + $property = new TResultProperty($resultMap); + $this->setObjectPropFromNode($property,$result); + $resultMap->addResultProperty($property); + } + + //create the discriminator + $discriminator = null; + if(isset($node->discriminator)) + { + $discriminator = new TDiscriminator(); + $this->setObjectPropFromNode($discriminator, $node->discriminator); + $discriminator->initMapping($resultMap); + } + + foreach($node->xpath('subMap') as $subMapNode) + { + if($discriminator===null) + throw new TSqlMapConfigurationException( + 'sqlmap_undefined_discriminator', $node, $this->_configFile,$subMapNode); + $subMap = new TSubMap; + $this->setObjectPropFromNode($subMap,$subMapNode); + $discriminator->addSubMap($subMap); + } + + if($discriminator!==null) + $resultMap->setDiscriminator($discriminator); + + return $resultMap; + } + + /** + * Load parameter map from xml. + * + * @param SimpleXmlElement parameter map node. + */ + protected function loadParameterMap($node) + { + $parameterMap = $this->createParameterMap($node); + + if(strlen($extendMap = $parameterMap->getExtends()) > 0) + { + if(!$this->_manager->getParameterMaps()->contains($extendMap)) + { + $extendNode=$this->getElementByIdValue($this->_document,'parameterMap',$extendMap); + if($extendNode!==null) + $this->loadParameterMap($extendNode); + } + + if(!$this->_manager->getParameterMaps()->contains($extendMap)) + throw new TSqlMapConfigurationException( + 'sqlmap_unable_to_find_parent_parameter_map', $node, $this->_configFile,$extendMap); + $superMap = $this->_manager->getParameterMap($extendMap); + $index = 0; + foreach($superMap->getPropertyNames() as $propertyName) + $parameterMap->insertProperty($index++,$superMap->getProperty($propertyName)); + } + $this->_manager->addParameterMap($parameterMap); + } + + /** + * Create a new parameter map from xml node. + * @param SimpleXmlElement parameter map node. + * @return TParameterMap new parameter mapping. + */ + protected function createParameterMap($node) + { + $parameterMap = new TParameterMap(); + $this->setObjectPropFromNode($parameterMap,$node); + foreach($node->parameter as $parameter) + { + $property = new TParameterProperty(); + $this->setObjectPropFromNode($property,$parameter); + $parameterMap->addProperty($property); + } + return $parameterMap; + } + + /** + * Load statement mapping from xml configuration file. + * @param SimpleXmlElement statement node. + */ + protected function loadStatementTag($node) + { + $statement = new TSqlMapStatement(); + $this->setObjectPropFromNode($statement,$node); + $this->processSqlStatement($statement, $node); + $mappedStatement = new TMappedStatement($this->_manager, $statement); + $this->_manager->addMappedStatement($mappedStatement); + } + + /** + * Load extended SQL statements if application. Replaces global properties + * in the sql text. Extracts inline parameter maps. + * @param TSqlMapStatement mapped statement. + * @param SimpleXmlElement statement node. + */ + protected function processSqlStatement($statement, $node) + { + $commandText = (string)$node; + if(strlen($extend = $statement->getExtends()) > 0) + { + $superNode = $this->getElementByIdValue($this->_document,'*',$extend); + if($superNode!==null) + $commandText = (string)$superNode . $commandText; + else + throw new TSqlMapConfigurationException( + 'sqlmap_unable_to_find_parent_sql', $extend, $this->_configFile,$node); + } + //$commandText = $this->_xmlConfig->replaceProperties($commandText); + $statement->initialize($this->_manager); + $this->applyInlineParameterMap($statement, $commandText, $node); + } + + /** + * Extract inline parameter maps. + * @param TSqlMapStatement statement object. + * @param string sql text + * @param SimpleXmlElement statement node. + */ + protected function applyInlineParameterMap($statement, $sqlStatement, $node) + { + $scope['file'] = $this->_configFile; + $scope['node'] = $node; + + $sqlStatement=preg_replace(self::ESCAPED_INLINE_SYMBOL_REGEXP,self::INLINE_PLACEHOLDER,$sqlStatement); + if($statement->parameterMap() === null) + { + // Build a Parametermap with the inline parameters. + // if they exist. Then delete inline infos from sqltext. + $parameterParser = new TInlineParameterMapParser; + $sqlText = $parameterParser->parse($sqlStatement, $scope); + if(count($sqlText['parameters']) > 0) + { + $map = new TParameterMap(); + $map->setID($statement->getID().'-InLineParameterMap'); + $statement->setInlineParameterMap($map); + foreach($sqlText['parameters'] as $property) + $map->addProperty($property); + } + $sqlStatement = $sqlText['sql']; + } + $sqlStatement=preg_replace('/'.self::INLINE_PLACEHOLDER.'/',self::INLINE_SYMBOL,$sqlStatement); + + $this->prepareSql($statement, $sqlStatement, $node); + } + + /** + * Prepare the sql text (may extend to dynamic sql). + * @param TSqlMapStatement mapped statement. + * @param string sql text. + * @param SimpleXmlElement statement node. + * @todo Extend to dynamic sql. + */ + protected function prepareSql($statement,$sqlStatement, $node) + { + $simpleDynamic = new TSimpleDynamicParser; + $sqlStatement=preg_replace(self::ESCAPED_SIMPLE_MARK_REGEXP,self::SIMPLE_PLACEHOLDER,$sqlStatement); + $dynamics = $simpleDynamic->parse($sqlStatement); + if(count($dynamics['parameters']) > 0) + { + $sql = new TSimpleDynamicSql($dynamics['parameters']); + $sqlStatement = $dynamics['sql']; + } + else + $sql = new TStaticSql(); + $sqlStatement=preg_replace('/'.self::SIMPLE_PLACEHOLDER.'/',self::SIMPLE_MARK,$sqlStatement); + $sql->buildPreparedStatement($statement, $sqlStatement); + $statement->setSqlText($sql); + } + + /** + * Load select statement from xml mapping. + * @param SimpleXmlElement select node. + */ + protected function loadSelectTag($node) + { + $select = new TSqlMapSelect; + $this->setObjectPropFromNode($select,$node); + $this->processSqlStatement($select,$node); + $mappedStatement = new TMappedStatement($this->_manager, $select); + if(strlen($select->getCacheModel()) > 0) + $mappedStatement = new TCachingStatement($mappedStatement); + + $this->_manager->addMappedStatement($mappedStatement); + } + + /** + * Load insert statement from xml mapping. + * @param SimpleXmlElement insert node. + */ + protected function loadInsertTag($node) + { + $insert = $this->createInsertStatement($node); + $this->processSqlStatement($insert, $node); + $mappedStatement = new TInsertMappedStatement($this->_manager, $insert); + $this->_manager->addMappedStatement($mappedStatement); + } + + /** + * Create new insert statement from xml node. + * @param SimpleXmlElement insert node. + * @return TSqlMapInsert insert statement. + */ + protected function createInsertStatement($node) + { + $insert = new TSqlMapInsert; + $this->setObjectPropFromNode($insert,$node); + if(isset($node->selectKey)) + $this->loadSelectKeyTag($insert,$node->selectKey); + return $insert; + } + + /** + * Load the selectKey statement from xml mapping. + * @param SimpleXmlElement selectkey node + */ + protected function loadSelectKeyTag($insert, $node) + { + $selectKey = new TSqlMapSelectKey; + $this->setObjectPropFromNode($selectKey,$node); + $selectKey->setID($insert->getID()); + $selectKey->setID($insert->getID().'.SelectKey'); + $this->processSqlStatement($selectKey,$node); + $insert->setSelectKey($selectKey); + $mappedStatement = new TMappedStatement($this->_manager, $selectKey); + $this->_manager->addMappedStatement($mappedStatement); + } + + /** + * Load update statement from xml mapping. + * @param SimpleXmlElement update node. + */ + protected function loadUpdateTag($node) + { + $update = new TSqlMapUpdate; + $this->setObjectPropFromNode($update,$node); + $this->processSqlStatement($update, $node); + $mappedStatement = new TUpdateMappedStatement($this->_manager, $update); + $this->_manager->addMappedStatement($mappedStatement); + } + + /** + * Load delete statement from xml mapping. + * @param SimpleXmlElement delete node. + */ + protected function loadDeleteTag($node) + { + $delete = new TSqlMapDelete; + $this->setObjectPropFromNode($delete,$node); + $this->processSqlStatement($delete, $node); + $mappedStatement = new TDeleteMappedStatement($this->_manager, $delete); + $this->_manager->addMappedStatement($mappedStatement); + } + + /** + * Load procedure statement from xml mapping. + * @todo Implement loading procedure + * @param SimpleXmlElement procedure node + */ + protected function loadProcedureTag($node) + { + //var_dump('todo: add load procedure'); + } + + /** + * Load cache models from xml mapping. + * @param SimpleXmlElement cache node. + */ + protected function loadCacheModel($node) + { + $cacheModel = new TSqlMapCacheModel; + $properties = array('id','implementation'); + foreach($node->attributes() as $name=>$value) + { + if(in_array(strtolower($name), $properties)) + $cacheModel->{'set'.$name}((string)$value); + } + $cache = Prado::createComponent($cacheModel->getImplementationClass(), $cacheModel); + $this->setObjectPropFromNode($cache,$node,$properties); + + foreach($node->xpath('property') as $propertyNode) + { + $name = $propertyNode->attributes()->name; + if($name===null || $name==='') continue; + + $value = $propertyNode->attributes()->value; + if($value===null || $value==='') continue; + + if( !TPropertyAccess::has($cache, $name) ) continue; + + TPropertyAccess::set($cache, $name, $value); + } + + $this->loadFlushInterval($cacheModel,$node); + + $cacheModel->initialize($cache); + $this->_manager->addCacheModel($cacheModel); + foreach($node->xpath('flushOnExecute') as $flush) + $this->loadFlushOnCache($cacheModel,$node,$flush); + } + + /** + * Load the flush interval + * @param TSqlMapCacheModel cache model + * @param SimpleXmlElement cache node + */ + protected function loadFlushInterval($cacheModel, $node) + { + $flushInterval = $node->xpath('flushInterval'); + if($flushInterval === null || count($flushInterval) === 0) return; + $duration = 0; + foreach($flushInterval[0]->attributes() as $name=>$value) + { + switch(strToLower($name)) + { + case 'seconds': + $duration += (integer)$value; + break; + case 'minutes': + $duration += 60 * (integer)$value; + break; + case 'hours': + $duration += 3600 * (integer)$value; + break; + case 'days': + $duration += 86400 * (integer)$value; + break; + case 'duration': + $duration = (integer)$value; + break 2; // switch, foreach + } + } + $cacheModel->setFlushInterval($duration); + } + + /** + * Load the flush on cache properties. + * @param TSqlMapCacheModel cache model + * @param SimpleXmlElement parent node. + * @param SimpleXmlElement flush node. + */ + protected function loadFlushOnCache($cacheModel,$parent,$node) + { + $id = $cacheModel->getID(); + if(!isset($this->_FlushOnExecuteStatements[$id])) + $this->_FlushOnExecuteStatements[$id] = array(); + foreach($node->attributes() as $name=>$value) + { + if(strtolower($name)==='statement') + $this->_FlushOnExecuteStatements[$id][] = (string)$value; + } + } + + /** + * Attach CacheModel to statement and register trigger statements for cache models + */ + protected function registerCacheTriggers() + { + foreach($this->_FlushOnExecuteStatements as $cacheID => $statementIDs) + { + $cacheModel = $this->_manager->getCacheModel($cacheID); + foreach($statementIDs as $statementID) + { + $statement = $this->_manager->getMappedStatement($statementID); + $cacheModel->registerTriggerStatement($statement); + } + } + } +} + -- cgit v1.2.3