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

TMappedStatement   F

Complexity

Total Complexity 127

Size/Duplication

Total Lines 913
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 17
Metric Value
wmc 127
lcom 1
cbo 17
dl 0
loc 913
rs 1.263

38 Methods

Rating   Name   Duplication   Size   Complexity  
A getID() 0 4 1
A getStatement() 0 4 1
A getManager() 0 4 1
A getCommand() 0 4 1
A initialGroupByResults() 0 4 1
A __construct() 0 7 1
A getSqlString() 0 4 1
B executeSQLQueryLimit() 0 28 5
A executeQueryForList() 0 5 1
B runQueryForList() 0 38 6
A executeQueryForMap() 0 5 1
B runQueryForMap() 0 33 6
B raiseRowDelegate() 0 25 5
A executeQueryForObject() 0 5 1
A runQueryForObject() 0 19 3
A executeInsert() 0 15 2
A getPreGeneratedSelectKey() 0 9 4
A getPostGeneratedSelectKey() 0 9 4
A executeSelectKey() 0 9 2
A executeUpdate() 0 9 1
B executePostSelect() 0 26 6
A onExecuteQuery() 0 4 1
B applyResultMap() 0 19 6
A fillResultClass() 0 15 4
A fillResultArrayList() 0 10 4
A fillResultObjectProperty() 0 17 4
B fillResultMap() 0 23 5
B addResultMapGroupBy() 0 39 6
A getResultMapGroupKey() 0 8 2
B fillDefaultResultMap() 0 16 5
B fillArrayResultMap() 0 13 5
A getScalarResult() 0 6 1
C setObjectProperty() 0 42 12
B enquequePostSelect() 0 30 5
A getPostSelectKeys() 0 19 4
A fillPropertyWithResultMap() 0 12 3
A __wakeup() 0 5 2
A __sleep() 0 8 4

How to fix   Complexity   

Complex Class

Complex classes like TMappedStatement 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 TMappedStatement, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * TMappedStatement and related classes.
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.Statements
10
 */
11
12
/**
13
 * TMappedStatement class executes SQL mapped statements. Mapped Statements can
14
 * hold any SQL statement and use Parameter Maps and Result Maps for input and output.
15
 *
16
 * This class is usualy instantiated during SQLMap configuration by TSqlDomBuilder.
17
 *
18
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
19
 * @package System.Data.SqlMap.Statements
20
 * @since 3.0
21
 */
