summaryrefslogtreecommitdiff
path: root/framework/Data/SqlMap/Configuration/TSqlMapXmlConfiguration.php
diff options
context:
space:
mode:
Diffstat (limited to 'framework/Data/SqlMap/Configuration/TSqlMapXmlConfiguration.php')
-rw-r--r--framework/Data/SqlMap/Configuration/TSqlMapXmlConfiguration.php1610
1 files changed, 805 insertions, 805 deletions
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 @@
-<?php
-/**
- * TSqlMapXmlConfigBuilder, TSqlMapXmlConfiguration, TSqlMapXmlMappingConfiguration classes file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 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 <weizhuo[at]gmail[dot]com>
- * @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 <weizho[at]gmail[dot]com>
- * @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 <weizho[at]gmail[dot]com>
- * @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);
- }
- }
- }
-}
-
+<?php
+/**
+ * TSqlMapXmlConfigBuilder, TSqlMapXmlConfiguration, TSqlMapXmlMappingConfiguration classes file.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 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 <weizhuo[at]gmail[dot]com>
+ * @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 <weizho[at]gmail[dot]com>
+ * @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 <weizho[at]gmail[dot]com>
+ * @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);
+ }
+ }
+ }
+}
+