Completed
Branch master (4dc390)
by Fabio
30:44
created

TSqlMapXmlMappingConfiguration   F

Complexity

Total Complexity 79

Size/Duplication

Total Lines 497
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 33
Metric Value
wmc 79
lcom 1
cbo 33
dl 0
loc 497
rs 1.3043

22 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A getConfigFile() 0 4 1
F configure() 0 44 12
B loadResultMap() 0 26 6
B createResultMap() 0 37 6
B loadParameterMap() 0 23 6
A createParameterMap() 0 12 2
A loadStatementTag() 0 8 1
A processSqlStatement() 0 16 3
B applyInlineParameterMap() 0 26 4
A prepareSql() 0 16 2
A loadSelectTag() 0 11 2
A loadInsertTag() 0 7 1
A createInsertStatement() 0 8 2
A loadSelectKeyTag() 0 11 1
A loadUpdateTag() 0 8 1
A loadDeleteTag() 0 8 1
A loadProcedureTag() 0 4 1
D loadCacheModel() 0 32 10
D loadFlushInterval() 0 28 9
A loadFlushOnCache() 0 11 4
A registerCacheTriggers() 0 12 3

How to fix   Complexity   

Complex Class

Complex classes like TSqlMapXmlMappingConfiguration often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use TSqlMapXmlMappingConfiguration, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * TSqlMapXmlConfigBuilder, TSqlMapXmlConfiguration, TSqlMapXmlMappingConfiguration classes file.
4
 *
5
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
6
 * @link https://github.com/pradosoft/prado
7
 * @copyright Copyright &copy; 2005-2015 The PRADO Group
8
 * @license https://github.com/pradosoft/prado/blob/master/COPYRIGHT
9
 * @package System.Data.SqlMap.Configuration
10
 */
11
12
Prado::using('System.Data.SqlMap.Configuration.TSqlMapStatement');
13
14
/**
15
 * TSqlMapXmlConfig class file.
16
 *
17
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
18
 * @package System.Data.SqlMap.Configuration
19
 */
20
abstract class TSqlMapXmlConfigBuilder
21
{
22
	/**
23
	 * Create an instance of an object give by the attribute named 'class' in the
24
	 * node and set the properties on the object given by attribute names and values.
25
	 * @param SimpleXmlNode property node
26
	 * @return Object new instance of class with class name given by 'class' attribute value.
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use TComponent.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
27
	 */
28
	protected function createObjectFromNode($node)
29
	{
30
		if(isset($node['class']))
31
		{
32
			$obj = Prado::createComponent((string)$node['class']);
33
			$this->setObjectPropFromNode($obj,$node,array('class'));
34
			return $obj;
35
		}
36
		throw new TSqlMapConfigurationException(
37
			'sqlmap_node_class_undef', $node, $this->getConfigFile());
38
	}
39
40
	/**
41
	 * For each attributes (excluding attribute named in $except) set the
42
	 * property of the $obj given by the name of the attribute with the value
43
	 * of the attribute.
44
	 * @param Object object instance
45
	 * @param SimpleXmlNode property node
46
	 * @param array exception property name
47
	 */
48
	protected function setObjectPropFromNode($obj,$node,$except=array())
49
	{
50
		foreach($node->attributes() as $name=>$value)
51
		{
52
			if(!in_array($name,$except))
53
			{
54
				if($obj->canSetProperty($name))
55
					$obj->{$name} = (string)$value;
56
				else
57
					throw new TSqlMapConfigurationException(
58
						'sqlmap_invalid_property', $name, get_class($obj),
59
						$node, $this->getConfigFile());
60
			}
61
		}
62
	}
63
64
	/**
65
	 * Gets the filename relative to the basefile.
66
	 * @param string base filename
67
	 * @param string relative filename
68
	 * @return string absolute filename.
69
	 */
70
	protected function getAbsoluteFilePath($basefile,$resource)
71
	{
72
		$basedir = dirname($basefile);
73
		$file = realpath($basedir.DIRECTORY_SEPARATOR.$resource);
74
		if(!is_string($file) || !is_file($file))
75
			$file = realpath($resource);
76
		if(is_string($file) && is_file($file))
77
			return $file;
78
		else
79
			throw new TSqlMapConfigurationException(
80
				'sqlmap_unable_to_find_resource', $resource);
81
	}
82
83
	/**
84
	 * Load document using simple xml.
85
	 * @param string filename.
86
	 * @return SimpleXmlElement xml document.
87
	 */
88
	protected function loadXmlDocument($filename,TSqlMapXmlConfiguration $config)
89
	{
90
		if( strpos($filename, '${') !== false)
91
			$filename = $config->replaceProperties($filename);
92
93
		if(!is_file($filename))
94
			throw new TSqlMapConfigurationException(
95
				'sqlmap_unable_to_find_config', $filename);
96
		return simplexml_load_string($config->replaceProperties(file_get_contents($filename)));
97
	}
98
99
	/**
100
	 * Get element node by ID value (try for attribute name ID as case insensitive).
101
	 * @param SimpleXmlDocument $document
102
	 * @param string tag name.
103
	 * @param string id value.
104
	 * @return SimpleXmlElement node if found, null otherwise.
105
	 */
106
	protected function getElementByIdValue($document, $tag, $value)
107
	{
108
		//hack to allow upper case and lower case attribute names.
109
		foreach(array('id','ID','Id', 'iD') as $id)
110
		{
111
			$xpath = "//{$tag}[@{$id}='{$value}']";
112
			foreach($document->xpath($xpath) as $node)
113
				return $node;
114
		}
115
	}
116
117
	/**
118
	 * @return string configuration file.
119
	 */
120
	protected abstract function getConfigFile();
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
121
}
122
123
/**
124
 * TSqlMapXmlConfig class.
125
 *
126
 * Configures the TSqlMapManager using xml configuration file.
127
 *
128
 * @author Wei Zhuo <weizho[at]gmail[dot]com>
129
 * @package System.Data.SqlMap.Configuration
130
 * @since 3.1
131
 */