22
class TMappedStatement extends TComponent implements IMappedStatement
23
{
24
	/**
25
	 * @var TSqlMapStatement current SQL statement.
26
	 */
27
	private $_statement;
28
29
	/**
30
	 * @var TPreparedCommand SQL command prepareer
31
	 */
32
	private $_command;
33
34
	/**
35
	 * @var TSqlMapper sqlmap used by this mapper.
36
	 */
37
	private $_manager;
38
39
	/**
40
	 * @var TPostSelectBinding[] post select statement queue.
41
	 */
42
	private $_selectQueue=array();
43
44
	/**
45
	 * @var boolean true when data is mapped to a particular row.
46
	 */
47
	private $_IsRowDataFound = false;
48
49
	/**
50
	 * @var TSQLMapObjectCollectionTree group by object collection tree
51
	 */
52
	private $_groupBy;
53
54
	/**
55
	 * @var Post select is to query for list.
56
	 */
57
	const QUERY_FOR_LIST = 0;
58
59
	/**
60
	 * @var Post select is to query for list.
61
	 */
62
	const QUERY_FOR_ARRAY = 1;
63
64
	/**
65
	 * @var Post select is to query for object.
66
	 */
67
	const QUERY_FOR_OBJECT = 2;
68
69
	/**
70
	 * @return string Name used to identify the TMappedStatement amongst the others.
71
	 * This the name of the SQL statement by default.
72
	 */
73
	public function getID()
74
	{
75
		return $this->_statement->ID;
76
	}
77
78
	/**
79
	 * @return TSqlMapStatement The SQL statment used by this MappedStatement
80
	 */
81
	public function getStatement()
82
	{
83
		return $this->_statement;
84
	}
85
86
	/**
87
	 * @return TSqlMapper The SqlMap used by this MappedStatement
88
	 */
89
	public function getManager()
90
	{
91
		return $this->_manager;
92
	}
93
94
	/**
95
	 * @return TPreparedCommand command to prepare SQL statements.
96
	 */
97
	public function getCommand()
98
	{
99
		return $this->_command;
100
	}
101
102
	/**
103
	 * Empty the group by results cache.
104
	 */
105
	protected function initialGroupByResults()
106
	{
107
		$this->_groupBy = new TSqlMapObjectCollectionTree();
108
	}
109
110
	/**
111
	 * Creates a new mapped statement.
112
	 * @param TSqlMapper an sqlmap.
113
	 * @param TSqlMapStatement An SQL statement.
114
	 */
115
	public function __construct(TSqlMapManager $sqlMap, TSqlMapStatement $statement)
116
	{
117
		$this->_manager = $sqlMap;
0 ignored issues
show
Documentation Bug introduced by
It seems like $sqlMap of type object<TSqlMapManager> is incompatible with the declared type object<TSqlMapper> of property $_manager.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
118
		$this->_statement = $statement;
119
		$this->_command = new TPreparedCommand();
120
		$this->initialGroupByResults();
121
	}
122
123
	public function getSqlString()
124
	{
125
		return $this->getStatement()->getSqlText()->getPreparedStatement()->getPreparedSql();
126
	}
127
128
	/**
129
	 * Execute SQL Query.
130
	 * @param IDbConnection database connection
131
	 * @param array SQL statement and parameters.
132
	 * @return mixed record set if applicable.
133
	 * @throws TSqlMapExecutionException if execution error or false record set.
134
	 * @throws TSqlMapQueryExecutionException if any execution error
135
	 */
136
/*	protected function executeSQLQuery($connection, $sql)
137
	{
138
		try
139
		{
140
			if(!($recordSet = $connection->execute($sql['sql'],$sql['parameters'])))
141
			{
142
				throw new TSqlMapExecutionException(
143
					'sqlmap_execution_error_no_record', $this->getID(),
144
					$connection->ErrorMsg());
145
			}
146
			return $recordSet;
147
		}
148
		catch (Exception $e)
149
		{
150
			throw new TSqlMapQueryExecutionException($this->getStatement(), $e);
151
		}
152
	}*/
153
154
	/**
155
	 * Execute SQL Query with limits.
156
	 * @param IDbConnection database connection
157
	 * @param array SQL statement and parameters.
158
	 * @return mixed record set if applicable.
159
	 * @throws TSqlMapExecutionException if execution error or false record set.
160
	 * @throws TSqlMapQueryExecutionException if any execution error
161
	 */
162
	protected function executeSQLQueryLimit($connection, $command, $max, $skip)
163
	{
164
		if($max>-1 || $skip > -1)
165
		{
166
			$maxStr=$max>0?' LIMIT '.$max:'';
167
			$skipStr=$skip>0?' OFFSET '.$skip:'';
168
			$command->setText($command->getText().$maxStr.$skipStr);
169
		}
170
		$connection->setActive(true);
171
		return $command->query();
172
173
		/*//var_dump($command);
174
		try
175
		{
176
			$recordSet = $connection->selectLimit($sql['sql'],$max,$skip,$sql['parameters']);
177
			if(!$recordSet)
178
			{
179
				throw new TSqlMapExecutionException(
180
							'sqlmap_execution_error_query_for_list',
181
							$connection->ErrorMsg());
182
			}
183
			return $recordSet;
184
		}
185
		catch (Exception $e)
186
		{
187
			throw new TSqlMapQueryExecutionException($this->getStatement(), $e);
188
		}*/
189
	}
190
191
	/**
192
	 * Executes the SQL and retuns a List of result objects.
193
	 * @param IDbConnection database connection
194
	 * @param mixed The object used to set the parameters in the SQL.
195
	 * @param object result collection object.
196
	 * @param integer The number of rows to skip over.
197
	 * @param integer The maximum number of rows to return.
198
	 * @return array a list of result objects
0 ignored issues
show
Documentation introduced by
Should the return type not be array|ArrayAccess? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
199
	 * @param callback row delegate handler
200
	 * @see executeQueryForList()
201
	 */
202
	public function executeQueryForList($connection, $parameter, $result=null, $skip=-1, $max=-1, $delegate=null)
203
	{
204
		$sql = $this->_command->create($this->_manager, $connection, $this->_statement, $parameter,$skip,$max);
205
		return $this->runQueryForList($connection, $parameter, $sql, $result, $delegate);
206
	}
207
208
	/**
209
	 * Executes the SQL and retuns a List of result objects.
210
	 *
211
	 * This method should only be called by internal developers, consider using
212
	 * <tt>executeQueryForList()</tt> first.
213
	 *
214
	 * @param IDbConnection database connection
215
	 * @param mixed The object used to set the parameters in the SQL.
216
	 * @param array SQL string and subsititution parameters.
217
	 * @param object result collection object.
218
	 * @param integer The number of rows to skip over.
219
	 * @param integer The maximum number of rows to return.
220
	 * @param callback row delegate handler
221
	 * @return array a list of result objects
0 ignored issues
show
Documentation introduced by
Should the return type not be array|ArrayAccess? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
222
	 * @see executeQueryForList()
223
	 */
224
	public function runQueryForList($connection, $parameter, $sql, $result, $delegate=null)
225
	{
226
		$registry=$this->getManager()->getTypeHandlers();
227
		$list = $result instanceof ArrayAccess ? $result :
228
							$this->_statement->createInstanceOfListClass($registry);
229
		$connection->setActive(true);
230
		$reader = $sql->query();
231
		//$reader = $this->executeSQLQueryLimit($connection, $sql, $max, $skip);
232
		if($delegate!==null)
233
		{
234
			foreach($reader as $row)
235
			{
236
				$obj = $this->applyResultMap($row);
237
				$param = new TResultSetListItemParameter($obj, $parameter, $list);
238
				$this->raiseRowDelegate($delegate, $param);
239
			}
240
		}
241
		else
242
		{
243
			//var_dump($sql,$parameter);
244
			foreach($reader as $row)
245
			{
246
//				var_dump($row);
247
				$list[] = $this->applyResultMap($row);
248
			}
249
		}
250
251
		if(!$this->_groupBy->isEmpty())
252
		{
253
			$list = $this->_groupBy->collect();
254
			$this->initialGroupByResults();
255
		}
256
257
		$this->executePostSelect($connection);
258
		$this->onExecuteQuery($sql);
259
260
		return $list;
261
	}
262
263
	/**
264
	 * Executes the SQL and retuns all rows selected in a map that is keyed on
265
	 * the property named in the keyProperty parameter.  The value at each key
266
	 * will be the value of the property specified in the valueProperty parameter.
267
	 * If valueProperty is null, the entire result object will be entered.
268
	 * @param IDbConnection database connection
269
	 * @param mixed The object used to set the parameters in the SQL.
270
	 * @param string The property of the result object to be used as the key.
271
	 * @param string The property of the result object to be used as the value (or null).
272
	 * @param callback row delegate handler
273
	 * @return array An array of object containing the rows keyed by keyProperty.
274
	 */
275
	public function executeQueryForMap($connection, $parameter, $keyProperty, $valueProperty=null,  $skip=-1, $max=-1, $delegate=null)
276
	{
277
		$sql = $this->_command->create($this->_manager, $connection, $this->_statement, $parameter, $skip, $max);
278
		return $this->runQueryForMap($connection, $parameter, $sql, $keyProperty, $valueProperty, $delegate);
279
	}
280
281
	/**
282
	 * Executes the SQL and retuns all rows selected in a map that is keyed on
283
	 * the property named in the keyProperty parameter.  The value at each key
284
	 * will be the value of the property specified in the valueProperty parameter.
285
	 * If valueProperty is null, the entire result object will be entered.
286
	 *
287
	 * This method should only be called by internal developers, consider using
288
	 * <tt>executeQueryForMap()</tt> first.
289
	 *
290
	 * @param IDbConnection database connection
291
	 * @param mixed The object used to set the parameters in the SQL.
292
	 * @param array SQL string and subsititution parameters.
293
	 * @param string The property of the result object to be used as the key.
294
	 * @param string The property of the result object to be used as the value (or null).
295
	 * @param callback row delegate, a callback function
296
	 * @return array An array of object containing the rows keyed by keyProperty.
297
	 * @see executeQueryForMap()
298
	 */
299
	public function runQueryForMap($connection, $parameter, $command, $keyProperty, $valueProperty=null, $delegate=null)
300
	{
301
		$map = array();
302
		//$recordSet = $this->executeSQLQuery($connection, $sql);
303
		$connection->setActive(true);
304
		$reader = $command->query();
305
		if($delegate!==null)
306
		{
307
			//while($row = $recordSet->fetchRow())
308
			foreach($reader as $row)
309
			{
310
				$obj = $this->applyResultMap($row);
311
				$key = TPropertyAccess::get($obj, $keyProperty);
312
				$value = ($valueProperty===null) ? $obj :
313
							TPropertyAccess::get($obj, $valueProperty);
314
				$param = new TResultSetMapItemParameter($key, $value, $parameter, $map);
315
				$this->raiseRowDelegate($delegate, $param);
316
			}
317
		}
318
		else
319
		{
320
			//while($row = $recordSet->fetchRow())
321
			foreach($reader as $row)
322
			{
323
				$obj = $this->applyResultMap($row);
324
				$key = TPropertyAccess::get($obj, $keyProperty);
325
				$map[$key] = ($valueProperty===null) ? $obj :
326
								TPropertyAccess::get($obj, $valueProperty);
327
			}
328
		}
329
		$this->onExecuteQuery($command);
330
		return $map;
331
	}
332
333
	/**
334
	 * Raises delegate handler.
335
	 * This method is invoked for each new list item. It is the responsibility
336
	 * of the handler to add the item to the list.
337
	 * @param object event parameter
338
	 */
339
	protected function raiseRowDelegate($handler, $param)
340
	{
341
		if(is_string($handler))
342
		{
343
			call_user_func($handler,$this,$param);
344
		}
345
		else if(is_callable($handler,true))
346
		{
347
			// an array: 0 - object, 1 - method name/path
348
			list($object,$method)=$handler;
349
			if(is_string($object))	// static method call
350
				call_user_func($handler,$this,$param);
351
			else
352
			{
353
				if(($pos=strrpos($method,'.'))!==false)
354
				{
355
					$object=$this->getSubProperty(substr($method,0,$pos));
356
					$method=substr($method,$pos+1);
357
				}
358
				$object->$method($this,$param);
359
			}
360
		}
361
		else
362
			throw new TInvalidDataValueException('sqlmap_invalid_delegate', $this->getID(), $handler);
363
	}
364
365
	/**
366
	 * Executes an SQL statement that returns a single row as an object of the
367
	 * type of the <tt>$result</tt> passed in as a parameter.
368
	 * @param IDbConnection database connection
369
	 * @param mixed The parameter data (object, arrary, primitive) used to set the parameters in the SQL
370
	 * @param mixed The result object.
371
	 * @return ${return}
0 ignored issues
show
Documentation introduced by
The doc-type ${return} could not be parsed: Unknown type name "${return}" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
372
	 */
373
	public function executeQueryForObject($connection, $parameter, $result=null)
374
	{
375
		$sql = $this->_command->create($this->_manager, $connection, $this->_statement, $parameter);
376
		return $this->runQueryForObject($connection, $sql, $result);
377
	}
378
379
	/**
380
	 * Executes an SQL statement that returns a single row as an object of the
381
	 * type of the <tt>$result</tt> passed in as a parameter.
382
	 *
383
	 * This method should only be called by internal developers, consider using
384
	 * <tt>executeQueryForObject()</tt> first.
385
	 *
386
	 * @param IDbConnection database connection
387
	 * @param array SQL string and subsititution parameters.
388
	 * @param object The result object.
389
	 * @return object the object.
390
	 * @see executeQueryForObject()
391
	 */
392
	public function runQueryForObject($connection, $command, &$result)
393
	{
394
		$object = null;
395
		$connection->setActive(true);
396
		foreach($command->query() as $row)
397
			$object = $this->applyResultMap($row, $result);
398
399
		if(!$this->_groupBy->isEmpty())
400
		{
401
			$list = $this->_groupBy->collect();
402
			$this->initialGroupByResults();
403
			$object = $list[0];
404
		}
405
406
		$this->executePostSelect($connection);
407
		$this->onExecuteQuery($command);
408
409
		return $object;
410
	}
411
412
	/**
413
	 * Execute an insert statement. Fill the parameter object with the ouput
414
	 * parameters if any, also could return the insert generated key.
415
	 * @param IDbConnection database connection
416
	 * @param mixed The parameter object used to fill the statement.
417
	 * @return string the insert generated key.
418
	 */
419
	public function executeInsert($connection, $parameter)
420
	{
421
		$generatedKey = $this->getPreGeneratedSelectKey($connection, $parameter);
422
423
		$command = $this->_command->create($this->_manager, $connection, $this->_statement, $parameter);
424
//		var_dump($command,$parameter);
425
		$result = $command->execute();
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
426
427
		if($generatedKey===null)
428
			$generatedKey = $this->getPostGeneratedSelectKey($connection, $parameter);
429
430
		$this->executePostSelect($connection);
431
		$this->onExecuteQuery($command);
432
		return $generatedKey;
433
	}
434
435
	/**
436
	 * Gets the insert generated ID before executing an insert statement.
437
	 * @param IDbConnection database connection
438
	 * @param mixed insert statement parameter.
439
	 * @return string new insert ID if pre-select key statement was executed, null otherwise.
440
	 */
441
	protected function getPreGeneratedSelectKey($connection, $parameter)
442
	{
443
		if($this->_statement instanceof TSqlMapInsert)
444
		{
445
			$selectKey = $this->_statement->getSelectKey();
446
			if(($selectKey!==null) && !$selectKey->getIsAfter())
447
				return $this->executeSelectKey($connection, $parameter, $selectKey);
448
		}
449
	}
450
451
	/**
452
	 * Gets the inserted row ID after executing an insert statement.
453
	 * @param IDbConnection database connection
454
	 * @param mixed insert statement parameter.
455
	 * @return string last insert ID, null otherwise.
456
	 */
457
	protected function getPostGeneratedSelectKey($connection, $parameter)
458
	{
459
		if($this->_statement instanceof TSqlMapInsert)
460
		{
461
			$selectKey = $this->_statement->getSelectKey();
462
			if(($selectKey!==null) && $selectKey->getIsAfter())
463
				return $this->executeSelectKey($connection, $parameter, $selectKey);
464
		}
465
	}
466
467
	/**
468
	 * Execute the select key statement, used to obtain last insert ID.
469
	 * @param IDbConnection database connection
470
	 * @param mixed insert statement parameter
471
	 * @param TSqlMapSelectKey select key statement
472
	 * @return string last insert ID.
473
	 */
474
	protected function executeSelectKey($connection, $parameter, $selectKey)
475
	{
476
		$mappedStatement = $this->getManager()->getMappedStatement($selectKey->getID());
477
		$generatedKey = $mappedStatement->executeQueryForObject(
478
									$connection, $parameter, null);
479
		if(strlen($prop = $selectKey->getProperty()) > 0)
480
				TPropertyAccess::set($parameter, $prop, $generatedKey);
481
		return $generatedKey;
482
	}
483
484
	/**
485
	 * Execute an update statement. Also used for delete statement.
486
	 * Return the number of rows effected.
487
	 * @param IDbConnection database connection
488
	 * @param mixed The object used to set the parameters in the SQL.
489
	 * @return integer The number of rows effected.
490
	 */
491
	public function executeUpdate($connection, $parameter)
492
	{
493
		$sql = $this->_command->create($this->getManager(),$connection, $this->_statement, $parameter);
494
		$affectedRows = $sql->execute();
495
		//$this->executeSQLQuery($connection, $sql);
496
		$this->executePostSelect($connection);
497
		$this->onExecuteQuery($sql);
498
		return $affectedRows;
499
	}
500
501
	/**
502
	 * Process 'select' result properties
503
	 * @param IDbConnection database connection
504
	 */
505
	protected function executePostSelect($connection)
506
	{
507
		while(count($this->_selectQueue))
508
		{
509
			$postSelect = array_shift($this->_selectQueue);
510
			$method = $postSelect->getMethod();
511
			$statement = $postSelect->getStatement();
512
			$property = $postSelect->getResultProperty()->getProperty();
513
			$keys = $postSelect->getKeys();
514
			$resultObject = $postSelect->getResultObject();
515
516
			if($method == self::QUERY_FOR_LIST || $method == self::QUERY_FOR_ARRAY)
517
			{
518
				$values = $statement->executeQueryForList($connection, $keys, null);
519
520
				if($method == self::QUERY_FOR_ARRAY)
521
					$values = $values->toArray();
522
				TPropertyAccess::set($resultObject, $property, $values);
523
			}
524
			else if($method == self::QUERY_FOR_OBJECT)
525
			{
526
				$value = $statement->executeQueryForObject($connection, $keys, null);
527
				TPropertyAccess::set($resultObject, $property, $value);
528
			}
529
		}
530
	}
531
532
	/**
533
	 * Raise the execute query event.
534
	 * @param array prepared SQL statement and subsititution parameters
535
	 */
536
	public function onExecuteQuery($sql)
537
	{
538
		$this->raiseEvent('OnExecuteQuery', $this, $sql);
539
	}
540
541
	/**
542
	 * Apply result mapping.
543
	 * @param array a result set row retrieved from the database
544
	 * @param object the result object, will create if necessary.
545
	 * @return object the result filled with data, null if not filled.
546
	 */
547
	protected function applyResultMap($row, &$resultObject=null)
548
	{
549
		if($row === false) return null;
550
551
		$resultMapName = $this->_statement->getResultMap();
552
		$resultClass = $this->_statement->getResultClass();
553
554
		$obj=null;
0 ignored issues
show
Unused Code introduced by
$obj is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
555
		if($this->getManager()->getResultMaps()->contains($resultMapName))
556
			$obj = $this->fillResultMap($resultMapName, $row, null, $resultObject);
557
		else if(strlen($resultClass) > 0)
558
			$obj = $this->fillResultClass($resultClass, $row, $resultObject);
559
		else
560
			$obj = $this->fillDefaultResultMap(null, $row, $resultObject);
561
		if(class_exists('TActiveRecord',false) && $obj instanceof TActiveRecord)
562
			//Create a new clean active record.
563
			$obj=TActiveRecord::createRecord(get_class($obj),$obj);
564
		return $obj;
565
	}
566
567
	/**
568
	 * Fill the result using ResultClass, will creates new result object if required.
569
	 * @param string result object class name
570
	 * @param array a result set row retrieved from the database
571
	 * @param object the result object, will create if necessary.
572
	 * @return object result object filled with data
573
	 */
574
	protected function fillResultClass($resultClass, $row, $resultObject)
575
	{
576
		if($resultObject===null)
577
		{
578
			$registry = $this->getManager()->getTypeHandlers();
579
			$resultObject = $this->_statement->createInstanceOfResultClass($registry,$row);
580
		}
581
582
		if($resultObject instanceOf ArrayAccess)
583
			return $this->fillResultArrayList($row, $resultObject);
584
		else if(is_object($resultObject))
585
			return $this->fillResultObjectProperty($row, $resultObject);
586
		else
587
			return $this->fillDefaultResultMap(null, $row, $resultObject);
588
	}
589
590
	/**
591
	 * Apply the result to a TList or an array.
592
	 * @param array a result set row retrieved from the database
593
	 * @param object result object, array or list
594
	 * @return object result filled with data.
595
	 */
596
	protected function fillResultArrayList($row, $resultObject)
597
	{
598
		if($resultObject instanceof TList)
599
			foreach($row as $v)
600
				$resultObject[] = $v;
601
		else
602
			foreach($row as $k => $v)
603
				$resultObject[$k] = $v;
604
		return $resultObject;
605
	}
606
607
	/**
608
	 * Apply the result to an object.
609
	 * @param array a result set row retrieved from the database
610
	 * @param object result object, array or list
611
	 * @return object result filled with data.
612
	 */
613
	protected function fillResultObjectProperty($row, $resultObject)
614
	{
615
		$index = 0;
616
		$registry=$this->getManager()->getTypeHandlers();
617
		foreach($row as $k=>$v)
618
		{
619
			$property = new TResultProperty;
620
			if(is_string($k) && strlen($k) > 0)
621
				$property->setColumn($k);
622
			$property->setColumnIndex(++$index);
623
			$type = gettype(TPropertyAccess::get($resultObject,$k));
624
			$property->setType($type);
625
			$value = $property->getPropertyValue($registry,$row);
626
			TPropertyAccess::set($resultObject, $k,$value);
627
		}
628
		return $resultObject;
629
	}
630
631
	/**
632
	 * Fills the result object according to result mappings.
633
	 * @param string result map name.
634
	 * @param array a result set row retrieved from the database
635
	 * @param object result object to fill, will create new instances if required.
636
	 * @return object result object filled with data.
637
	 */
638
	protected function fillResultMap($resultMapName, $row, $parentGroup=null, &$resultObject=null)
639
	{
640
		$resultMap = $this->getManager()->getResultMap($resultMapName);
641
		$registry = $this->getManager()->getTypeHandlers();
642
		$resultMap = $resultMap->resolveSubMap($registry,$row);
643
644
		if($resultObject===null)
645
			$resultObject = $resultMap->createInstanceOfResult($registry);
646
647
		if(is_object($resultObject))
648
		{
649
			if(strlen($resultMap->getGroupBy()) > 0)
650
				return $this->addResultMapGroupBy($resultMap, $row, $parentGroup, $resultObject);
651
			else
652
				foreach($resultMap->getColumns() as $property)
653
					$this->setObjectProperty($resultMap, $property, $row, $resultObject);
654
		}
655
		else
656
		{
657
			$resultObject = $this->fillDefaultResultMap($resultMap, $row, $resultObject);
658
		}
659
		return $resultObject;
660
	}
661
662
	/**
663
	 * ResultMap with GroupBy property. Save object collection graph in a tree
664
	 * and collect the result later.
665
	 * @param TResultMap result mapping details.
666
	 * @param array a result set row retrieved from the database
667
	 * @param object the result object
668
	 * @return object result object.
669
	 */
670
	protected function addResultMapGroupBy($resultMap, $row, $parent, &$resultObject)
671
	{
672
		$group = $this->getResultMapGroupKey($resultMap, $row);
673
674
		if(empty($parent))
675
		{
676
			$rootObject = array('object'=>$resultObject, 'property' => null);
677
			$this->_groupBy->add(null, $group, $rootObject);
678
		}
679
680
		foreach($resultMap->getColumns() as $property)
681
		{
682
			//set properties.
683
			$this->setObjectProperty($resultMap, $property, $row, $resultObject);
684
			$nested = $property->getResultMapping();
685
686
			//nested property
687
			if($this->getManager()->getResultMaps()->contains($nested))
688
			{
689
				$nestedMap = $this->getManager()->getResultMap($nested);
690
				$groupKey = $this->getResultMapGroupKey($nestedMap, $row);
691
692
				//add the node reference first
693
				if(empty($parent))
694
					$this->_groupBy->add($group, $groupKey, '');
695
696
				//get the nested result mapping value
697
				$value = $this->fillResultMap($nested, $row, $groupKey);
698
699
				//add it to the object tree graph
700
				$groupObject = array('object'=>$value, 'property' => $property->getProperty());
701
				if(empty($parent))
702
					$this->_groupBy->add($group, $groupKey, $groupObject);
703
				else
704
					$this->_groupBy->add($parent, $groupKey, $groupObject);
705
			}
706
		}
707
		return $resultObject;
708
	}
709
710
	/**
711
	 * Gets the result 'group by' groupping key for each row.
712
	 * @param TResultMap result mapping details.
713
	 * @param array a result set row retrieved from the database
714
	 * @return string groupping key.
715
	 */
716
	protected function getResultMapGroupKey($resultMap, $row)
717
	{
718
		$groupBy = $resultMap->getGroupBy();
719
		if(isset($row[$groupBy]))
720
			return $resultMap->getID().$row[$groupBy];
721
		else
722
			return $resultMap->getID().crc32(serialize($row));
723
	}
724
725
	/**
726
	 * Fill the result map using default settings. If <tt>$resultMap</tt> is null
727
	 * the result object returned will be guessed from <tt>$resultObject</tt>.
728
	 * @param TResultMap result mapping details.
729
	 * @param array a result set row retrieved from the database
730
	 * @param object the result object
731
	 * @return mixed the result object filled with data.
732
	 */
733
	protected function fillDefaultResultMap($resultMap, $row, $resultObject)
734
	{
735
		if($resultObject===null)
736
			$resultObject='';
737
738
		if($resultMap!==null)
739
			$result = $this->fillArrayResultMap($resultMap, $row, $resultObject);
740
		else
741
			$result = $row;
742
743
		//if scalar result types
744
		if(count($result) == 1 && ($type = gettype($resultObject))!= 'array')
745
			return $this->getScalarResult($result, $type);
746
		else
747
			return $result;
748
	}
749
750
	/**
751
	 * Retrieve the result map as an array.
752
	 * @param TResultMap result mapping details.
753
	 * @param array a result set row retrieved from the database
754
	 * @param object the result object
755
	 * @return array array list of result objects.
756
	 */
757
	protected function fillArrayResultMap($resultMap, $row, $resultObject)
758
	{
759
		$result = array();
760
		$registry=$this->getManager()->getTypeHandlers();
761
		foreach($resultMap->getColumns() as $column)
762
		{
763
			if(($column->getType()===null)
764
				&& ($resultObject!==null) && !is_object($resultObject))
765
			$column->setType(gettype($resultObject));
766
			$result[$column->getProperty()] = $column->getPropertyValue($registry,$row);
767
		}
768
		return $result;
769
	}
770
771
	/**
772
	 * Converts the first array value to scalar value of given type.
773
	 * @param array list of results
774
	 * @param string scalar type.
775
	 * @return mixed scalar value.
776
	 */
777
	protected function getScalarResult($result, $type)
778
	{
779
		$scalar = array_shift($result);
780
		settype($scalar, $type);
781
		return $scalar;
782
	}
783
784
	/**
785
	 * Set a property of the result object with appropriate value.
786
	 * @param TResultMap result mapping details.
787
	 * @param TResultProperty the result property to fill.
788
	 * @param array a result set row retrieved from the database
789
	 * @param object the result object
790
	 */
791
	protected function setObjectProperty($resultMap, $property, $row, &$resultObject)
792
	{
793
		$select = $property->getSelect();
794
		$key = $property->getProperty();
795
		$nested = $property->getNestedResultMap();
796
		$registry=$this->getManager()->getTypeHandlers();
797
		if($key === '')
798
		{
799
			$resultObject = $property->getPropertyValue($registry,$row);
800
		}
801
		else if(strlen($select) == 0 && ($nested===null))
802
		{
803
			$value = $property->getPropertyValue($registry,$row);
804
805
			$this->_IsRowDataFound = $this->_IsRowDataFound || ($value != null);
806
			if(is_array($resultObject) || is_object($resultObject))
807
				TPropertyAccess::set($resultObject, $key, $value);
808
			else
809
				$resultObject = $value;
810
		}
811
		else if($nested!==null)
812
		{
813
			if($property->instanceOfListType($resultObject) || $property->instanceOfArrayType($resultObject))
814
			{
815
				if(strlen($resultMap->getGroupBy()) <= 0)
816
					throw new TSqlMapExecutionException(
817
						'sqlmap_non_groupby_array_list_type', $resultMap->getID(),
818
						get_class($resultObject), $key);
819
			}
820
			else
821
			{
822
				$obj = $nested->createInstanceOfResult($this->getManager()->getTypeHandlers());
823
				if($this->fillPropertyWithResultMap($nested, $row, $obj) == false)
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
824
					$obj = null;
825
				TPropertyAccess::set($resultObject, $key, $obj);
826
			}
827
		}
828
		else //'select' ResultProperty
829
		{
830
			$this->enquequePostSelect($select, $resultMap, $property, $row, $resultObject);
831
		}
832
	}
833
834
	/**
835
	 * Add nested result property to post select queue.
836
	 * @param string post select statement ID
837
	 * @param TResultMap current result mapping details.
838
	 * @param TResultProperty current result property.
839
	 * @param array a result set row retrieved from the database
840
	 * @param object the result object
841
	 */
842
	protected function enquequePostSelect($select, $resultMap, $property, $row, $resultObject)
843
	{
844
		$statement = $this->getManager()->getMappedStatement($select);
845
		$key = $this->getPostSelectKeys($resultMap, $property, $row);
846
		$postSelect = new TPostSelectBinding;
847
		$postSelect->setStatement($statement);
848
		$postSelect->setResultObject($resultObject);
849
		$postSelect->setResultProperty($property);
850
		$postSelect->setKeys($key);
851
852
		if($property->instanceOfListType($resultObject))
853
		{
854
			$values = null;
0 ignored issues
show
Unused Code introduced by
$values is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
855
			if($property->getLazyLoad())
856
			{
857
				$values = TLazyLoadList::newInstance($statement, $key,
858
								$resultObject, $property->getProperty());
859
				TPropertyAccess::set($resultObject, $property->getProperty(), $values);
860
			}
861
			else
862
				$postSelect->setMethod(self::QUERY_FOR_LIST);
863
		}
864
		else if($property->instanceOfArrayType($resultObject))
865
			$postSelect->setMethod(self::QUERY_FOR_ARRAY);
866
		else
867
			$postSelect->setMethod(self::QUERY_FOR_OBJECT);
868
869
		if(!$property->getLazyLoad())
870
			$this->_selectQueue[] = $postSelect;
871
	}
872
873
	/**
874
	 * Finds in the post select property the SQL statement primary selection keys.
875
	 * @param TResultMap result mapping details
876
	 * @param TResultProperty result property
877
	 * @param array current row data.
878
	 * @return array list of primary key values.
879
	 */
880
	protected function getPostSelectKeys($resultMap, $property,$row)
881
	{
882
		$value = $property->getColumn();
883
		if(is_int(strpos($value.',',0)) || is_int(strpos($value, '=',0)))
884
		{
885
			$keys = array();
886
			foreach(explode(',', $value) as $entry)
887
			{
888
				$pair =explode('=',$entry);
889
				$keys[trim($pair[0])] = $row[trim($pair[1])];
890
			}
891
			return $keys;
892
		}
893
		else
894
		{
895
			$registry=$this->getManager()->getTypeHandlers();
896
			return $property->getPropertyValue($registry,$row);
897
		}
898
	}
899
900
	/**
901
	 * Fills the property with result mapping results.
902
	 * @param TResultMap nested result mapping details.
903
	 * @param array a result set row retrieved from the database
904
	 * @param object the result object
905
	 * @return boolean true if the data was found, false otherwise.
906
	 */
907
	protected function fillPropertyWithResultMap($resultMap, $row, &$resultObject)
908
	{
909
		$dataFound = false;
910
		foreach($resultMap->getColumns() as $property)
911
		{
912
			$this->_IsRowDataFound = false;
913
			$this->setObjectProperty($resultMap, $property, $row, $resultObject);
914
			$dataFound = $dataFound || $this->_IsRowDataFound;
915
		}
916
		$this->_IsRowDataFound = $dataFound;
917
		return $dataFound;
918
	}
919
920
	public function __wakeup()
921
	{
922
		parent::__wakeup();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class TComponent as the method __wakeup() does only exist in the following sub-classes of TComponent: ActiveAccount, AddressRecord, Album, Artist, BaseFkRecord, BaseRecordTest, Blogs, Category, ChatBufferRecord, ChatUserRecord, Cover, Customer, DepSections, DepartmentRecord, Employee, ItemRecord, MultipleFKSqliteRecord, Order, OrderDetail, PlayerRecord, PostRecord, Product, ProfileRecord, Region, Shipper, SimpleUser, SkillRecord, SqlTest, SqliteRecord, SqliteUsers, Supplier, TActiveRecord, TDeleteMappedStatement, TInsertMappedStatement, TMappedStatement, TSelectMappedStatement, TUpdateMappedStatement, Table1, Table2, TeamRecord, Territory, Track, UserRecord, UserRecord2. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
923
		if (is_null($this->_selectQueue)) $this->_selectQueue = array();
924
	}
925
926
	public function __sleep()
927
	{
928
		$exprops = array(); $cn = __CLASS__;
0 ignored issues
show
Coding Style introduced by
It is generally recommended to place each PHP statement on a line by itself.

Let’s take a look at an example:

// Bad
$a = 5; $b = 6; $c = 7;

// Good
$a = 5;
$b = 6;
$c = 7;
Loading history...
929
		if (!count($this->_selectQueue)) $exprops[] = "\0$cn\0_selectQueue";
930
		if (is_null($this->_groupBy)) $exprops[] = "\0$cn\0_groupBy";
931
		if (!$this->_IsRowDataFound) $exprops[] = "\0$cn\0_IsRowDataFound";
932
		return array_diff(parent::__sleep(),$exprops);
933
	}
934
}
935
936
/**
937
 * TPostSelectBinding class.
938
 *
939
 * @author Wei Zhuo <weizho[at]gmail[dot]com>
940
 * @package System.Data.SqlMap.Statements
941
 * @since 3.1
942
 */
943
class TPostSelectBinding
944
{
945
	private $_statement=null;
946
	private $_property=null;
947
	private $_resultObject=null;
948
	private $_keys=null;
949
	private $_method=TMappedStatement::QUERY_FOR_LIST;
950
951
	public function getStatement(){ return $this->_statement; }
952
	public function setStatement($value){ $this->_statement = $value; }
953
954
	public function getResultProperty(){ return $this->_property; }
955
	public function setResultProperty($value){ $this->_property = $value; }
956
957
	public function getResultObject(){ return $this->_resultObject; }
958
	public function setResultObject($value){ $this->_resultObject = $value; }
959
960
	public function getKeys(){ return $this->_keys; }
961
	public function setKeys($value){ $this->_keys = $value; }
962
963
	public function getMethod(){ return $this->_method; }
964
	public function setMethod($value){ $this->_method = $value; }
965
}
966
967
/**
968
 * TSQLMapObjectCollectionTree class.
969
 *
970
 * Maps object collection graphs as trees. Nodes in the collection can
971
 * be {@link add} using parent relationships. The object collections can be
972
 * build using the {@link collect} method.
973
 *
974
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
975
 * @package System.Data.SqlMap.Statements
976
 * @since 3.1
977
 */
978
class TSqlMapObjectCollectionTree extends TComponent
979
{
980
	/**
981
	 * @var array object graph as tree
982
	 */
983
	private $_tree = array();
984
	/**
985
	 * @var array tree node values
986
	 */
987
	private $_entries = array();
988
	/**
989
	 * @var array resulting object collection
990
	 */
991
	private $_list = array();
992
993
	/**
994
	 * @return boolean true if the graph is empty
995
	 */
996
	public function isEmpty()
997
	{
998
		return count($this->_entries) == 0;
999
	}
1000
1001
	/**
1002
	 * Add a new node to the object tree graph.
1003
	 * @param string parent node id
1004
	 * @param string new node id
1005
	 * @param mixed node value
1006
	 */
1007
	public function add($parent, $node, $object='')
1008
	{
1009
		if(isset($this->_entries[$parent]) && ($this->_entries[$parent]!==null)
1010
			&& isset($this->_entries[$node]) && ($this->_entries[$node]!==null))
1011
		{
1012
			$this->_entries[$node] = $object;
1013
			return;
1014
		}
1015
		$this->_entries[$node] = $object;
1016
		if(empty($parent))
1017
		{
1018
			if(isset($this->_entries[$node]))
1019
				return;
1020
			$this->_tree[$node] = array();
1021
		}
1022
		$found = $this->addNode($this->_tree, $parent, $node);
1023
		if(!$found && !empty($parent))
1024
		{
1025
			$this->_tree[$parent] = array();
1026
			if(!isset($this->_entries[$parent]) || $object !== '')
1027
				$this->_entries[$parent] = $object;
1028
			$this->addNode($this->_tree, $parent, $node);
1029
		}
1030
	}
1031
1032
	/**
1033
	 * Find the parent node and add the new node as its child.
1034
	 * @param array list of nodes to check
1035
	 * @param string parent node id
1036
	 * @param string new node id
1037
	 * @return boolean true if parent node is found.
1038
	 */
1039
	protected function addNode(&$childs, $parent, $node)
1040
	{
1041
		$found = false;
1042
		reset($childs);
1043
		for($i = 0, $k = count($childs); $i < $k; $i++)
1044
		{
1045
			$key = key($childs);
1046
			next($childs);
1047
			if($key == $parent)
1048
			{
1049
				$found = true;
1050
				$childs[$key][$node] = array();
1051
			}
1052
			else
1053
			{
1054
				$found = $found || $this->addNode($childs[$key], $parent, $node);
1055
			}
1056
		}
1057
		return $found;
1058
	}
1059
1060
	/**
1061
	 * @return array object collection
1062
	 */
1063
	public function collect()
1064
	{
1065
		while(count($this->_tree) > 0)
1066
			$this->collectChildren(null, $this->_tree);
1067
		return $this->getCollection();
1068
	}
1069
1070
	/**
1071
	 * @param array list of nodes to check
1072
	 * @return boolean true if all nodes are leaf nodes, false otherwise
1073
	 */
1074
	protected function hasChildren(&$nodes)
1075
	{
1076
		$hasChildren = false;
1077
		foreach($nodes as $node)
1078
			if(count($node) != 0)
1079
				return true;
1080
		return $hasChildren;
1081
	}
1082
1083
	/**
1084
	 * Visit all the child nodes and collect them by removing.
1085
	 * @param string parent node id
1086
	 * @param array list of child nodes.
1087
	 */
1088
	protected function collectChildren($parent, &$nodes)
1089
	{
1090
		$noChildren = !$this->hasChildren($nodes);
1091
		$childs = array();
1092
		for(reset($nodes); $key = key($nodes);)
1093
		{
1094
			next($nodes);
1095
			if($noChildren)
1096
			{
1097
				$childs[] = $key;
1098
				unset($nodes[$key]);
1099
			}
1100
			else
1101
				$this->collectChildren($key, $nodes[$key]);
1102
		}
1103
		if(count($childs) > 0)
1104
			$this->onChildNodesVisited($parent, $childs);
1105
	}
1106
1107
	/**
1108
	 * Set the object properties for all the child nodes visited.
1109
	 * @param string parent node id
1110
	 * @param array list of child nodes visited.
1111
	 */
1112
	protected function onChildNodesVisited($parent, $nodes)
1113
	{
1114
		if(empty($parent) || empty($this->_entries[$parent]))
1115
			return;
1116
1117
		$parentObject = $this->_entries[$parent]['object'];
1118
		$property = $this->_entries[$nodes[0]]['property'];
1119
1120
		$list = TPropertyAccess::get($parentObject, $property);
1121
1122
		foreach($nodes as $node)
1123
		{
1124
			if($list instanceof TList)
1125
				$parentObject->{$property}[] = $this->_entries[$node]['object'];
1126
			else if(is_array($list))
1127
				$list[] = $this->_entries[$node]['object'];
1128
			else
1129
				throw new TSqlMapExecutionException(
1130
					'sqlmap_property_must_be_list');
1131
		}
1132
1133
		if(is_array($list))
1134
			TPropertyAccess::set($parentObject, $property, $list);
1135
1136
		if($this->_entries[$parent]['property'] === null)
1137
			$this->_list[] = $parentObject;
1138
	}
1139
1140
	/**
1141
	 * @return array object collection.
1142
	 */
1143
	protected function getCollection()
1144
	{
1145
		return $this->_list;
1146
	}
1147
1148
	public function __sleep()
1149
	{
1150
		$exprops = array(); $cn = __CLASS__;
0 ignored issues
show
Coding Style introduced by
It is generally recommended to place each PHP statement on a line by itself.

Let’s take a look at an example:

// Bad
$a = 5; $b = 6; $c = 7;

// Good
$a = 5;
$b = 6;
$c = 7;
Loading history...
1151
		if (!count($this->_tree)) $exprops[] = "\0$cn\0_tree";
1152
		if (!count($this->_entries)) $exprops[] = "\0$cn\0_entries";
1153
		if (!count($this->_list)) $exprops[] = "\0$cn\0_list";
1154
		return array_diff(parent::__sleep(),$exprops);
1155
	}
1156
}
1157
1158
/**
1159
 * TResultSetListItemParameter class
1160
 *
1161
 * @author Wei Zhuo <weizho[at]gmail[dot]com>
1162
 * @package System.Data.SqlMap.Statements
1163
 * @since 3.1
1164
 */