132
class TSqlMapXmlConfiguration extends TSqlMapXmlConfigBuilder
133
{
134
	/**
135
	 * @var TSqlMapManager manager
136
	 */
137
	private $_manager;
138
	/**
139
	 * @var string configuration file.
140
	 */
141
	private $_configFile;
142
	/**
143
	 * @var array global properties.
144
	 */
145
	private $_properties=array();
146
147
	/**
148
	 * @param TSqlMapManager manager instance.
149
	 */
150
	public function __construct($manager)
151
	{
152
		$this->_manager=$manager;
153
	}
154
155
	public function getManager()
156
	{
157
		return $this->_manager;
158
	}
159
160
	protected function getConfigFile()
161
	{
162
		return $this->_configFile;
163
	}
164
165
	/**
166
	 * Configure the TSqlMapManager using the given xml file.
167
	 * @param string SqlMap configuration xml file.
168
	 */
169
	public function configure($filename=null)
170
	{
171
		$this->_configFile=$filename;
172
		$document = $this->loadXmlDocument($filename,$this);
173
174
		foreach($document->xpath('//property') as $property)
175
			$this->loadGlobalProperty($property);
176
177
		foreach($document->xpath('//typeHandler') as $handler)
178
			$this->loadTypeHandler($handler);
179
180
		foreach($document->xpath('//connection[last()]') as $conn)
181
			$this->loadDatabaseConnection($conn);
182
183
		//try to load configuration in the current config file.
184
		$mapping = new TSqlMapXmlMappingConfiguration($this);
185
		$mapping->configure($filename);
186
187
		foreach($document->xpath('//sqlMap') as $sqlmap)
188
			$this->loadSqlMappingFiles($sqlmap);
189
190
		$this->resolveResultMapping();
191
		$this->attachCacheModels();
192
	}
193
194
	/**
195
	 * Load global replacement property.
196
	 * @param SimpleXmlElement property node.
197
	 */
198
	protected function loadGlobalProperty($node)
199
	{
200
		$this->_properties[(string)$node['name']] = (string)$node['value'];
201
	}
202
203
	/**
204
	 * Load the type handler configurations.
205
	 * @param SimpleXmlElement type handler node
206
	 */
207
	protected function loadTypeHandler($node)
208
	{
209
		$handler = $this->createObjectFromNode($node);
210
		$this->_manager->getTypeHandlers()->registerTypeHandler($handler);
211
	}
212
213
	/**
214
	 * Load the database connection tag.
215
	 * @param SimpleXmlElement connection node.
216
	 */
217
	protected function loadDatabaseConnection($node)
218
	{
219
		$conn = $this->createObjectFromNode($node);
220
		$this->_manager->setDbConnection($conn);
221
	}
222
223
	/**
224
	 * Load SqlMap mapping configuration.
225
	 * @param unknown_type $node
226
	 */
227
	protected function loadSqlMappingFiles($node)
228
	{
229
		if(strlen($resource = (string)$node['resource']) > 0)
230
		{
231
			if( strpos($resource, '${') !== false)
232
				$resource = $this->replaceProperties($resource);
233
234
			$mapping = new TSqlMapXmlMappingConfiguration($this);
235
			$filename = $this->getAbsoluteFilePath($this->_configFile, $resource);
236
			$mapping->configure($filename);
237
		}
238
	}
239
240
	/**
241
	 * Resolve nest result mappings.
242
	 */
243
	protected function resolveResultMapping()
244
	{
245
		$maps = $this->_manager->getResultMaps();
246
		foreach($maps as $entry)
247
		{
248
			foreach($entry->getColumns() as $item)
249
			{
250
				$resultMap = $item->getResultMapping();
251
				if(strlen($resultMap) > 0)
252
				{
253
					if($maps->contains($resultMap))
254
						$item->setNestedResultMap($maps[$resultMap]);
255
					else
256
						throw new TSqlMapConfigurationException(
257
							'sqlmap_unable_to_find_result_mapping',
258
								$resultMap, $this->_configFile, $entry->getID());
259
				}
260
			}
261
			if($entry->getDiscriminator()!==null)
262
				$entry->getDiscriminator()->initialize($this->_manager);
263
		}
264
	}
265
266
	/**
267
	 * Set the cache for each statement having a cache model property.
268
	 */
269
	protected function attachCacheModels()
270
	{
271
		foreach($this->_manager->getMappedStatements() as $mappedStatement)
272
		{
273
			if(strlen($model = $mappedStatement->getStatement()->getCacheModel()) > 0)
274
			{
275
				$cache = $this->_manager->getCacheModel($model);
276
				$mappedStatement->getStatement()->setCache($cache);
277
			}
278
		}
279
	}
280
281
	/**
282
	 * Replace the place holders ${name} in text with properties the
283
	 * corresponding global property value.
284
	 * @param string original string.
285
	 * @return string string with global property replacement.
286
	 */
287
	public function replaceProperties($string)
288
	{
289
		foreach($this->_properties as $find => $replace)
290
			$string = str_replace('${'.$find.'}', $replace, $string);
291
		return $string;
292
	}
293
}
294
295
/**
296
 * Loads the statements, result maps, parameters maps from xml configuration.
297
 *
298
 * description
299
 *
300
 * @author Wei Zhuo <weizho[at]gmail[dot]com>
301
 * @package System.Data.SqlMap.Configuration
302
 * @since 3.1
303
 */