1165
class TResultSetListItemParameter extends TComponent
1166
{
1167
	private $_resultObject;
1168
	private $_parameterObject;
1169
	private $_list;
1170
1171
	public function __construct($result, $parameter, &$list)
1172
	{
1173
		$this->_resultObject = $result;
1174
		$this->_parameterObject = $parameter;
1175
		$this->_list = &$list;
1176
	}
1177
1178
	public function getResult()
1179
	{
1180
		return $this->_resultObject;
1181
	}
1182
1183
	public function getParameter()
1184
	{
1185
		return $this->_parameterObject;
1186
	}
1187
1188
	public function &getList()
1189
	{
1190
		return $this->_list;
1191
	}
1192
}
1193
1194
/**
1195
 * TResultSetMapItemParameter class.
1196
 *
1197
 * @author Wei Zhuo <weizho[at]gmail[dot]com>
1198
 * @package System.Data.SqlMap.Statements
1199
 * @since 3.1
1200
 */
1201
class TResultSetMapItemParameter extends TComponent
1202
{
1203
	private $_key;
1204
	private $_value;
1205
	private $_parameterObject;
1206
	private $_map;
1207
1208
	public function __construct($key, $value, $parameter, &$map)
1209
	{
1210
		$this->_key = $key;
1211
		$this->_value = $value;
1212
		$this->_parameterObject = $parameter;
1213
		$this->_map = &$map;
1214
	}
1215
1216
	public function getKey()
1217
	{
1218
		return $this->_key;
1219
	}
1220
1221
	public function getValue()
1222
	{
1223
		return $this->_value;
1224
	}
1225
1226
	public function getParameter()
1227
	{
1228
		return $this->_parameterObject;
1229
	}
1230
1231
	public function &getMap()
1232
	{
1233
		return $this->_map;
1234
	}
1235
}
1236
1237