304
class TSqlMapXmlMappingConfiguration extends TSqlMapXmlConfigBuilder
305
{
306
	private $_xmlConfig;
307
	private $_configFile;
308
	private $_manager;
309
310
	private $_document;
311
312
	private $_FlushOnExecuteStatements=array();
313
314
	/**
315
	 * Regular expressions for escaping simple/inline parameter symbols
316
	 */
317
	const SIMPLE_MARK='$';
318
	const INLINE_SYMBOL='#';
319
	const ESCAPED_SIMPLE_MARK_REGEXP='/\$\$/';
320
	const ESCAPED_INLINE_SYMBOL_REGEXP='/\#\#/';
321
	const SIMPLE_PLACEHOLDER='`!!`';
322
	const INLINE_PLACEHOLDER='`!!!`';
323
324
	/**
325
	 * @param TSqlMapXmlConfiguration parent xml configuration.
326
	 */
327
	public function __construct(TSqlMapXmlConfiguration $xmlConfig)
328
	{
329
		$this->_xmlConfig=$xmlConfig;
330
		$this->_manager=$xmlConfig->getManager();
331
	}
332
333
	protected function getConfigFile()
334
	{
335
		return $this->_configFile;
336
	}
337
338
	/**
339
	 * Configure an XML mapping.
340
	 * @param string xml mapping filename.
341
	 */
342
	public function configure($filename)
343
	{
344
		$this->_configFile=$filename;
345
		$document = $this->loadXmlDocument($filename,$this->_xmlConfig);
346
		$this->_document=$document;
347
348
		static $bCacheDependencies;
349
		if($bCacheDependencies === null)
350
			$bCacheDependencies = Prado::getApplication()->getMode() !== TApplicationMode::Performance;
351
352
		if($bCacheDependencies)
353
			$this->_manager->getCacheDependencies()
354
					->getDependencies()
355
					->add(new TFileCacheDependency($filename));
356
357
		foreach($document->xpath('//resultMap') as $node)
358
			$this->loadResultMap($node);
359
360
		foreach($document->xpath('//parameterMap') as $node)
361
			$this->loadParameterMap($node);
362
363
		foreach($document->xpath('//statement') as $node)
364
			$this->loadStatementTag($node);
365
366
		foreach($document->xpath('//select') as $node)
367
			$this->loadSelectTag($node);
368
369
		foreach($document->xpath('//insert') as $node)
370
			$this->loadInsertTag($node);
371
372
		foreach($document->xpath('//update') as $node)
373
			$this->loadUpdateTag($node);
374
375
		foreach($document->xpath('//delete') as $node)
376
			$this->loadDeleteTag($node);
377
378
		foreach($document->xpath('//procedure') as $node)
379
			$this->loadProcedureTag($node);
380
381
		foreach($document->xpath('//cacheModel') as $node)
382
				$this->loadCacheModel($node);
383
384
		$this->registerCacheTriggers();
385
	}
386
387
	/**
388
	 * Load the result maps.
389
	 * @param SimpleXmlElement result map node.
390
	 */
391
	protected function loadResultMap($node)
392
	{
393
		$resultMap = $this->createResultMap($node);
394
395
		//find extended result map.
396
		if(strlen($extendMap = $resultMap->getExtends()) > 0)
397
		{
398
			if(!$this->_manager->getResultMaps()->contains($extendMap))
399
			{
400
				$extendNode=$this->getElementByIdValue($this->_document,'resultMap',$extendMap);
401
				if($extendNode!==null)
402
					$this->loadResultMap($extendNode);
403
			}
404
405
			if(!$this->_manager->getResultMaps()->contains($extendMap))
406
				throw new TSqlMapConfigurationException(
407
					'sqlmap_unable_to_find_parent_result_map', $node, $this->_configFile, $extendMap);
408
409
			$superMap = $this->_manager->getResultMap($extendMap);
410
			$resultMap->getColumns()->mergeWith($superMap->getColumns());
411
		}
412
413
		//add the result map
414
		if(!$this->_manager->getResultMaps()->contains($resultMap->getID()))
415
			$this->_manager->addResultMap($resultMap);
416
	}
417
418
	/**
419
	 * Create a new result map and its associated result properties,
420
	 * disciminiator and sub maps.
421
	 * @param SimpleXmlElement result map node
422
	 * @return TResultMap SqlMap result mapping.
423
	 */
424
	protected function createResultMap($node)
425
	{
426
		$resultMap = new TResultMap();
427
		$this->setObjectPropFromNode($resultMap,$node);
428
429
		//result nodes
430
		foreach($node->result as $result)
431
		{
432
			$property = new TResultProperty($resultMap);
433
			$this->setObjectPropFromNode($property,$result);
434
			$resultMap->addResultProperty($property);
435
		}
436
437
		//create the discriminator
438
		$discriminator = null;
439
		if(isset($node->discriminator))
440
		{
441
			$discriminator = new TDiscriminator();
442
			$this->setObjectPropFromNode($discriminator, $node->discriminator);
443
			$discriminator->initMapping($resultMap);
444
		}
445
446
		foreach($node->xpath('subMap') as $subMapNode)
447
		{
448
			if($discriminator===null)
449
				throw new TSqlMapConfigurationException(
450
					'sqlmap_undefined_discriminator', $node, $this->_configFile,$subMapNode);
451
			$subMap = new TSubMap;
452
			$this->setObjectPropFromNode($subMap,$subMapNode);
453
			$discriminator->addSubMap($subMap);
454
		}
455
456
		if($discriminator!==null)
457
			$resultMap->setDiscriminator($discriminator);
458
459
		return $resultMap;
460
	}
461
462
	/**
463
	 * Load parameter map from xml.
464
	 *
465
	 * @param SimpleXmlElement parameter map node.
466
	 */
467
	protected function loadParameterMap($node)
468
	{
469
		$parameterMap = $this->createParameterMap($node);
470
471
		if(strlen($extendMap = $parameterMap->getExtends()) > 0)
472
		{
473
			if(!$this->_manager->getParameterMaps()->contains($extendMap))
474
			{
475
				$extendNode=$this->getElementByIdValue($this->_document,'parameterMap',$extendMap);
476
				if($extendNode!==null)
477
					$this->loadParameterMap($extendNode);
478
			}
479
480
			if(!$this->_manager->getParameterMaps()->contains($extendMap))
481
				throw new TSqlMapConfigurationException(
482
					'sqlmap_unable_to_find_parent_parameter_map', $node, $this->_configFile,$extendMap);
483
			$superMap = $this->_manager->getParameterMap($extendMap);
484
			$index = 0;
485
			foreach($superMap->getPropertyNames() as $propertyName)
486
				$parameterMap->insertProperty($index++,$superMap->getProperty($propertyName));
487
		}
488
		$this->_manager->addParameterMap($parameterMap);
489
	}
490
491
	/**
492
	 * Create a new parameter map from xml node.
493
	 * @param SimpleXmlElement parameter map node.
494
	 * @return TParameterMap new parameter mapping.
495
	 */
496
	protected function createParameterMap($node)
497
	{
498
		$parameterMap = new TParameterMap();
499
		$this->setObjectPropFromNode($parameterMap,$node);
500
		foreach($node->parameter as $parameter)
501
		{
502
			$property = new TParameterProperty();
503
			$this->setObjectPropFromNode($property,$parameter);
504
			$parameterMap->addProperty($property);
505
		}
506
		return $parameterMap;
507
	}
508
509
	/**
510
	 * Load statement mapping from xml configuration file.
511
	 * @param SimpleXmlElement statement node.
512
	 */
513
	protected function loadStatementTag($node)
514
	{
515
		$statement = new TSqlMapStatement();
516
		$this->setObjectPropFromNode($statement,$node);
517
		$this->processSqlStatement($statement, $node);
518
		$mappedStatement = new TMappedStatement($this->_manager, $statement);
519
		$this->_manager->addMappedStatement($mappedStatement);
520
	}
521
522
	/**
523
	 * Load extended SQL statements if application. Replaces global properties
524
	 * in the sql text. Extracts inline parameter maps.
525
	 * @param TSqlMapStatement mapped statement.
526
	 * @param SimpleXmlElement statement node.
527
	 */
528
	protected function processSqlStatement($statement, $node)
529
	{
530
		$commandText = (string)$node;
531
		if(strlen($extend = $statement->getExtends()) > 0)
532
		{
533
			$superNode = $this->getElementByIdValue($this->_document,'*',$extend);
534
			if($superNode!==null)
535
				$commandText = (string)$superNode . $commandText;
536
			else
537
				throw new TSqlMapConfigurationException(
538
						'sqlmap_unable_to_find_parent_sql', $extend, $this->_configFile,$node);
539
		}
540
		//$commandText = $this->_xmlConfig->replaceProperties($commandText);
541
		$statement->initialize($this->_manager);
542
		$this->applyInlineParameterMap($statement, $commandText, $node);
543
	}
544
545
	/**
546
	 * Extract inline parameter maps.
547
	 * @param TSqlMapStatement statement object.
548
	 * @param string sql text
549
	 * @param SimpleXmlElement statement node.
550
	 */
551
	protected function applyInlineParameterMap($statement, $sqlStatement, $node)
552
	{
553
		$scope['file'] = $this->_configFile;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$scope was never initialized. Although not strictly required by PHP, it is generally a good practice to add $scope = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
554
		$scope['node'] = $node;
555
556
		$sqlStatement=preg_replace(self::ESCAPED_INLINE_SYMBOL_REGEXP,self::INLINE_PLACEHOLDER,$sqlStatement);
557
		if($statement->parameterMap() === null)
558
		{
559
			// Build a Parametermap with the inline parameters.
560
			// if they exist. Then delete inline infos from sqltext.
561
			$parameterParser = new TInlineParameterMapParser;
562
			$sqlText = $parameterParser->parse($sqlStatement, $scope);
563
			if(count($sqlText['parameters']) > 0)
564
			{
565
				$map = new TParameterMap();
566
				$map->setID($statement->getID().'-InLineParameterMap');
567
				$statement->setInlineParameterMap($map);
568
				foreach($sqlText['parameters'] as $property)
569
					$map->addProperty($property);
570
			}
571
			$sqlStatement = $sqlText['sql'];
572
		}
573
		$sqlStatement=preg_replace('/'.self::INLINE_PLACEHOLDER.'/',self::INLINE_SYMBOL,$sqlStatement);
574
575
		$this->prepareSql($statement, $sqlStatement, $node);
576
	}
577
578
	/**
579
	 * Prepare the sql text (may extend to dynamic sql).
580
	 * @param TSqlMapStatement mapped statement.
581
	 * @param string sql text.
582
	 * @param SimpleXmlElement statement node.
583
	 * @todo Extend to dynamic sql.
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
584
	 */
585
	protected function prepareSql($statement,$sqlStatement, $node)
586
	{
587
		$simpleDynamic = new TSimpleDynamicParser;
588
		$sqlStatement=preg_replace(self::ESCAPED_SIMPLE_MARK_REGEXP,self::SIMPLE_PLACEHOLDER,$sqlStatement);
589
		$dynamics = $simpleDynamic->parse($sqlStatement);
590
		if(count($dynamics['parameters']) > 0)
591
		{
592
			$sql = new TSimpleDynamicSql($dynamics['parameters']);
593
			$sqlStatement = $dynamics['sql'];
594
		}
595
		else
596
			$sql = new TStaticSql();
597
		$sqlStatement=preg_replace('/'.self::SIMPLE_PLACEHOLDER.'/',self::SIMPLE_MARK,$sqlStatement);
598
		$sql->buildPreparedStatement($statement, $sqlStatement);
599
		$statement->setSqlText($sql);
600
	}
601
602
	/**
603
	 * Load select statement from xml mapping.
604
	 * @param SimpleXmlElement select node.
605
	 */
606
	protected function loadSelectTag($node)
607
	{
608
		$select = new TSqlMapSelect;
609
		$this->setObjectPropFromNode($select,$node);
610
		$this->processSqlStatement($select,$node);
611
		$mappedStatement = new TMappedStatement($this->_manager, $select);
612
		if(strlen($select->getCacheModel()) > 0)
613
			$mappedStatement = new TCachingStatement($mappedStatement);
614
615
		$this->_manager->addMappedStatement($mappedStatement);
616
	}
617
618
	/**
619
	 * Load insert statement from xml mapping.
620
	 * @param SimpleXmlElement insert node.
621
	 */
622
	protected function loadInsertTag($node)
623
	{
624
		$insert = $this->createInsertStatement($node);
625
		$this->processSqlStatement($insert, $node);
626
		$mappedStatement = new TInsertMappedStatement($this->_manager, $insert);
627
		$this->_manager->addMappedStatement($mappedStatement);
628
	}
629
630
	/**
631
	 * Create new insert statement from xml node.
632
	 * @param SimpleXmlElement insert node.
633
	 * @return TSqlMapInsert insert statement.
634
	 */
635
	protected function createInsertStatement($node)
636
	{
637
		$insert = new TSqlMapInsert;
638
		$this->setObjectPropFromNode($insert,$node);
639
		if(isset($node->selectKey))
640
			$this->loadSelectKeyTag($insert,$node->selectKey);
641
		return $insert;
642
	}
643
644
	/**
645
	 * Load the selectKey statement from xml mapping.
646
	 * @param SimpleXmlElement selectkey node
647
	 */
648
	protected function loadSelectKeyTag($insert, $node)
649
	{
650
		$selectKey = new TSqlMapSelectKey;
651
		$this->setObjectPropFromNode($selectKey,$node);
652
		$selectKey->setID($insert->getID());
653
		$selectKey->setID($insert->getID().'.SelectKey');
654
		$this->processSqlStatement($selectKey,$node);
655
		$insert->setSelectKey($selectKey);
656
		$mappedStatement = new TMappedStatement($this->_manager, $selectKey);
657
		$this->_manager->addMappedStatement($mappedStatement);
658
	}
659
660
	/**
661
	 * Load update statement from xml mapping.
662
	 * @param SimpleXmlElement update node.
663
	 */
664
	protected function loadUpdateTag($node)
665
	{
666
		$update = new TSqlMapUpdate;
667
		$this->setObjectPropFromNode($update,$node);
668
		$this->processSqlStatement($update, $node);
669
		$mappedStatement = new TUpdateMappedStatement($this->_manager, $update);
670
		$this->_manager->addMappedStatement($mappedStatement);
671
	}
672
673
	/**
674
	 * Load delete statement from xml mapping.
675
	 * @param SimpleXmlElement delete node.
676
	 */
677
	protected function loadDeleteTag($node)
678
	{
679
		$delete = new TSqlMapDelete;
680
		$this->setObjectPropFromNode($delete,$node);
681
		$this->processSqlStatement($delete, $node);
682
		$mappedStatement = new TDeleteMappedStatement($this->_manager, $delete);
683
		$this->_manager->addMappedStatement($mappedStatement);
684
	}
685
686
	/**
687
	 * Load procedure statement from xml mapping.
688
	 * @todo Implement loading procedure
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
689
	 * @param SimpleXmlElement procedure node
690
	 */
691
	protected function loadProcedureTag($node)
692
	{
693
		//var_dump('todo: add load procedure');
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
694
	}
695
696
	/**
697
	 * Load cache models from xml mapping.
698
	 * @param SimpleXmlElement cache node.
699
	 */
700
	protected function loadCacheModel($node)
701
	{
702
		$cacheModel = new TSqlMapCacheModel;
703
		$properties = array('id','implementation');
704
		foreach($node->attributes() as $name=>$value)
705
		{
706
			if(in_array(strtolower($name), $properties))
707
				$cacheModel->{'set'.$name}((string)$value);
708
		}
709
		$cache = Prado::createComponent($cacheModel->getImplementationClass(), $cacheModel);
710
		$this->setObjectPropFromNode($cache,$node,$properties);
711
712
		foreach($node->xpath('property') as $propertyNode)
713
		{
714
			$name = $propertyNode->attributes()->name;
715
			if($name===null || $name==='') continue;
716
717
			$value = $propertyNode->attributes()->value;
718
			if($value===null || $value==='') continue;
719
720
			if( !TPropertyAccess::has($cache, $name) ) continue;
721
722
			TPropertyAccess::set($cache, $name, $value);
723
		}
724
725
		$this->loadFlushInterval($cacheModel,$node);
726
727
		$cacheModel->initialize($cache);
728
		$this->_manager->addCacheModel($cacheModel);
729
		foreach($node->xpath('flushOnExecute') as $flush)
730
			$this->loadFlushOnCache($cacheModel,$node,$flush);
731
	}
732
733
	/**
734
	 * Load the flush interval
735
	 * @param TSqlMapCacheModel cache model
736
	 * @param SimpleXmlElement cache node
737
	 */
738
	protected function loadFlushInterval($cacheModel, $node)
739
	{
740
		$flushInterval = $node->xpath('flushInterval');
741
		if($flushInterval === null || count($flushInterval) === 0) return;
742
		$duration = 0;
743
		foreach($flushInterval[0]->attributes() as $name=>$value)
744
		{
745
			switch(strToLower($name))
746
			{
747
				case 'seconds':
748
					$duration += (integer)$value;
749
				break;
750
				case 'minutes':
751
					$duration += 60 * (integer)$value;
752
				break;
753
				case 'hours':
754
					$duration += 3600 * (integer)$value;
755
				break;
756
				case 'days':
757
					$duration += 86400 * (integer)$value;
758
				break;
759
				case 'duration':
760
					$duration = (integer)$value;
761
				break 2; // switch, foreach
762
			}
763
		}
764
		$cacheModel->setFlushInterval($duration);
765
	}
766
767
	/**
768
	 * Load the flush on cache properties.
769
	 * @param TSqlMapCacheModel cache model
770
	 * @param SimpleXmlElement parent node.
771
	 * @param SimpleXmlElement flush node.
772
	 */
773
	protected function loadFlushOnCache($cacheModel,$parent,$node)
774
	{
775
		$id = $cacheModel->getID();
776
		if(!isset($this->_FlushOnExecuteStatements[$id]))
777
			$this->_FlushOnExecuteStatements[$id] = array();
778
		foreach($node->attributes() as $name=>$value)
779
		{
780
			if(strtolower($name)==='statement')
781
				$this->_FlushOnExecuteStatements[$id][] = (string)$value;
782
		}
783
	}
784
785
	/**
786
	 * Attach CacheModel to statement and register trigger statements for cache models
787
	 */
788
	protected function registerCacheTriggers()
789
	{
790
		foreach($this->_FlushOnExecuteStatements as $cacheID => $statementIDs)
791
		{
792
			$cacheModel = $this->_manager->getCacheModel($cacheID);
793
			foreach($statementIDs as $statementID)
794
			{
795
				$statement = $this->_manager->getMappedStatement($statementID);
796
				$cacheModel->registerTriggerStatement($statement);
797
			}
798
		}
799
	}
800
}
801
802